C++日志库plog使用指南

前言

  • 之前介绍过一个C语言日志库 轻量级c语言开源日志库log.c介绍,源代码只有不到200行,使用非常方便。
  • 但是也存在很多缺点,比如日志时间只支持打印到秒,没有作多线程处理,不支持日志回滚。在小型项目或者测试demo中使用还可以,在大型项目中,就无法满足需求了。
  • 于是又找到了一个C++日志库plog,虽然代码量较多,但使用也非常简单,并且功能非常强大,可以满足在大型项目中的使用需求。

plog简介

  • plog 是一个轻量级、跨平台的C++日志库,它设计简洁且易于使用。有以下特点
    • 简单易用: plog 提供了直观的API,允许开发者以简洁的方式在代码中添加日志记录功能。例如,通过LOGD, LOGI, LOGW, LOGE等宏定义来分别表示不同级别的日志输出(如debug、info、warning和error)。
    • 多线程支持: plog 设计为线程安全的,可以安全地在多线程环境下使用,确保各个线程的日志记录不会相互干扰。
    • 多种日志级别: 支持多种日志级别,可以根据需要调整输出的日志详细程度,只显示重要信息或者包括所有调试细节。
    • 文件回滚与滚动日志: plog 允许配置日志文件的大小限制和循环策略,当达到一定大小时会自动创建新的日志文件,以实现日志的滚动存储。
    • 异步/同步日志写入: 可以根据需求选择同步或异步的方式来写入日志,提高程序性能,尤其是在大量日志产生时。
    • 可扩展性: plog 提供了自定义appender的能力,用户可以创建自己的日志接收器,将日志输出到各种不同的目标,如文件、数据库、网络等。
    • 跨平台兼容: plog 能够在多个操作系统和编译器下运行,如Windows、Linux、macOS等,并且兼容多种C++标准。
    • 体积小巧: plog 的源代码量小,占用资源少,适合嵌入式系统或其他对体积敏感的应用场景

使用步骤

  • 下载源代码后,将根目录下include目录下的所有文件拷贝到我们自己的工程下,然后在工程中包含对应的头文件即可。

使用示例

基本功能

  • 通过一个示例演示下基本功能。
  • 测试代码 : main.cpp
  •   #include <plog/Log.h> // Step1: include the header.#include <plog/Initializers/RollingFileInitializer.h>#include <plog/Appenders/ColorConsoleAppender.h>#include <string.h>#include <iostream>#include <iomanip>void polgFunc(){PLOG_DEBUG << "DEBUG join polgFunc func";PLOG_INFO << "DEBUG join polgFunc func";PLOG_ERROR << "DEBUG join polgFunc func";}int main(){// 日志初始化// 参数1 - 日志级别, 参数2 - 日志文件名, 参数3 - 单个日志大小, 参数4 - 日志回滚数// 如果不想实现日志回滚,参数3和参数4可以不填或者填0plog::init(plog::info, "plog.log", 1024, 5);// 同时打印到控制台plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender;plog::get()->addAppender(&consoleAppender); // Also add logging to the console.int iData = 10020;double fData = 3.141592654; std::string sData = "hello plog";PLOG_DEBUG << "debug hello log!"; LOG_INFO << "info hello log!";PLOG_WARNING << "warning hello log!";PLOG_ERROR << "error hello log!";PLOG_INFO << "int data : " << iData;PLOG_INFO << "int hex data : " << std::hex << iData;PLOG_INFO << "float data : " << fData;PLOG_INFO << "float data : " << std::fixed << std::setprecision(2) << fData;PLOG_INFO << "string data : " << fData;polgFunc();system("pause");return 0;}
    
  • 控制台打印
    在这里插入图片描述
  • 文件打印:在当前目录下会生成一个 plog.log 文件
    在这里插入图片描述
  • 日志回滚 : 文件超出我们设置的大小后,可以自动回滚
    在这里插入图片描述

