基于C11的简单log,支持C++的‘<<’风格和C的‘可变参数’风格

基于C11的简单log,支持C++的‘<<’风格和C的‘可变参数’风格

日志仅由richlog.h单个文件实现功能,软件集成简单。

支持C++的std::cout的<<风格的日志打印,也支持C的printf风格的日志打印

日志多线程安全,采用C++11 mutex 互斥锁

日志格式如下:

[日志级别][时间戳][模块名][组件名][日志所在文件名][日志所在行号][日志所在函数名]->日志内容

日志格式、输出方式可配置,以下为配置函数

//日志输出到文件开关,默认关闭
static void set_output_to_file(bool to_file)
//日志输出到终端开关,默认打开
static void set_output_to_console(bool to_console)
//日志打印时间戳开关,默认打开
static void set_print_timestamp(bool log_timestamp)
//设置日志打印模块名,默认为空
static void set_modulename(std::string name)
//设置日志打印组件名,默认为空
static void set_componentname(std::string name)
//日志级别开关,默认打开
static void set_print_log_level(bool log_level)
//日志所在文件名开关,默认打开
static void set_print_filename(bool log_level)
//日志所在行号开关,默认打开
static void set_print_linenum(bool plinenum)
//日志所在函数名,默认打开
static void set_print_funcname(bool pfuncname)
//设置日志输出的文件名,默认为空
static void set_output_to_filename(std::string filename)

richlog.h代码

