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 ...
随机推荐
- Java 8中Lambda表达式默认方法的模板方法模式,你够了解么?
为了以更简单的术语描述模板方法,考虑这个场景:假设在一个工作流系统中,为了完成任务,有4个任务必须以给定的执行顺序执行.在这4个任务中,不同工作流系统的实现可以根据自身情况自定义任务的执行内容. 模板 ...
- mycat数据库集群系列之数据库多实例安装
mycat数据库集群系列之数据库多实例安装 最近在梳理数据库集群的相关操作,现在花点时间整理一下关于mysql数据库集群的操作总结,恰好你又在看这一块,供一份参考.本次系列终结大概包括以下内容:多数据 ...
- 虚拟化技术之kvm基础
一.KVM简介 KVM的全称是kernel base virtual machine(基于内核的虚拟机)是一个开源的系统虚拟化模块,自Linux 2.6.20之后集成在Linux的各个主要发行版本中. ...
- C++ 2的幂次方表示
[题目描述] 任何一个正整数都可以用2的幂次方表示.例如: 137=27+23+20 同时约定方次用括号来表示,即ab可表示为a(b).由此可知,137可表示为: 2(7)+2(3)+2(0) 进一步 ...
- 关于Redis的工作模式
1.哨兵模式 在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异常,则会做主从切换,将某一台slave作为master. 缺点 ...
- Vue管理系统前端系列四组件拆分封装
目录 组件封装 首页布局拆分后结构 拆分后代码 状态管理中添加 app 模块 组件封装 在上一篇记录中,首页中有太多的代码,为了避免代码的臃肿,需要对主要的功能模块拆分,来让代码看起来更简洁,且能进行 ...
- keepalived的vrrp多播报文被禁,导致VIP同时位于多个机器上
keepalived的vrrp多播报文被禁,导致VIP同时位于多个机器上 查看man keepalived.conf,VRRP instances中给出了单播的设置方法,添加unicast_peer即 ...
- Logistic回归分析之多分类Logistic回归
Logistic回归分析(logit回归)一般可分为3类,分别是二元Logistic回归分析.多分类Logistic回归分析和有序Logistic回归分析.logistic回归分析类型如下所示. Lo ...
- 简单实现C++Stack模板
栈的特点是先进后出以及只能在栈顶进行插入和删除操作 本次实现的栈的基本操作: 1)弹栈 2)压栈 3)求栈大小 4)求栈容量 5)判断栈空 6)获取栈顶元素 1.用数组的方式实现栈基本操作 /** * ...
- PyTorch入门-CIFAR10图像分类
CIFAR10数据集下载 CIFAR10数据集包含10个类别,图像尺寸为 3×32×32 官方下载地址很慢,这里给一个百度云: https://pan.baidu.com/s/1oTvW8wNa-VO ...