水平太菜,最近捣鼓这个 log,折腾了好一会。由于之前都是用 std::cout,不能满足同时输出到屏与文件的目的,故经过一番搜索,在stackoverflow 找到了答案,现总结如下:

  1. 头文件 logger.hpp, 代码如下:
#ifndef __LOGGER
#define __LOGGER #include <iostream>
#include <fstream>
#include <sstream>
#include <mutex>
#include <ctime> #include <syslog.h> 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 宏,会有文件,行号等信息。

  1. 使用
#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;
}

mini logger for c++的更多相关文章

  1. X2E车载数据记录仪

            随着智能驾驶及网联技术深入应用,汽车中传输的数据量与日俱增,包括多种总线数据.视频数据.雷达数据.定位数据等等.据悉,高级别智能驾驶汽车中每秒传输的总线数据就达到G比特级别.而从产品开 ...

  2. Ubuntu下LimeSDR Mini使用说明

    本文内容.开发板及配件仅限用于学校或科研院所开展科研实验! 淘宝店铺名称:开源SDR实验室 LimeSDR链接:https://item.taobao.com/item.htm?spm=a230r.1 ...

  3. 让MacBook识别noppoo mini 84

    让MacBook识别noppoo mini 84 noppoo默认是没有mac驱动的,需要下载一个IOUSBHIDDriverDescriptorOverride否则无法noppoo的键位是识别错误的 ...

  4. ABP源码分析八:Logger集成

    ABP使用Castle日志记录工具,并且可以使用不同的日志类库,比如:Log4Net, NLog, Serilog... 等等.对于所有的日志类库,Castle提供了一个通用的接口来实现,我们可以很方 ...

  5. org.apache.log4j.Logger详解

    org.apache.log4j.Logger 详解 1. 概述 1.1. 背景 在应用程序中添加日志记录总的来说基于三个目的 :监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工 ...

  6. Java程序日志:java.util.logging.Logger类

    一.Logger 的级别 比log4j的级别详细,全部定义在java.util.logging.Level里面.各级别按降序排列如下:SEVERE(最高值)WARNINGINFOCONFIGFINEF ...

  7. 中大东校小米路由器mini实现inode上网,ipv6 wifi【中大】【东校】【inode】【ipv6】

    还有不到4个月就要毕业了,前几天半夜没事捣鼓小米路由没想到竟然实现了wifi的ipv6. 正好又安利了同学一台小米路由mini,从刷机到inode到ipv6全搞了一遍. 这里将教程写出来,服务学弟妹. ...

  8. [LeetCode] Logger Rate Limiter 记录速率限制器

    Design a logger system that receive stream of messages along with its timestamps, each message shoul ...

  9. .Net Core Logger 实现log写入本地文件系统

    .net core 自带一个基础的logger框架Microsoft.Extensions.Logging. 微软默认实现了Microsoft.Extensions.Logging.Console.d ...

随机推荐

  1. set学习记录

    set是STL中的集合容器,其中每个元素都互不相同,并且都是以递增的形式排列. set只能使用迭代器访问. 说一下常用函数: 1.insert(x):插入函数用于把x插入set. 2.find(val ...

  2. 报错:Cause: java.sql.SQLSyntaxErrorException: ORA-00936: 缺失表达式

    错误原因:

  3. 第一章 Kubernetes入门

    第一章 Kubernetes入门 kubernetes是基于容器技术的分布式架构领先方案,是一个完备的分布式系统支撑平台. kubernetes带来的好处:1)全面拥抱微服务:2)统可以随时随地整体“ ...

  4. Fiddler+模拟器+APP抓包HTTPS 为什么有时候抓不到?

    抓包的原理是什么? 代理 客户端请求 -> 经过代理 -> 到达服务端 服务端返回 -> 经过代理 -> 到达客户端 任何Https的App都能抓到包么? Android7.0 ...

  5. JavaScript学习系列博客_20_JavaScript 作用域

    作用域 - 作用域指一个变量的作用的范围 - 在JS中一共有两种作用域 1.全局作用域 - 直接编写在script标签中的JS代码,都在全局作用域- 全局作用域在页面打开时创建,在页面关闭时销毁 - ...

  6. Ubuntu图形桌面切换到命令行界面

    Ubuntu提供两种进入方式,一个是我们平常最熟悉的图形界面形式,还有一种是纯命令行方式. 1.按 Ctrl + Alt + (F1~F6中的任意一个)即可进入纯命令行模式. 进入后,需要输入用户名, ...

  7. 一张图带你玩转docker

  8. APEX安装

    git clone https://github.com/NVIDIA/apex.gitcd apex export CUDA_HOME=/usr/local/cudapip3 install -v ...

  9. you-get 下载B站上的视频

    安装you-get pip install you-get 安装好后,我们可以查看一下you-get的参数 you-get -h 视频下载 单个视频下载 CMD下载 you-get -o /data/ ...

  10. Java通过反射加载的类,变量无法注入

    //之前都是直接newInstance的到obj,类中的变量无法被注入//Object obj = aClass.newInstance(); //改成如下方式的到bean,变量就能顺利被注入 ,其他 ...