#ifndef _RICHLOGS_H
#define _RICHLOGS_H#include <cstring>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <sstream>
#include <chrono>
#include <thread>
#include <mutex>#define CXXLOG_FILENAME(x) (strrchr((x),'/')?strrchr((x),'/')+1:(x))
#define C11LOG_ERROR   CPP_LOG::RichLogs(CPP_LOG::ERROR,CXXLOG_FILENAME(__FILE__),__LINE__,__FUNCTION__)
#define C11LOG_WARN    CPP_LOG::RichLogs(CPP_LOG::WARN,CXXLOG_FILENAME(__FILE__),__LINE__,__FUNCTION__)
#define C11LOG_INFO    CPP_LOG::RichLogs(CPP_LOG::INFO,CXXLOG_FILENAME(__FILE__),__LINE__,__FUNCTION__)
#define C11LOG_DEBUG   CPP_LOG::RichLogs(CPP_LOG::DEBUG,CXXLOG_FILENAME(__FILE__),__LINE__,__FUNCTION__)namespace CPP_LOG
{
enum  LOG_LEVEL{ERROR,WARN,INFO,DEBUG};class RichLogs
{
public:RichLogs(LOG_LEVEL log_level,std::string filename,unsigned int line_num,std::string func_name){m_has_endl=false;if(m_print_log_level){switch(log_level){case ERROR:m_log_data<<"[ERROR]";break;case WARN:m_log_data<<"[ WARN]";break;case INFO:m_log_data<<"[ INFO]";break;case DEBUG:m_log_data<<"[DEBUG]";break;}}if(m_print_timestamp){m_log_data<<"["<<getNowTime().count()<<"]";}if(m_module_name!=""){m_log_data<<"["<<m_module_name<<"]";}if(m_component_name!=""){m_log_data<<"["<<m_component_name<<"]";}if(m_print_filename){m_log_data<<"["<<filename<<"]";}if(m_print_linenum){m_log_data<<"["<<line_num<<"]";}if(m_print_funcname){m_log_data<<"["<<func_name<<"]";}m_log_data<<"->";}~RichLogs(){if(!m_has_endl){m_log_data<<std::endl;}if(m_output_to_file){if(m_output_to_filename!=""){std::ofstream outputFile;outputFile.open(m_output_to_filename,std::ios::app);if (outputFile.is_open()){std::lock_guard<std::mutex> lock(m_log_mutex);outputFile<<m_log_data.str();outputFile.flush();}outputFile.close();}}if(m_output_to_console){std::lock_guard<std::mutex> lock(m_log_mutex);std::cout<<m_log_data.str();}}RichLogs& operator<<(std::ostream&(*p)(std::ostream&)){m_has_endl=true;m_log_data<<std::endl;return *this;}template<typename T>RichLogs& operator<<(const T& logdata){m_has_endl=false;m_log_data<<logdata;return *this;}// 泛型template <typename... Args>RichLogs& operator()(const char *pformat, Args... args){int total_len = std::snprintf(nullptr, 0, pformat, args...);if (0 >= total_len){return *this;}total_len++;char *log_str_out = nullptr;log_str_out = new(std::nothrow) char[total_len];if (NULL == log_str_out || nullptr == log_str_out){return *this;}std::snprintf(log_str_out, total_len, pformat, args...);if(log_str_out[total_len-2]=='\n'){m_has_endl=true;}else{m_has_endl=false;}std::string str(log_str_out);delete log_str_out;log_str_out = nullptr;m_log_data<<str;return *this;}static void set_output_to_file(bool to_file){std::lock_guard<std::mutex> lock(m_log_mutex);m_output_to_file=to_file;}static void set_output_to_console(bool to_console){std::lock_guard<std::mutex> lock(m_log_mutex);m_output_to_console=to_console;}static void set_print_timestamp(bool log_timestamp){std::lock_guard<std::mutex> lock(m_log_mutex);m_print_timestamp=log_timestamp;}static void set_modulename(std::string name){std::lock_guard<std::mutex> lock(m_log_mutex);m_module_name=name;}static void set_componentname(std::string name){std::lock_guard<std::mutex> lock(m_log_mutex);m_component_name=name;}static void set_print_log_level(bool log_level){std::lock_guard<std::mutex> lock(m_log_mutex);m_print_log_level=log_level;}static void set_print_filename(bool log_level){std::lock_guard<std::mutex> lock(m_log_mutex);m_print_log_level=log_level;}static void set_print_linenum(bool plinenum){std::lock_guard<std::mutex> lock(m_log_mutex);m_print_linenum=plinenum;}static void set_print_funcname(bool pfuncname){std::lock_guard<std::mutex> lock(m_log_mutex);m_print_funcname=pfuncname;}static void set_output_to_filename(std::string filename){std::lock_guard<std::mutex> lock(m_log_mutex);m_output_to_filename=filename;}private:bool m_has_endl;std::stringstream m_log_data;static std::mutex m_log_mutex;static bool m_output_to_file;static bool m_output_to_console;static bool m_print_log_level;static bool m_print_timestamp;static std::string m_module_name;static std::string m_component_name;static bool m_print_filename;static bool m_print_linenum;static bool m_print_funcname;static std::string m_output_to_filename;std::chrono::milliseconds getNowTime(){std::chrono::system_clock::time_point now_time = std::chrono::system_clock::now();return std::chrono::duration_cast<std::chrono::milliseconds>(now_time.time_since_epoch());}
};std::mutex RichLogs::m_log_mutex;
bool RichLogs::m_output_to_file=false;
bool RichLogs::m_output_to_console=true;
bool RichLogs::m_print_log_level=true;
bool RichLogs::m_print_timestamp=true;
std::string RichLogs::m_module_name="";
std::string RichLogs::m_component_name="";
bool RichLogs::m_print_filename=true;
bool RichLogs::m_print_linenum=true;
bool RichLogs::m_print_funcname=true;
std::string RichLogs::m_output_to_filename="";}
#endif //C11LOG_C11LOG_H

测试例子

#include <iostream>
#include "richlog.h"using namespace std;int main()
{CPP_LOG::RichLogs::set_modulename("test123");CPP_LOG::RichLogs::set_componentname("sdfghjk");CPP_LOG::RichLogs::set_output_to_file(true);CPP_LOG::RichLogs::set_output_to_filename("test4444.log");for(int i=0;i<100;i++){C11LOG_INFO<<"123456 "<<" sdfsdfgfdgjghjsegwdsfbrsntbrsb"<<"54332gfdsbrrbfdxbw4353vsw";C11LOG_DEBUG<<"123456 "<<1234<<" "<<345.6<<" sdsafdsv ewtertyui"<<'c'<<'l';C11LOG_WARN<<"123456 "<<1234<<" "<<345.6<<" sdsafdsv ewtertyui"<<'c'<<'l';C11LOG_ERROR<<"123456 "<<1234<<" "<<345.6<<" sdsafdsv ewtertyui"<<'c'<<'l';C11LOG_INFO("%d-%f-%s-%c\n",1234,345.234,"kkkkkkk",'e');C11LOG_DEBUG("%d-%f-%s-%c\n",1234,345.234,"kkkkkkk",'e');C11LOG_WARN("%d-%f-%s-%c",1234,345.234,"kkkkkkk",'e');C11LOG_ERROR("%d-%f-%s-%c",1234,345.234,"kkkkkkk",'e');}return 0;
}