进阶功能 - 自定义日志打印格式

  • 对测试代码进行修改 main.cpp
  •   #include <plog/Log.h> // Step1: include the header.#include <plog/Initializers/RollingFileInitializer.h>#include <plog/Appenders/ColorConsoleAppender.h>#include <string.h>#include <iostream>#include <iomanip>// 自定义日志格式器namespace plog{class MyFormatter{public:static util::nstring header() // This method returns a header for a new file. In our case it is empty.{return util::nstring();}static util::nstring format(const Record& record) // This method returns a string from a record.{util::nostringstream ss;util::Time t;t.time = record.getTime().time;struct tm *ltime = localtime(&t.time);t.millitm = record.getTime().millitm;// 在这里设置日志打印的格式ss << "[plog] ["<<ltime->tm_year + 1900 <<"/"<< std::setfill(PLOG_NSTR('0')) << std::setw(2) << ltime->tm_mon + 1 <<"/"<< std::setfill(PLOG_NSTR('0')) << std::setw(2) << ltime->tm_mday << "_";ss << std::setfill(PLOG_NSTR('0')) << std::setw(2) << ltime->tm_hour << PLOG_NSTR(":") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << ltime->tm_min << PLOG_NSTR(":") << std::setfill(PLOG_NSTR('0')) << std::setw(2) << ltime->tm_sec << ".";ss << std::setfill(PLOG_NSTR('0')) << std::setw(3) <<t.millitm << "] ";ss << std::setw(5) << std::left << std::setfill(PLOG_NSTR(' ')) <<severityToString(record.getSeverity()) <<" [" << record.getTid()<< "]"<<" [" << record.getFunc() << ":" << record.getLine() << "] " << record.getMessage() << "\n";return ss.str();}};}void polgFunc(){PLOG_DEBUG << "DEBUG join polgFunc func";PLOG_INFO << "DEBUG join polgFunc func";PLOG_ERROR << "DEBUG join polgFunc func";}int main(){// 日志初始化// 参数1 - 日志级别, 参数2 - 日志文件名, 参数3 - 单个日志大小, 参数4 - 日志回滚数// 如果不想实现日志回滚,参数3和参数4可以不填或者填0// plog::init(plog::info, "plog.log", 1024, 5);plog::init<plog::MyFormatter>(plog::info, "plogformat.log", 1024, 5); // 同时打印到控制台plog::ColorConsoleAppender<plog::TxtFormatter> consoleAppender;plog::get()->addAppender(&consoleAppender); // Also add logging to the console.int iData = 10020;double fData = 3.141592654; std::string sData = "hello plog";PLOG_DEBUG << "debug hello log!"; LOG_INFO << "info hello log!";PLOG_WARNING << "warning hello log!";PLOG_ERROR << "error hello log!";PLOG_INFO << "int data : " << iData;PLOG_INFO << "int hex data : " << std::hex << iData;PLOG_INFO << "float data : " << fData;PLOG_INFO << "float data : " << std::fixed << std::setprecision(2) << fData;PLOG_INFO << "string data : " << fData;polgFunc();system("pause");return 0;}
    
  • 文件打印:再运行看下文件中的打印
    在这里插入图片描述
  • 可以看到,打印的格式就是我们自定义的格式。

在线程中打印

  • 可以在线程中打印

  • main.cpp

  •   #include <plog/Log.h> #include <plog/Initializers/RollingFileInitializer.h>#include <string.h>#include <iostream>#include <windows.h>#include <process.h>unsigned int __stdcall ThreadFun(PVOID lpParam) {PLOG_DEBUG << "debug ThreadFun!";LOG_INFO << "info ThreadFun!";PLOG_WARNING << "warning ThreadFun!";PLOG_ERROR << "error ThreadFun!";return 0;}int main(){plog::init(plog::info, "plog.log", 1024, 5);HANDLE handle1 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun, NULL, 0, NULL);HANDLE handle2 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun, NULL, 0, NULL);HANDLE handle3 = (HANDLE)_beginthreadex(NULL, 0, ThreadFun, NULL, 0, NULL);system("pause");return 0;}
  • 打印结果
    在这里插入图片描述

  • 可以看到不同线程中的线程id

