mini logger for c++
水平太菜,最近捣鼓这个 log,折腾了好一会。由于之前都是用 std::cout,不能满足同时输出到屏与文件的目的,故经过一番搜索,在stackoverflow 找到了答案,现总结如下:
- 头文件 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 宏,会有文件,行号等信息。
- 使用
#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++的更多相关文章
- X2E车载数据记录仪
随着智能驾驶及网联技术深入应用,汽车中传输的数据量与日俱增,包括多种总线数据.视频数据.雷达数据.定位数据等等.据悉,高级别智能驾驶汽车中每秒传输的总线数据就达到G比特级别.而从产品开 ...
- Ubuntu下LimeSDR Mini使用说明
本文内容.开发板及配件仅限用于学校或科研院所开展科研实验! 淘宝店铺名称:开源SDR实验室 LimeSDR链接:https://item.taobao.com/item.htm?spm=a230r.1 ...
- 让MacBook识别noppoo mini 84
让MacBook识别noppoo mini 84 noppoo默认是没有mac驱动的,需要下载一个IOUSBHIDDriverDescriptorOverride否则无法noppoo的键位是识别错误的 ...
- ABP源码分析八:Logger集成
ABP使用Castle日志记录工具,并且可以使用不同的日志类库,比如:Log4Net, NLog, Serilog... 等等.对于所有的日志类库,Castle提供了一个通用的接口来实现,我们可以很方 ...
- org.apache.log4j.Logger详解
org.apache.log4j.Logger 详解 1. 概述 1.1. 背景 在应用程序中添加日志记录总的来说基于三个目的 :监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工 ...
- Java程序日志:java.util.logging.Logger类
一.Logger 的级别 比log4j的级别详细,全部定义在java.util.logging.Level里面.各级别按降序排列如下:SEVERE(最高值)WARNINGINFOCONFIGFINEF ...
- 中大东校小米路由器mini实现inode上网,ipv6 wifi【中大】【东校】【inode】【ipv6】
还有不到4个月就要毕业了,前几天半夜没事捣鼓小米路由没想到竟然实现了wifi的ipv6. 正好又安利了同学一台小米路由mini,从刷机到inode到ipv6全搞了一遍. 这里将教程写出来,服务学弟妹. ...
- [LeetCode] Logger Rate Limiter 记录速率限制器
Design a logger system that receive stream of messages along with its timestamps, each message shoul ...
- .Net Core Logger 实现log写入本地文件系统
.net core 自带一个基础的logger框架Microsoft.Extensions.Logging. 微软默认实现了Microsoft.Extensions.Logging.Console.d ...
随机推荐
- linux 命令行安装谷歌浏览器
wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm 2. yum install -y ls ...
- Mybatis-04-分页
分页 思考:为什么要分页? 减少数据的处理量 1 使用limit分页 select * from user limit startIndex,pageSize;
- offer收割机也有方法论
秋招的战火就像这夏天的温度一样炙热,陆陆续续很多学弟学妹问我秋招的注意事项,作为温暖型大叔的我此刻必须出场了. 看仔细了,接下来龙叔就把这offer收割机的秘密都告诉你们. 如果你还没点关注的话,记得 ...
- mycat数据库集群系列之mysql主从同步设置
最近在梳理数据库集群的相关操作,现在花点时间整理一下关于mysql数据库集群的操作总结,恰好你又在看这一块,供一份参考.本次系列终结大概包括以下内容:多数据库安装.mycat部署安装.数据库之读写分离 ...
- hiho一下第零周(题目1 : A + B)
#include<iostream> using namespace std; int main() { int a,b; while(cin>>a>>b) cou ...
- Linux文件权限-笔记
文件权限共10个字符,第一个字符表示该文件是[文件夹]或[文件]——如果是字符“d"则表示该文件是文件夹:如果是字符“-”则表示是文件. 后九个字符,三个一组,共三组,分别表示[所有者权限] ...
- window下命令启动/停止nginx
查看Nginx的版本号:nginx -v 启动Nginx:start nginx 快速停止或关闭Nginx:nginx -s stop 正常停止或关闭Nginx:nginx -s quit 配置文件修 ...
- cinder api启动过程源码分析
1.启动cinder-api服务 当你通过cinder-api命令(如:/usr/bin/cinder-api --config-file /etc/cinder/cinder.conf)启动api服 ...
- Qt 最简单的多线程方法QtConcurrent::run()
Qt 最简单的多线程方法QtConcurrent::run()(转载) 最近编写了一个软件,没有考虑多线程的问题,编好以后,软件在执行计算的时候,鼠标响应有时候会延迟,但是完全能用,考虑到后续随着计算 ...
- layaair 物理
box2d http://box2d.org Box2D JS https://sourceforge.net/projects/box2d-js/ Box2D一:基础知识 https://www.c ...