196 lines
5.1 KiB
C++
196 lines
5.1 KiB
C++
/**
|
|
* 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 <atomic>
|
|
#include <condition_variable>
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <mutex>
|
|
#include <queue>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <sys/syscall.h>
|
|
#include <thread>
|
|
#include <unistd.h>
|
|
|
|
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<LogLevel, std::string> 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<microseconds>(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<LogMessage> &pLogMessage);
|
|
void Stop();
|
|
|
|
static Logger &GetInstance()
|
|
{
|
|
static Logger instance;
|
|
return instance;
|
|
}
|
|
|
|
private:
|
|
Logger() = default;
|
|
void LogWorker();
|
|
|
|
private:
|
|
std::queue<std::shared_ptr<LogMessage>> m_CacheQueue;
|
|
std::mutex m_CacheQueueMutex;
|
|
std::condition_variable m_CacheQueueCV;
|
|
std::unique_ptr<std::thread> m_OutputThread = nullptr;
|
|
std::atomic<bool> m_bStopFlag = {false};
|
|
std::atomic<bool> 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<LogMessage> pLogMessage = std::make_shared<LogMessage>();
|
|
pLogMessage->level = m_LogLevel;
|
|
pLogMessage->message = sFormatBuffer.str();
|
|
|
|
Logger::GetInstance().EnqueueMsg(pLogMessage);
|
|
}
|
|
}
|
|
|
|
template <typename T> 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
|