在多个文件中打印

  • 多个文件中如何打印呢?只需要通过 plog::init 在程序入口处初始化,然后在其他文件中包含 #include <plog/Log.h> 头文件直接通过 PLOG_INFO 打印即可,不需要传任何参数,使用非常方便。这里就不演示了。

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

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

相关文章

【Effective Objective - C】—— block 块

【Effective Objective - C】—— block 块 前言37.理解块的概念块的基础知识块可以捕获变量内联块的用法块的内部结构栈块堆块全局块要点 38.为常用的块类型创建typedef要点 39.用handler块降低代码分散程度协议传值实现异步块实现异步回调操作里的块要点 40.用块引用其所属对…

SpringBoot项目快速创建

SpringBoot项目快速创建 方法一&#xff1a;通过IDEA的Spring Initializr 点击文件&#xff0c;新建项目&#xff0c;选择Spring Initializr 名称&#xff1a;项目名称存放位置&#xff1a; 语言&#xff1a;Java类型&#xff1a;Maven组&#xff1a;<groupId>com.exam…

MyBatisPlus条件构造器和常用接口

前置配置文章 一、wapper介绍 wrapper的继承体系&#xff1a; Wrapper &#xff1a; 条件构造抽象类&#xff0c;最顶端父类 AbstractWrapper &#xff1a; 用于查询条件封装&#xff0c;生成 sql 的 where 条件 QueryWrapper &#xff1a; 查询条件封装UpdateWrapper &#x…

【MATLAB GUI】 4. 坐标区和表

看B站up主freexyn的freexyn编程实例视频教程系列36Matlab GUI的学习笔记 文章目录 坐标区表 坐标区 任务要求设计一个图像显示界面&#xff0c;根据选定的周期做出相应的sin函数图像 使用坐标区、弹出式菜单、普通按钮设计页面&#xff0c;弹出式菜单string设置为1、2、3、4代…

C#,动态规划(DP)丢鸡蛋问题(Egg Dropping Puzzle)的三种算法与源代码

1 扔鸡蛋问题 动态规划&#xff08;Dynamic Programming&#xff0c;DP&#xff09;是运筹学的一个分支&#xff0c;是求解决策过程最优化的过程。20世纪50年代初&#xff0c;美国数学家贝尔曼&#xff08;R.Bellman&#xff09;等人在研究多阶段决策过程的优化问题时&#xf…

【MySQL】数据库概述

目录 一、为什么使用数据库&#xff1f; 二、数据库与数据库管理系统 2.1 相关概念 2.2 两者关系 三、 MySQL介绍 四、 RDBMS和非RDBMS 4.1 关系型数据库&#xff08;RDBMS&#xff09; 4.2 非关系型数据库&#xff08;非RDBMS&#xff09; 五、关系型数据库设计规则 …

WebService学习,wsdl文件详解

目录 第一章、起因1.1&#xff09;学习原因1.2&#xff09;提问的过程&#xff08;逐步提出问题&#xff09;1、&#xff1f;wsdl链接的含义&#xff0c;有什么作用&#xff1f;2、什么是wsdl文档&#xff1f;3、如何阅读wsdl文件&#xff1f;4、wsdl文件有什么作用&#xff1f…

百面嵌入式专栏(经验篇)如何在面试中介绍自己的项目经验

文章目录 1. 在面试前准备项目描述,别害怕,因为面试官什么都不知道2. 准备项目的各种细节,一旦被问倒了,就说明你没做过3.不露痕迹地说出面试官爱听的话4.一定要主动,面试官没有义务挖掘你的亮点5.一旦有低级错误,可能会直接出局6.引导篇:准备些加分点,在介绍时有意提到…

图文说明Linux云服务器如何更改实例镜像

一、应用场景举例 在学习Linux的vim时&#xff0c;我们难免要对vim进行一些配置&#xff0c;这里我们提供一个vim插件的安装包&#xff1a; curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o./install.sh && bash ./install.sh 但是此安装包…

关于el-select值的回显问题 : 框内显示label值还是value值

<el-form-item label"状态" prop""><el-selectv-model"roleForm.state"class"m-2"size"large"style"width: 240px"placeholder"请选择状态"value-key"value"//value-key 与下面的ke…

