/** * Filename drsdk_log.h * Copyright Shanghai Baosight Software Co., Ltd. * Description The logging component used internally in dsfapi * * Author wuzheqiang * Version 12/19/2024 wuzheqiang Initial Version **************************************************************/ #ifndef DRSDK_LOG_H #define DRSDK_LOG_H #include "data_types.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace dsfapi { #define THREAD_ID syscall(SYS_gettid) #define RESET "\033[0m" #define RED "\033[31m" /* Red */ #define YELLOW "\033[33m" /* Yellow */ enum LogLevel : uint8 { DEBUG, INFO, ERROR, log_level_max }; static std::map g_LogLevelStr = { {LogLevel::DEBUG, "DEBUG"}, {LogLevel::INFO, "INFO"}, {LogLevel::ERROR, "ERROR"}, }; enum OutputMethod : uint8 { NONE = 0x00, // 0b00000000 TERMINAL = 0x01, // 0b00000001 FILE = 0x02, // 0b00000010 BOTH = 0x03, // 0b00000011 output_method_max }; inline std::string CurrentTimestampMicro(int type = 0) { using namespace std::chrono; auto now = system_clock::now(); auto in_time_t = system_clock::to_time_t(now); auto us = duration_cast(now.time_since_epoch()) % 1000000; std::tm buf; localtime_r(&in_time_t, &buf); std::ostringstream oss; switch (type) { case 0: { char timeStr[100] = {}; std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &buf); oss << timeStr; oss << '.' << std::setfill('0') << std::setw(6) << us.count(); break; } case 1: { char timeStr[100] = {}; std::strftime(timeStr, sizeof(timeStr), "%Y%m%d%H%M%S", &buf); oss << timeStr; break; } default: { char timeStr[100] = {}; std::strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &buf); oss << timeStr; break; } } return oss.str(); } struct LogMessage { LogLevel level = LogLevel::INFO; std::string message = ""; }; class Logger { public: ~Logger(); int32 Init(const LogLevel eLogLevel, const OutputMethod eOutPutMethod, const std::string &strLogPath = ""); LogLevel GetLogLevel() const; void EnqueueMsg(const std::shared_ptr &pLogMessage); void Stop(); static Logger &GetInstance() { static Logger instance; return instance; } private: Logger() = default; void LogWorker(); private: std::queue> m_CacheQueue; std::mutex m_CacheQueueMutex; std::condition_variable m_CacheQueueCV; std::unique_ptr m_OutputThread = nullptr; std::atomic m_bStopFlag = {false}; std::atomic m_bInitFlag = {false}; OutputMethod m_OutputMethod = OutputMethod::TERMINAL; std::ofstream m_LogStream; std::string m_strLogFile = ""; LogLevel m_LogLevel = LogLevel::INFO; }; class LogStream { public: LogStream(LogLevel loglevel, const char *filename, const char *funcname, uint32 line) : m_LogLevel(loglevel), m_nLine(line) { m_sFileName = std::string(filename).substr(std::string(filename).find_last_of("/\\") + 1); m_sFuncName = std::string(funcname); m_sBuffer.clear(); m_SdkLogLevel = Logger::GetInstance().GetLogLevel(); } ~LogStream() { if (!m_sBuffer.str().empty()) { std::ostringstream sFormatBuffer; sFormatBuffer << "[" << dsfapi::CurrentTimestampMicro() << "][" << g_LogLevelStr[m_LogLevel] << "][" << THREAD_ID << "][" << m_sFileName << ":" << m_nLine << ":" << m_sFuncName << "]" << m_sBuffer.str(); std::shared_ptr pLogMessage = std::make_shared(); pLogMessage->level = m_LogLevel; pLogMessage->message = sFormatBuffer.str(); Logger::GetInstance().EnqueueMsg(pLogMessage); } } template LogStream &operator<<(const T &msg) { if (m_LogLevel >= m_SdkLogLevel) { m_sBuffer << msg; } return *this; } // for std::endl,std::flush LogStream &operator<<(std::ostream &(*pf)(std::ostream &)) { if (m_LogLevel >= m_SdkLogLevel) { // Not processing; When the final output , std::endl will be added; // pf(m_sBuffer); } return *this; } private: LogLevel m_LogLevel = LogLevel::INFO; std::string m_sFileName = ""; std::string m_sFuncName = ""; uint32 m_nLine = 0; std::ostringstream m_sBuffer; LogLevel m_SdkLogLevel = LogLevel::INFO; }; #define LOG_DEBUG dsfapi::LogStream(dsfapi::LogLevel::DEBUG, __FILE__, __func__, __LINE__) #define LOG_INFO dsfapi::LogStream(dsfapi::LogLevel::INFO, __FILE__, __func__, __LINE__) #define LOG_ERR dsfapi::LogStream(dsfapi::LogLevel::ERROR, __FILE__, __func__, __LINE__) } // namespace dsfapi #endif // DRSDK_LOG_H