17_c/c++开源库 easylogging日志库

1.简介与安装

简介:
EasyLogging的主要特点包括:

简单易用:EasyLogging的API设计简洁明了,使用起来非常方便。开发者只需包含头文件并初始化库,即可开始记录日志。
高效性:EasyLogging采用异步日志记录方式,将日志信息的写入操作与程序的主线程分离,从而避免了日志记录对程序性能的影响。
线程安全:EasyLogging支持多线程环境下的日志记录,内部采用了锁机制来保证线程安全。
可配置性:EasyLogging提供了丰富的配置选项,允许开发者根据需要自定义日志记录的级别、格式、输出目标等。
跨平台兼容:EasyLogging支持多种操作系统和编译器,具有良好的跨平台兼容性。

安装

sudo apt install libeasyloggingpp-dev

使用

编译依赖
pkg-config --cflags --libs easyloggingpp

没错,你没有看错, ubuntu20.04上默认安装libeasyloggingpp-dev 没有提示任何 ld链接选项.
通过github 下载最新的源代码, 编译安装, 也是一样.
但实际上, ld链接时提示错误:

g++ -o 1_easylogging_日志.out 1_easylogging_日志.o
/bin/ld: 1_easylogging_日志.o: in function `main':
/home/liuj/1_data/3_cpp-practice/21_开源库/17_easylogging日志库/1_easylogging_日志.cc:7: undefined reference to `el::base::Writer::construct(int, char const*, ...)'
/bin/ld: 1_easylogging_日志.o: in function `__static_initialization_and_destruction_0(int, int)':
/home/liuj/1_data/3_cpp-practice/21_开源库/17_easylogging日志库/1_easylogging_日志.cc:4: undefined reference to `el::base::Storage::Storage(std::shared_ptr<el::LogBuilder> const&)'
/bin/ld: 1_easylogging_日志.o: in function `el::LogBuilder::LogBuilder()':
/usr/include/easylogging++.h:2197: undefined reference to `el::base::utils::OS::termSupportsColor()'
/bin/ld: 1_easylogging_日志.o: in function `el::base::Writer::~Writer()':

解决方法1:
将easylogging++.cc 源代码以头文件方式导入

#include <easylogging++.h>
#include <easylogging++.cc>

解决方法2:
将libeasylogging++.cc 编译为动态库 libeasylogging.so, 拷贝到系统lib目录下 /usr/lib
本文使用的是: 解决方法2
1. 在scons中检测库/usr/lib/libeasylogging.so 存在,不存在则拷贝
2. 链接选项: -leasylogging

2.实例

1.代码

1_easylogging_日志.cc

#include <easylogging++.h>
// #include <easylogging++.cc>

INITIALIZE_EASYLOGGINGPP    // 初始化宏,有且只能使用一次

int main(int argc, char* argv[]) {
   LOG(INFO) << "My first info log using default logger";
   return 0;
}


my_log.conf

* GLOBAL:
    ENABLED                 =   true
    TO_FILE                 =   true
    TO_STANDARD_OUTPUT      =   true
    FORMAT                  =   "[%level | %datetime] | %msg"
    FILENAME                =   "log/log_%datetime{%Y%M%d}.log"
    MILLISECONDS_WIDTH      =   3
    PERFORMANCE_TRACKING    =   false
    MAX_LOG_FILE_SIZE       =   2097152 ## 2MB
    LOG_FLUSH_THRESHOLD     =   0

* TRACE:
    FILENAME                =   "log/trace_log_%datetime{%Y%M%d}.log"

* DEBUG:
    FILENAME                =   "log/debug_log_%datetime{%Y%M%d}.log"

* FATAL:
    ENABLED                 =   false

* ERROR:
    FILENAME                =   "log/error_log_%datetime{%Y%M%d}.log"

* WARNING:
    FILENAME                =   "log/warning_log_%datetime{%Y%M%d}.log"

* INFO:
    FILENAME                =   "log/info_log_%datetime{%Y%M%d}.log"

* VERBOSE:
    ENABLED                 =   false

2_easylogging_读取配置.cc

#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

int main(int argc, char** argv)
{
	el::Configurations conf("my_log.conf");
	el::Loggers::reconfigureAllLoggers(conf);

	LOG(TRACE)   << "***** trace log  *****";
	LOG(DEBUG)   << "***** debug log  *****";
	LOG(ERROR)   << "***** error log  *****";
	LOG(WARNING) << "***** warning log  *****";
	LOG(INFO)    << "***** info log  *****";

	system("pause");
	return 0;
}

3_easylogging_条件打印.cc

#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

int main(int argc, char **argv)
{
	int i = 0;
	while (i++ < 100)
	{
		//  条件日志
		LOG_IF((i % 5 == 0), INFO) << " %5 == 0" << i;
		// 每n次记录一次
		LOG_EVERY_N(20, INFO) << "LOG_EVERY_N i = " << i;
		// 当计数达到n次之后,才开始记录日志
		LOG_AFTER_N(6, INFO) << "LOG_AFTER_N i = " << i;
		// 当记录次数达到n次之后,就不再记录
		LOG_N_TIMES(1, INFO) << "LOG_N_TIMES i = " << i;
	}

	return 0;
}

2.scons编译

SConstruct

import os
env = Environment()
env["PROGSUFFIX"] = ".out"            # 可执行文件后缀.out
env["CCFLAGS"] = " -g3 -O0 -Wall"     # gdb 调试

def build_share_lib():
    SharedLibrary("easylogging","easylogging++.cc")
    # Install(target="/usr/lib",source=['easylogging.so'])  # --NG
    # Command("/usr/lib/libeasylogging.so","libeasylogging.so","sudo cp -rf libeasylogging.so /usr/lib/")    # --NG
    # Command("./lib/libeasylogging.so","libeasylogging.so","cp -rf libeasylogging.so ./lib/libeasylogging.so")  # --OK
    if not os.path.exists("/usr/lib/libeasylogging.so"):
        os.system("sudo cp -rf libeasylogging.so /usr/lib/libeasylogging.so") # --ok
        print("copy libeasylogging.so /usr/lib ---ok")
        # os.system("sudo install libeasylogging.so /usr/lib") # --ok

## 模板2
build_share_lib()
env["LIBS"] = ["easylogging"]
env.Program("1_easylogging_日志.cc", LIBS=["easylogging"],LIBPATH='.') # fix:scons无法优先编译 动态库easylogging.so
env.Program("2_easylogging_读取配置.cc")
env.Program("3_easylogging_条件打印.cc")

scons

scons: Reading SConscript files …
scons: done reading SConscript files.
scons: Building targets …
g++ -o 1_easylogging_日志.o -c -g3 -O0 -Wall 1_easylogging_日志.cc
g++ -o easylogging++.os -c -fPIC easylogging++.cc
g++ -o libeasylogging.so -shared easylogging++.os
g++ -o 1_easylogging_日志.out 1_easylogging_日志.o -L. -leasylogging
g++ -o 2_easylogging_读取配置.o -c -g3 -O0 -Wall 2_easylogging_读取配置.cc
g++ -o 2_easylogging_读取配置.out 2_easylogging_读取配置.o -leasylogging
g++ -o 3_easylogging_条件打印.o -c -g3 -O0 -Wall 3_easylogging_条件打印.cc
g++ -o 3_easylogging_条件打印.out 3_easylogging_条件打印.o -leasylogging
scons: done building targets.

3.运行

./1_easylogging_日志.out

2024-04-24 00:45:55,850 INFO [default] My first info log using default logger

./2_easylogging_读取配置.out

[TRACE | 2024-04-24 00:45:58,466] | ***** trace log  *****
[DEBUG | 2024-04-24 00:45:58,466] | ***** debug log  *****
[ERROR | 2024-04-24 00:45:58,466] | ***** error log  *****
[WARNING | 2024-04-24 00:45:58,466] | ***** warning log  *****
[INFO | 2024-04-24 00:45:58,466] | ***** info log  *****
sh: pause: command not found

./3_easylogging_条件打印.out

2024-04-24 00:46:03,897 INFO [default] LOG_N_TIMES i = 1
2024-04-24 00:46:03,897 INFO [default]  %5 == 05
2024-04-24 00:46:03,897 INFO [default] LOG_AFTER_N i = 7
2024-04-24 00:46:03,897 INFO [default] LOG_AFTER_N i = 8
2024-04-24 00:46:03,897 INFO [default] LOG_AFTER_N i = 9
2024-04-24 00:46:03,897 INFO [default]  %5 == 010
2024-04-24 00:46:03,897 INFO [default] LOG_AFTER_N i = 10
2024-04-24 00:46:03,897 INFO [default] LOG_AFTER_N i = 11
2024-04-24 00:46:03,898 INFO [default] LOG_AFTER_N i = 12
2024-04-24 00:46:03,898 INFO [default] LOG_AFTER_N i = 13
2024-04-24 00:46:03,898 INFO [default] LOG_AFTER_N i = 14
2024-04-24 00:46:03,898 INFO [default]  %5 == 015
2024-04-24 00:46:03,898 INFO [default] LOG_AFTER_N i = 15
2024-04-24 00:46:03,898 INFO [default] LOG_AFTER_N i = 16
2024-04-24 00:46:03,898 INFO [default] LOG_AFTER_N i = 17
2024-04-24 00:46:03,898 INFO [default] LOG_AFTER_N i = 18
2024-04-24 00:46:03,898 INFO [default] LOG_AFTER_N i = 19
2024-04-24 00:46:03,898 INFO [default]  %5 == 020
2024-04-24 00:46:03,898 INFO [default] LOG_EVERY_N i = 20

gitee 在线代码


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++题解】1302. 是否适合晨练?

问题&#xff1a;1302. 是否适合晨练&#xff1f; 类型&#xff1a;分支 题目描述&#xff1a; 夏天到了&#xff0c;气温太高&#xff0c;小明的爷爷每天有晨练的习惯&#xff0c;但有时候温度不适合晨练&#xff1b;小明想编写一个程序&#xff0c;帮助爷爷判断温度是否适合…

5分钟——测试搭建的springboot接口(二)

5分钟——测试搭建的springboot接口&#xff08;二&#xff09; 1. 查看数据库字段2. 测试getAll接口3. 测试add接口4. 测试update接口5. 测试deleteById接口 1. 查看数据库字段 2. 测试getAll接口 3. 测试add接口 4. 测试update接口 5. 测试deleteById接口

计算机网络-IS-IS基础配置实验

前面我们了解了IS-IS的一些基础理论&#xff0c;从建立邻接、链路状态数据库同步以及路由计算&#xff0c;现在开始学习下配置操作。 一、IS-IS配置 网络拓扑图&#xff1a; 拓扑图 IS-IS有Level级别的区分&#xff0c;Level-1可以是性能较低的设备只维护区域内的LSDB&#xff…

论文辅助笔记:LLM-MOB代码解读

论文笔记 Where Would I Go Next? Large Language Models as Human Mobility Predictor-CSDN博客 1 主函数 1.1 导入库 import os import pickle import time import ast import logging from datetime import datetime import pandas as pd from openai import OpenAIclie…

Sqli-labs靶场第25关[Sqli-labs-less-25]自动化注入-SQLmap工具注入

过滤了AND OR 使用的函数是 preg_replace 特点&#xff1a;只对值进行一次检测闭合方式为 单引号 可以使用双写进行绕过 手工注入 ?id0 union select 1,database(),user() -- sqlmap自动化注入 sqlmap.py -u http://192.168.58.114:802/sqli-labs/Less-25/?id2 --batch -…

Aurora-64B/10B、XDMA与DDR结合设计高速数据流通路设计/Aurora光纤设计/XDMA读取DDR设计/基于FPGA的高速数据传输设计

因最近想通过FPGA把数据从光纤传到PC&#xff0c;借此机会和大家一起学习Aurora、XDMA结合DDR 制作不易&#xff0c;记得三连哦&#xff0c;给我动力&#xff0c;持续更新&#xff01;&#xff01;&#xff01; 完整工程文件下载&#xff1a;XDMA读写DDR工程 提取码&…

[Algorithm][前缀和][和为K的子数组][和可被K整除的子数组][连续数组][矩阵区域和]详细讲解

目录 1.和为 K 的子数组1.题目链接2.算法原理详解3.代码实现 2.和可被 K 整除的子数组1.题目链接2.算法原理详解3.代码实现 3.连续数组1.题目链接2.算法原理详解3.代码实现 4.矩阵区域和1.题目链接2.算法原理详解3.代码实现 1.和为 K 的子数组 1.题目链接 和为 K 的子数组 2.…

网络安全攻击溯源的重要性及挑战

网络安全攻击溯源是一个复杂且至关重要的过程&#xff0c;它涉及对网络攻击事件的来源进行追踪和分析&#xff0c;以便确定攻击者的身份、动机和攻击路径。在IP技术背景下&#xff0c;网络安全攻击溯源更是显得尤为重要&#xff0c;因为IP地址作为网络设备的唯一标识&#xff0…

Kafka 3.x.x 入门到精通(02)——对标尚硅谷Kafka教程

Kafka 3.x.x 入门到精通&#xff08;02&#xff09;——对标尚硅谷Kafka教程 2. Kafka基础2.1 集群部署2.1.1 解压文件2.1.2 安装ZooKeeper2.1.3 安装Kafka2.1.4 封装启动脚本 2.2 集群启动2.2.1 相关概念2.2.1.1 代理&#xff1a;Broker2.2.1.2 控制器&#xff1a;Controller …

css中新型的边框设置属性border-inline

一、概念与背景 border-inline 是 CSS Logical Properties and Values 模块中的一个属性&#xff0c;用于控制元素在流内&#xff08;inline&#xff09;方向上的边框。该模块旨在提供与书写模式&#xff08;writing mode&#xff09;无关的布局和样式描述方式&#xff0c;使得…

【现代交换原理与通信网技术】期末突击

文章目录 自己老师画的重点1. 程控交换机结构2. 测试模拟电路的七项功能3.中继电路的六项功能4.数字用户电路和模拟用户电路比较5.路由规划的基本原则6.七路信令的结构7.随路信令和公共信道信令8.软交换9.无极网和分级网10.路由选择.流量控制的原则/方法11.电路交换&&分…

解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务(Spring MVC Springboot)同时允许跨域

解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务&#xff08;Spring MVC Springboot&#xff09;同时允许跨域 Tomcat 配置允许跨域Web 项目配置允许跨域Tomcat 同时允许静态文件和 Web 服务跨域 偶尔遇到一个 Tomcat 部署项目跨域问题&#xff0c;因为已经处理过…

企业微信hook接口协议,ipad协议http,外部联系人图片视频文件下载

外部联系人文件下载 参数名必选类型说明file_id是StringCDNkeyopenim_cdn_authkey是String认证keyaes_key是Stringaes_keysize是int文件大小 请求示例 {"url": "https://imunion.weixin.qq.com/cgi-bin/mmae-bin/tpdownloadmedia?paramv1_e80c6c6c0cxxxx3544d9…

设计模式-状态模式在Java中的使用示例-信用卡业务系统

场景 在软件系统中&#xff0c;有些对象也像水一样具有多种状态&#xff0c;这些状态在某些情况下能够相互转换&#xff0c;而且对象在不同的状态下也将具有不同的行为。 为了更好地对这些具有多种状态的对象进行设计&#xff0c;我们可以使用一种被称之为状态模式的设计模式…

【Android】android 10 jar_sdk_library添加

前言 当前项目遇到客户&#xff0c;Android 10 平台&#xff0c;需要封装jar_sdk_library给第三方应用使用。其中jar_sdk_library中存在aidl文件。遇到无法编译通过问题。 解决 system/tools/aidl修改 Android.bp修改

vue中web端播放rtsp视频流(摄像头监控视频)(海康威视录像机)

一、ffmpeg安装​​​​​​ ffmpeg下载 https://ffmpeg.org/download.html找ffmpeg-release-essentials.zip点击下载&#xff0c;下载完解压ffmpeg.exe 程序运行 二、配置ffmpeg环境变量 添加成功后验证是否生效任意地方打开cmd窗口输入 ffmpeg 打印如下表示成功 三、node…

Ribbon负载均衡器

1. 负载均衡器 目前主流的负载方案分为以下两种&#xff1a;&#xff08;面试题&#xff09; 1.1 服务端负载均衡 在消费者和服务提供方中间使用独立的代理方式进行负载&#xff0c;有硬件的&#xff08;比如 F5&#xff09;&#xff0c;也有软件的&#xff08;比如 Nginx&a…

【重磅开源】MapleBoot项目开发规范

基于SpringBootVue3开发的轻量级快速开发脚手架 &#x1f341;项目简介 一个通用的前、后端项目模板 一个快速开发管理系统的项目 一个可以生成SpringBootVue代码的项目 一个持续迭代的开源项目 一个程序员的心血合集 度过严寒&#xff0c;终有春日&#xff…

uniapp配置了pages.json 的 tabbar 国际化,小程序切换语言没有实时切换

如上图&#xff0c;按照uniapp官方文档配置了tabbar的国际化 但是微信小程序实时切换语言没有实时刷新 解决方案&#xff1a; 在App.vue中加入以下代码&#xff1a; 在onLaunch中执行方法即可

LLM大语言模型(十二):关于ChatGLM3-6B不兼容Langchain 的Function Call

背景 基于本地的ChatGLM3-6B直接开发LangChain Function Call应用&#xff0c;发现其输出的action和action_input非常不稳定。 表现为生成的JSON格式回答非常容易出现不规范的情况&#xff0c;导致LangChain的Agent执行报错&#xff0c;或者进入死循环。 ChatGLM3-6B不兼容La…
最新文章