区块链笔记(五)---德勤相关分析报告

web3.0 定义&#xff1a; 在《Insights into a Modern World》提出&#xff0c;“信息将由用户自己发布、保管、不可追溯且永远不会泄露&#xff0c;用户的任何行为将不需要任何中间机构来帮助传递”&#xff1b;用来指代一种区块链技术&#xff0c;可以基于“无须信任的交互…

探索D咖智能饮品机器人的工作原理:科技、材料与设计的相互融合

智能饮品机器人是近年来随着人工智能和自动化技术的发展而崭露头角的一种创新产品。它将科技、材料和设计相互融合&#xff0c;为消费者带来了全新的饮品体验。下面D咖来探索智能饮品机器人的工作原理&#xff0c;以及科技、材料和设计在其中的作用。 首先&#xff0c;智能饮品…

STM32—触摸键

目录 1 、 电路构成及原理图 2 、编写实现代码 3、代码讲解 4、烧录到开发板调试、验证代码 5、检验效果 此笔记基于朗峰 STM32F103 系列全集成开发板的记录。 1 、 电路构成及原理图 触摸键简单的了解就是一次电容的充放电过程。从原理图可以看出&#xff0c;触摸键 …

钧达股份:光伏跨界新贵只身赴港股,光伏“秩序重塑”?

2月21日&#xff0c;钧达股份终是在“千呼万唤”之中披露最新业绩快报。 快报显示&#xff0c;钧达股份预计2023年经调整后营业收入183.97亿元&#xff0c;同比增长58.65%&#xff0c;归母净利润8.32亿元&#xff0c;同比增长16.00%。 其中&#xff0c;由于Q4完整计提了9.5GW…

c语言经典测试题3

1.题1 int a 248, b 4; int const *c 21; const int *d &a; int *const e &b; int const * const f &a; 请问下列表达式哪些会被编译器禁止&#xff1f; A: *c 32; B: *d 43 C: e&a D: f0x321f 我们来分析一下&#xff1a;const用来修饰变量是想其…

遍历的三种算法——递归、非递归、层次

一、递归遍历方法&#xff1a; 先序遍历&#xff1a; Status PreOrderTraverse(Tree *t) {if (t NULL) return OK;//合法性检查else {visit(t->data);//访问根节点PreOrderTraverse(t->lchild);//递归遍历左子树PreOrderTraverse(t->rchild);//递归遍历右子树} } …

【ArcGIS】利用高程进行坡度分析

在ArcGIS中利用高程进行坡度分析 坡度ArcGIS实操参考 坡度 坡度是地表单元陡缓的程度&#xff0c;通常把坡面的垂直高度和水平距离的比值称为坡度。 坡度的表示方法有百分比法、度数法、密位法和分数法四种&#xff0c;其中以百分比法和度数法较为常用。 &#xff08;1&#…

C语言特殊函数

静态函数 背景知识&#xff1a;普通函数都是跨文件可见的&#xff0c;即在文件 a.c 中定义的函数可以在 b.c 中使用。 静态函数&#xff1a;只能在定义的文件内可见的函数&#xff0c;称为静态函数。 语法 staitc void f(void) // 在函数头前面增加关键字 static &#xff…

智慧城市的新宠儿:会“思考”的井盖

在城市化飞速发展的今天&#xff0c;我们或许未曾过多地关注那些平凡却至关重要的井盖。它们无声地矗立在城市的每个角落&#xff0c;守护着深藏于地下的城市生命线&#xff0c;然而&#xff0c;这些井盖并未满足于传统的角色&#xff0c;它们正逐步融入智慧城市的宏大画卷中&a…

IDEA生成Java Doc帮助文档

使用场景 使用IDEA&#xff08;本次使用2020.3版&#xff09;将自己写的常用的工具类打成jar包&#xff0c;安装到maven本地仓库&#xff0c;最后生成对应的doc参考文档。 操作流程 方法一 选中项目 右键 show in Explor&#xff0c;如下图&#xff1a; 选中地址栏 cmd 输入…