水平太菜,最近捣鼓这个 log,折腾了好一会。由于之前都是用 std::cout,不能满足同时输出到屏与文件的目的,故经过一番搜索,在stackoverflow 找到了答案,现总结如下:
头文件 logger.hpp, 代码如下:
#ifndef __LOGGER
#define __LOGGER
#include
#include
#include
#include
#include
#include
typedef enum
{
EMERG = LOG_EMERG, /* system is unusable /
ALERT = LOG_ALERT, / action must be taken immediately /
CRIT = LOG_CRIT, / critical conditions /
ERROR = LOG_ERR, / error conditions /
WARNING = LOG_WARNING, / warning conditions /
NOTICE = LOG_NOTICE, / normal but significant condition /
INFO = LOG_INFO, / informational /
DEBUG = LOG_DEBUG / debug-level messages */
} Severity;
static std::string severity_str[] = {
[EMERG] = "EMERG", /* system is unusable /
[ALERT] = "ALERT", / action must be taken immediately /
[CRIT] = "CRIT", / critical conditions /
[ERROR] = "ERROR", / error conditions /
[WARNING] = "WARNING", / warning conditions /
[NOTICE] = "NOTICE,", / normal but significant condition /
[INFO] = "INFO", / informational /
[DEBUG] = "DEBUG", / debug-level messages */
};
class Logger
{
private:
Logger() {}
~Logger() {}
/* forbide copy */
Logger &operator=(const Logger &) = delete;
Logger(const Logger &) = delete;
private:
static Severity m_log_level; /* only show log that with level
not higher than m_log_level /
static bool m_sync_syslog; / sync log to syslog ? /
static bool m_sync_stdout; / sync log to stdout /
static bool m_sync_file; / sync log to file /
static std::string m_logfile; / file to save log */
static Severity m_severity;
static std::string m_filename;
static int m_line;
static std::string m_funcname;
std::stringstream ss;
std::mutex m_lk;
public:
static Logger &Instance(Severity s = Severity::INFO,
const char *f = "", int l = 0,
const char *fc = "")
{
static Logger instance_;
instance_.m_severity = s;
instance_.m_filename = f;
instance_.m_line = l;
instance_.m_funcname = fc;
return instance_;
}
static void Init(bool sync_flag, const char *logfile)
{
m_sync_file = sync_flag;
m_logfile = logfile;
}
static void Init(bool sync_stdout, bool sync_file, bool sync_syslog)
{
m_sync_file = sync_file;
m_sync_stdout = sync_stdout;
m_sync_syslog = sync_syslog;
}
static void Init(const char *label = "LOGGER",
Severity s = Severity::INFO,
bool sync_syslog = false)
{
m_log_level = s;
if (sync_syslog)
{
m_sync_syslog = true;
openlog(label, LOG_CONS | LOG_NDELAY, LOG_USER | LOG_LOCAL1);
}
}
Logger &operator<<(const char *t)
{
std::lock_guard<std::mutex> _lk(m_lk);
ss << t;
return *this;
}
template <typename T>
Logger &operator<<(const T &t)
{
std::lock_guard<std::mutex> _lk(m_lk);
ss << t;
return *this;
}
Logger &operator<<(std::ostream &(*os)(std::ostream &))
{
dump_line();
return *this;
}
void dump_line()
{
std::lock_guard<std::mutex> _lk(m_lk);
time_t rawtime;
char now[80];time(&rawtime);
struct tm *tt = localtime(&rawtime);
strftime(now, 80, "%Y-%m-%d %H:%M:%S", tt);
std::string obuf = "";
if (!m_filename.empty())
{
obuf += "[" + m_filename + ":" +
std::to_string(m_line) + " " +
m_funcname + "]";
}
obuf += "[" + std::string(now) + "][" +
severity_str[static_cast<int>(m_severity)] + "] ";
obuf += ss.str();
if (m_log_level >= m_severity)
{
/* syslog */
if (m_sync_syslog)
syslog(LOG_USER | m_severity, "%s", obuf.c_str());
/* stdout/stderr */
if (m_sync_stdout)
std::cerr << obuf << std::endl;
if (m_sync_file)
{
std::ofstream fout(m_logfile, std::ios::app);
fout.write(obuf.c_str(), obuf.length());
fout.close();
}
}
ss.str("");
m_funcname = "";
m_filename = "";
m_line = 0;
}
template <typename T>
void operator()(T t)
{
ss << t;
dump_line();
}
template <typename T, typename... Args>
void operator()(const T &t, const Args &... args)
{
ss << t;
(*this)(args...);
}
};
#define ENDL std::endl
#ifndef NDEBUG
#define LOG(v) Logger::Instance(v, FILE, LINE, func)
#define LOGI Logger::Instance(Severity::INFO, FILE, LINE, func)
#define LOGV Logger::Instance(Severity::NOTICE, FILE, LINE, func)
#define LOGD Logger::Instance(Severity::DEBUG, FILE, LINE, func)
#define LOGW Logger::Instance(Severity::WARNING, FILE, LINE, func)
#define LOGE Logger::Instance(Severity::ERROR, FILE, LINE, func)
#define LOGFI(a, v…) Logger::Instance(Severity::INFO, FILE, LINE, func)(a, ##v)
#define LOGFV(a, v…) Logger::Instance(Severity::NOTICE, FILE, LINE, func)(a, ##v)
#define LOGFD(a, v…) Logger::Instance(Severity::DEBUG, FILE, LINE, func)(a, ##v)
#define LOGFW(a, v…) Logger::Instance(Severity::WARNING, FILE, LINE, func)(a, ##v)
#define LOGFE(a, v…) Logger::Instance(Severity::ERROR, FILE, LINE, func)(a, ##v)
#else
#define LOG(v) Logger::Instance(v)
#define LOGI Logger::Instance()
#define LOGV Logger::Instance()
#define LOGD Logger::Instance()
#define LOGW Logger::Instance()
#define LOGE Logger::Instance()
#define LOGFI(a, v…) Logger::Instance()(a, ##v)
#define LOGFV(a, v…) Logger::Instance()(a, ##v)
#define LOGFD(a, v…) Logger::Instance()(a, ##v)
#define LOGFW(a, v…) Logger::Instance()(a, ##v)
#define LOGFE(a, v…) Logger::Instance()(a, ##v)
#endif // NDEBUG
#define LINE LOGI << FILE << LINE << ENDL
#endif //__LOGGER
cpp 源码文件
#include "logger.h"
Severity Logger::m_log_level = Severity::INFO; /* only show log that with level
not higher than m_log_level */
bool Logger::m_sync_syslog = false; /* sync log to syslog ? */
bool Logger::m_sync_stdout = true; /* sync log to stdout */
bool Logger::m_sync_file = false; /* sync log to file */
std::string Logger::m_logfile;
Severity Logger::m_severity = Severity::INFO;
std::string Logger::m_filename;
int Logger::m_line;
std::string Logger::m_funcname;
头文件提供了5个宏,实现了5种log级别。目前没有加入色彩显示功能。如果定义了 DEBUG_MODE 宏,会有文件,行号等信息。
使用
#include "logger.h"
using namespace LOGGER;
int main()
{
Logger::Init(Severity::DEBUG, "./log.log");
LOG(Severity::ERROR) << "Severity error" << std::endl;
LOGI << "INFO LOG" << std::endl;
LOGV << "VERBOSE LOG" << std::endl;
LOGD << "DEBUG LOG" << std::endl;
LOGW << "WARNNING LOG" << std::endl;
LOGE << "ERROR LOG" << std::endl;
LOGFI ("INFO LOG");
LOGFV ("VERBOSE LOG");
LOGFD ("DEBUG LOG");
LOGFW ("WARNNING LOG");
LOGFE ("ERROR LOG");
return 0;
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章