运行结果:
日志测试结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/400581.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot整合日志功能(slf4j+logback)详解

目录 一、日志门面与日志实现 1.1 什么是日志门面和日志实现&#xff1f; 1.2 为什么需要日志门面&#xff1f; 二、简介 三、日志格式 四、记录日志 4.1 使用日志工厂 4.2 使用Lombok的Slf4j注解 五、日志级别 5.1 日志级别介绍 5.2 配置日志级别 5.3 指定某个包下…

分类预测|基于粒子群优化核极限学习机的Adaboost集成模型数据分类预测Matlab程序 PSO-KELM-Adaboost

分类预测|基于粒子群优化核极限学习机的Adaboost集成模型数据分类预测Matlab程序 PSO-KELM-Adaboost 文章目录 前言分类预测|基于粒子群优化核极限学习机的Adaboost集成模型数据分类预测Matlab程序 PSO-KELM-Adaboost 一、PSO-KELM-Adaboost模型1. 核化极限学习机 (KELM)2. 粒子…

数据库原理面试-核心概念-问题理解

目录 1.数据库、数据库系统与数据库管理系统 2.理解数据独立性 3.数据模型 4.模式、外模式和内模式 5.关系和关系数据库 6.主键与外键 7.SQL语言 8.索引与视图 9.数据库安全 10.数据库完整性 11.数据依赖和函数依赖 12.范式&#xff1f;三范式&#xff1f;为什么要遵…

用栈访问最后若干元素——682、71、388

682. 棒球比赛&#xff08;简单&#xff09; 你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成&#xff0c;过去几回合的得分可能会影响以后几回合的得分。 比赛开始时&#xff0c;记录是空白的。你会得到一个记录操作的字符串列表 ops&#xff0c;其中 ops[…

【redis的大key问题】

在使用 Redis 的过程中&#xff0c;如果未能及时发现并处理 Big keys&#xff08;下文称为“大Key”&#xff09;&#xff0c;可能会导致服务性能下降、用户体验变差&#xff0c;甚至引发大面积故障。 本文将介绍大Key产生的原因、其可能引发的问题及如何快速找出大Key并将其优…

基于llama.cpp实现Llama3模型的guff格式转换、4bit量化以及GPU推理加速(海光DCU)

重要说明&#xff1a;本文从网上资料整理而来&#xff0c;仅记录博主学习相关知识点的过程&#xff0c;侵删。 序言 本文使用llama.cpp框架&#xff0c;对 Llama3-8B-Instruct 模型进行gguf格式转换&#xff0c;8bit量化&#xff0c;并在CPU和GPU上对8bit模型进行推理。 测试…

基于SpringBoot的企业资产管理系统

TOC springboot117基于SpringBoot的企业资产管理系统 系统概述 1.1 研究背景 智慧养老是面向居家老人、社区及养老机构的传感网系统与信息平台&#xff0c;并在此基础上提供实时、快捷、高效、低成本的&#xff0c;物联化、互联化、智能化的养老服务。 随着科技进步&#…

mysql中log

目录 MySQL 日志系统概述 日志类型 日志的作用和重要性 Mermaid图示 1. Undo Log 和 Redo Log 的协同工作图 2. Redo Log 确保持久性的流程图 Undo Log&#xff08;回滚日志&#xff09; 事务的原子性&#xff08;Atomicity&#xff09;保障 事务回滚机制 MVCC&#…

【二叉树进阶】--- 二叉搜索树转双向链表 最近公共祖先

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 数据结构 本篇博客我们继续了解一些二叉树的进阶算法。 &#x1f3e0; 二叉搜索 树转化为双向循环链表 &#x1f4cc; 题目内容 将二叉搜索树转化为排序…

失败:Windows--WSL2--Ubuntuon--Docker

