/************************************************************************* * 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 CNSTREAM_CORE_LOGGING_HPP_ #define CNSTREAM_CORE_LOGGING_HPP_ #include #include #include #include #include /** * @brief Log filter. * * Usage: * 1 ./app --log_filter=SOURCE:2,INFERENCE:3 ... * 2 export CNSTREAM_log_filter=SOURCE:2,INFERENCE:3 ... */ DECLARE_string(log_filter); /** * @brief Min category log level, default LOG_INFO */ DECLARE_int32(min_log_level); /** * @brief Flush log file time, in second, default 30s */ DECLARE_int32(flush_log_file_secs); /** * @brief Log messages go to stderr, default true */ DECLARE_bool(log_to_stderr); /** * @brief Log messages go to log file, default false */ DECLARE_bool(log_to_file); #define STR(src) #src #define LOGF(category) \ cnstream::LogMessage(STR(category), __FILE__, __LINE__, cnstream::LogSeverity::LOG_FATAL).stream() #define LOGF_IF(category, condition) \ !(condition) ? (void) 0 : cnstream::LogMessageVoidify() & LOGF(category) #define LOGE(category) \ cnstream::LogMessage(STR(category), __FILE__, __LINE__, cnstream::LogSeverity::LOG_ERROR).stream() #define LOGE_IF(category, condition) \ !(condition) ? (void) 0 : cnstream::LogMessageVoidify() & LOGE(category) #define LOGW(category) \ cnstream::LogMessage(STR(category), __FILE__, __LINE__, cnstream::LogSeverity::LOG_WARNING).stream() #define LOGW_IF(category, condition) \ !(condition) ? (void) 0 : cnstream::LogMessageVoidify() & LOGW(category) #define LOGI(category) cnstream::LogMessage(STR(category), __FILE__, __LINE__, cnstream::LogSeverity::LOG_INFO).stream() #define LOGI_IF(category, condition) \ !(condition) ? (void) 0 : cnstream::LogMessageVoidify() & LOGI(category) #define LOGD(category) \ cnstream::LogMessage(STR(category), __FILE__, __LINE__, cnstream::LogSeverity::LOG_DEBUG).stream() #define LOGD_IF(category, condition) \ !(condition) ? (void) 0 : cnstream::LogMessageVoidify() & LOGD(category) #define LOGT(category) \ cnstream::LogMessage(STR(category), __FILE__, __LINE__, cnstream::LogSeverity::LOG_TRACE).stream() #define LOGT_IF(category, condition) \ !(condition) ? (void) 0 : cnstream::LogMessageVoidify() & LOGT(category) #define LOGA(category) cnstream::LogMessage(STR(category), __FILE__, __LINE__, cnstream::LogSeverity::LOG_ALL).stream() #define LOGA_IF(category, condition) \ !(condition) ? (void) 0 : cnstream::LogMessageVoidify() & LOGA(category) namespace cnstream { /** * @brief log severity * 0, FATAL * 1, ERROR * 2, WARNING * 3, INFO * 4, DEBUG * 5, TRACE * 6, ALL */ enum class 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 void InitCNStreamLogging(const char* log_dir); void AddLogSink(LogSink* log_sink); void RemoveLogSink(LogSink* log_sink); void ShutdownCNStreamLogging(); } // namespace cnstream #endif // CNSTREAM_CORE_LOGGING_HPP_