123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- /*************************************************************************
- * Copyright (C) 2019 by Cambricon, Inc. All rights reserved
- *
- * This source code is licensed under the Apache-2.0 license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * A part of this source code is referenced from glog project.
- * https://github.com/google/glog/blob/master/src/logging.cc
- *
- * Copyright (c) 1999, Google Inc.
- *
- * This source code is licensed under the BSD 3-Clause license found in the
- * LICENSE file in the root directory of this source tree.
- *
- *************************************************************************/
- #ifndef EDK_CXXUTIL_LOG_H_
- #define EDK_CXXUTIL_LOG_H_
- #include <string>
- #include <streambuf>
- #include <ostream>
- /*
- * Log filter.
- *
- * Environment variable: EDK_LOG_FILTER
- * Default: ""
- *
- * Usage:
- * export EDK_LOG_FILTER=BANG:2,DEVICE:3 ...
- */
- /*
- * Min category log level
- *
- * Environment variable: EDK_LOG_LEVEL
- * Default: 2 (LOG_WARNING)
- */
- #define STRINGIFY(src) #src
- #define _EDK_LOG_IS_ON(cate, sev) edk::log::LogActivated(STRINGIFY(cate), sev)
- #define _EDK_LOG_STREAM(cate, sev) edk::log::LogMessage(STRINGIFY(cate), __FILE__, __LINE__, sev).stream()
- #define _EDK_LOG(cate, sev) \
- !(_EDK_LOG_IS_ON(cate, sev)) ? (void)0 : edk::log::LogMessageVoidify() & _EDK_LOG_STREAM(cate, sev)
- #define _EDK_LOG_IF(cate, sev, condition) \
- !(_EDK_LOG_IS_ON(cate, sev) && (condition)) ? (void)0 : edk::log::LogMessageVoidify() & _EDK_LOG_STREAM(cate, sev)
- #define _EDK_LOG_CONCAT(lhs, rhs) lhs##_##rhs
- #define _EDK_LOG_COUNTER_NAME(name, line) _EDK_LOG_CONCAT(name, line)
- #define _EDK_LOG_COUNTER _EDK_LOG_COUNTER_NAME(_log_counter, __LINE__)
- #define LOG_EVERY_N(category, severity, N) \
- static int _EDK_LOG_COUNTER = 0; \
- ++_EDK_LOG_COUNTER > N ? _EDK_LOG_COUNTER -= N : 0; \
- _EDK_LOG_IF(category, edk::log::severity, (_EDK_LOG_COUNTER == 1))
- #define LOG_FIRST_N(category, severity, N) \
- static int _EDK_LOG_COUNTER = 0; \
- ++_EDK_LOG_COUNTER > N + 1 ? --_EDK_LOG_COUNTER : 0; \
- _EDK_LOG_IF(category, edk::log::severity, (_EDK_LOG_COUNTER <= N))
- // LOGF is on regardless of severity
- #define LOGF(category) _EDK_LOG_STREAM(category, edk::log::LOG_FATAL)
- #define LOGF_IF(category, condition) \
- !(condition) ? (void)0 : edk::log::LogMessageVoidify() & _EDK_LOG_STREAM(category, edk::log::LOG_FATAL)
- #define LOGE(category) _EDK_LOG(category, edk::log::LOG_ERROR)
- #define LOGE_IF(category, condition) _EDK_LOG_IF(category, edk::log::LOG_ERROR, condition)
- #define LOGW(category) _EDK_LOG(category, edk::log::LOG_WARNING)
- #define LOGW_IF(category, condition) _EDK_LOG_IF(category, edk::log::LOG_WARNING, condition)
- #define LOGI(category) _EDK_LOG(category, edk::log::LOG_INFO)
- #define LOGI_IF(category, condition) _EDK_LOG_IF(category, edk::log::LOG_INFO, condition)
- #define LOGD(category) _EDK_LOG(category, edk::log::LOG_DEBUG)
- #define LOGD_IF(category, condition) _EDK_LOG_IF(category, edk::log::LOG_DEBUG, condition)
- #define LOGT(category) _EDK_LOG(category, edk::log::LOG_TRACE)
- #define LOGT_IF(category, condition) _EDK_LOG_IF(category, edk::log::LOG_TRACE, condition)
- #define LOGA(category) _EDK_LOG(category, edk::log::LOG_ALL)
- #define LOGA_IF(category, condition) _EDK_LOG_IF(category, edk::log::LOG_ALL, condition)
- #define CHECK(category, condition) \
- LOGF_IF((category), !(condition)) << "Check condition (" << STRINGIFY(condition) ") failed"
- namespace edk {
- namespace log {
- /**
- * @brief log severity
- * 0, FATAL
- * 1, LOG_ERROR
- * 2, WARNING
- * 3, INFO
- * 4, DEBUG
- * 5, TRACE
- * 6, ALL
- */
- enum LogSeverity {
- LOG_FATAL = 0,
- LOG_ERROR,
- LOG_WARNING,
- LOG_INFO,
- LOG_DEBUG,
- LOG_TRACE,
- LOG_ALL
- };
- class LogSink {
- public:
- virtual ~LogSink() { }
- virtual void Send(LogSeverity severity, const char* category,
- const char* filename, int line,
- const struct ::tm* tm_time, int32_t usecs,
- const char* message, size_t message_len) = 0;
- virtual void WaitTillSent() { } // noop default
- static std::string ToString(LogSeverity severity, const char* category,
- const char* filename, int line,
- const struct ::tm* tm_time, int32_t usecs,
- const char* message, size_t message_len);
- }; // class LogSink
- class LogMessageVoidify {
- public:
- LogMessageVoidify() { }
- // This has to be an operator with a precedence lower than << but
- // higher than ?:
- void operator&(std::ostream&) { }
- };
- class LogMessage {
- public:
- class LogStreamBuf : public std::streambuf {
- public:
- // REQUIREMENTS: "len" must be >= 2 to account for the '\n' and '\0'.
- LogStreamBuf(char *buf, int len) {
- setp(buf, buf + len - 2);
- }
- // This effectively ignores overflow.
- virtual int_type overflow(int_type ch) {
- return ch;
- }
- // Legacy public ostrstream method.
- size_t pcount() const { return pptr() - pbase(); }
- char* pbase() const { return std::streambuf::pbase(); }
- }; // class LogStreamBuf
- class LogStream : public std::ostream {
- public:
- LogStream(char *buf, int len)
- : std::ostream(NULL),
- streambuf_(buf, len) {
- rdbuf(&streambuf_);
- }
- // Legacy std::streambuf methods.
- size_t pcount() const { return streambuf_.pcount(); }
- char* pbase() const { return streambuf_.pbase(); }
- char* str() const { return pbase(); }
- private:
- LogStream(const LogStream&) = delete;
- LogStream& operator=(const LogStream&) = delete;
- LogStreamBuf streambuf_;
- }; // class LogStream
- LogMessage(const char* category, const char* file, int line, LogSeverity severity);
- ~LogMessage();
- void Init(const char* category, const char* file, int line, LogSeverity severity);
- std::ostream& stream();
- struct LogMessageData;
- private:
- LogMessage(const LogMessage&) = delete;
- LogMessage& operator=(const LogMessage&) = delete;
- void Flush();
- void SendToLog();
- LogMessageData* data_;
- LogMessageData* allocated_;
- static const size_t MaxLogMsgLen;
- }; // class LogMessage
- namespace detail {
- bool CategoryActivated(const char* category, LogSeverity severity) noexcept;
- } // namespace detail
- extern const int g_min_log_level;
- extern const bool g_enable_category_filter;
- inline bool LogActivated(const char* category, LogSeverity severity) noexcept {
- if (g_enable_category_filter) {
- return detail::CategoryActivated(category, severity);
- }
- return g_min_log_level >= severity;
- }
- /**
- * @brief Init log system
- *
- * @note Only log to stderr as default if not init
- *
- * @param log_to_stderr Log messages go to stderr
- * @param log_to_file Log messages go to log file
- * @param log_dir Directory to store log file
- */
- void InitLogging(bool log_to_stderr, bool log_to_file, const std::string& log_dir = "") noexcept;
- /**
- * @brief Shutdown log output
- */
- void ShutdownLogging() noexcept;
- /**
- * @brief Flush log file interval, in second
- *
- * @note Using 30s as default if not set
- *
- * @param time Flush interval
- */
- void SetFileFlushInterval(uint32_t time) noexcept;
- /**
- * @brief Add customized log sink to logger
- *
- * @param log_sink Customized log sink
- */
- void AddLogSink(LogSink* log_sink) noexcept;
- /**
- * @brief Remove customized log sink
- *
- * @param log_sink Customized log sink
- */
- void RemoveLogSink(LogSink* log_sink) noexcept;
- } // namespace log
- } // namespace edk
- #endif // EDK_CXXUTIL_LOG_H_
|