编写目的&#xff1a; 在Windows上安装Docker&#xff0c;用Docker安装Gitlab、Jenkins等软件。 文章记录一下Windows上安装Docker的过程。 参考文档&#xff1a; 旧版 WSL 的手动安装步骤 | Microsoft Learn 下面用"参考文档"代替 目录 第一步&#xff1a;启…

SAP与网易大数据系统集成案例

一、项目环境 江西某药业有限公司是一家以医药产业为主营、资本经营为平台的大型民营企业集团。公司成立迄今&#xff0c;企业经营一直呈现稳健、快速发展的态势集团总销售额超40亿元。 为了帮助企业更有效的进行分配和管理&#xff0c;包括人力、物资、时间和预算等资源&a…

UVa1660/LA3031 Cable TV Network

UVa1660/LA3031 Cable TV Network 题目链接题意分析AC 代码 题目链接 本题是2004年icpc欧洲区域赛东南欧赛区的题目 题意 给定一个n&#xff08;n≤50&#xff09;个点的无向图&#xff0c;求它的点连通度&#xff0c;即最少删除多少个点&#xff0c;使得图不连通。如下图所示…

C语言----约瑟夫环

约瑟夫环 实例说明&#xff1a; 本实例使用循环链表实现约瑟夫环。给定一组编号分别是4、7、5、9、3、2、6、1、8。报数初始值由用户输入&#xff0c;这里输入4&#xff0c;如图12.18所示&#xff0c;按照约瑟夫环原理打印输出队列。 实现过程&#xff1a; (1)在 VC6.0中创建…

GlobalMapper软件安装流程

目录 一、环境准备 二、安装步骤 三、软件激活 一、环境准备 系统&#xff1a;win7操作系统 安装包下载&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1Vb4VVRFBRYawt3MT-5gYOw 提取码&#xff1a;sxdj 二、安装步骤 1、解压&#xff0c;右键global-mapper-23_1-x…

Redis的简单介绍

一、Redis简介 1.NOSQL NoSQL( Not Only SQL)&#xff0c;意即“不仅仅是SQL”&#xff0c;泛指非关系型的数据库。随着互联网web2.0网站的兴起&#xff0c;传统的关系数据库在应付web2.0网站&#xff0c;纯动态网站已经显得力不从心&#xff0c;暴露了很多难以克服的问题&am…

java学习19VUE

VUE NPM npm的全称是Node Package Manager 中文名为Node.js包管理器&#xff0c;是一个NodeJS包管理和分发工具&#xff0c;已经成为了非官方的发布Node模块(包)的标准。NPM可以方便地从一个全球的代码库中获取并安装Node.js模块&#xff0c;这些模块可以用于构建应用程序、…

【LeetCode Cookbook(C++ 描述)】一刷二叉树之层序遍历(BFS)

目录 LeetCode #102&#xff1a;Binary Tree Lever Order Traversal 二叉树的层序遍历递归解法迭代解法 LeetCode #107&#xff1a;Binary Tree Level Order Traversal II - 二叉树的层序遍历 II递归解法迭代解法 LeetCode #429&#xff1a;N-ary Tree Level Order Traversal -…

python结合csv和正则实现条件筛选数据统计分数

前景提要&#xff1a; 有一个项目的数值和员工统计的对不上&#xff0c;如果一页一页翻找自己手动算&#xff0c;一个就有16、7页&#xff0c; 功能实现 1、创建csv文件 需要将每一个模块的所有数据头提取出来&#xff0c;这个可以直接用爬虫或者手工复制出来&#xff0c;因…

The Sandbox 游戏制作教程第 4 章|使用装备制作游戏,触发独特互动

欢迎回到我们的系列&#xff0c;我们将记录 The Sandbox Game Maker 的 “On-Equip”&#xff08;装备&#xff09;功能的多种用途。 如果你刚加入 The Sandbox&#xff0c;On-Equip 功能是 “可收集组件”&#xff08;Collectable Component&#xff09;中的一个多功能工具&a…

无人机的电压和放电速率,你知道吗?

一、无人机电压 无人机电瓶多采用锂电池&#xff0c;其电压范围在3.7伏至44.4伏之间&#xff0c;具体取决于电池的单体电压和串联的电池节数。 单体电压&#xff1a;锂电池的单体电压通常为3.7V&#xff0c;但在满电状态下可能达到4.2V。 串联电池节数&#xff1a;无人机电瓶…