linux 使用log4cpp记录项目日志

为什么要用log4cpp记录项目日志

在通常情况下,Linux/UNIX 每个程序在开始运行的时刻,都会打开 3 个已经打开的 stream. 分别用来输入,输出,打印错误信息。通常他们会被连接到用户终端。这 3 个句柄的类型为指向 FILE 的指针。可以被 fprintf、fread等函数使用,他们在程序开始启动后,stdin, stdout, and stderr 的文件描述符是 0, 1 和 2,其它的文件描述符则排在其后。

很多时候会用 printf 打印信息来调试程序,但是如果终端关掉了,那怎么显示 printf 的调试信息呢?log4cpp就可以解决这个问题.

1 log4cpp安装

  • wget https://nchc.dl.sourceforge.net/project/log4cpp/log4cpp-1.1.x%20%28ne
    w%29/log4cpp-1.1/log4cpp-1.1.3.tar.gz
  • tar -zxvf log4cpp-1.1.3.tar.gz
  • cd log4cpp
  • ./configure --prefix=安装路径
  • make
  • make install

2确定 log4cpp 头文件&库

找头文件./log4cpp/include/log4cpp
在这里插入图片描述找到对应的库./log4cpp/src/.libs
在这里插入图片描述

3 log4cpp日志说明

3-1 设置日志信息输出方式

#include <log4cpp/Category.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/OstreamAppender.hh>

// 以root的身份将信息输出到 std::cout
//log4cpp::Appender *appender = new log4cpp::OstreamAppender("root",&std::cout);

// 以root的身份将信息输出到 log 文件
log4cpp::Appender *appender = new log4cpp::FileAppender("root","test.log");
日志信息appender方式注释
log4cpp::FileAppender输出到文件
log4cpp::RollingFileAppender输出到回卷文件,即当文件到达某个大小后回卷
log4cpp::OstreamAppender输出到一个 ostream 类
log4cpp::RemoteSyslogAppender输出到远程 syslog 服务器
log4cpp::StringQueueAppender内存队列
log4cpp::SyslogAppender本地 syslog
log4cpp::Win32DebugAppender发送到缺省系统调试器
log4cpp::NTEventLogAppender发送到 win 事件日志

日志输出到终端或者文件中实际上是很慢的,会引起 IO 中断,可以输出到内存里 StringQueueAppender,然后从
StringQueueAppender 输出到其它地方,这样线程执行效率是比较高效的。

3-2 设置日志信息输出格式

log4cpp::PatternLayout *patternLayout = new log4cpp::PatternLayout();
patternLayout->setConversionPattern("%d [%p] - %m%n");
appender->setLayout(patternLayout);

patternLayout->setConversionPattern( )支持以下一组格式字符:

日志格式字符注释
%%百分比符号
%c日志类别
%d日期格式:日期格式字符后面可以跟一个日期格式,括在大括号之间的说明符。例如,%d{%\H:%M:%S,%l}%d{%S\d%M%Y%H:%\M:%S,%l}。如果没有给出日期格式说明符,则使用以下式:“Wed Jan 02 02:03:55 1980”。%l表示毫秒。
%m消息
%n特定于平台的行分隔符
%p优先级
%r自创建此布局以来的毫秒
%R自1970年1月1日起的秒数(时间戳)
%u进程启动后的时钟周期
%xNDC
%t线程名称

默认情况下,PatternLayout->ConversionPattern( )设置为“%m%n”。

3-3 设置 日志输出类别(category) 和 日志优先级(priority)

log4cpp::Category &root = log4cpp::Category::getRoot();		//设置在配置文件里
root.setPriority(log4cpp::Priority::NOTICE);
root.addAppender(appender);

日志的级别总共有:
NOTSET < DEBUG < INFO < NOTICE < WARN < ERROR < CRIT < ALERT <FATAL = EMERG。
日志级别的意思是低于该级别的日志不会被记录。

3-4设置 日志操作的宏

#define LOG(__level) 
log4cpp::Category::getRoot() <<log4cpp::Priority::__level << __FILE__ << " " << __LINE__ << ": "

3-5 使用 日志操作的宏 记录日志

LOG(DEBUG) << "i am happy.";
LOG(INFO)  << "oh, you happy, we happy.";
LOG(NOTICE)<< "please do not contact me. ";
LOG(WARN)  << "i am very busy now.";
LOG(ERROR) << "oh, what happed?";

4 使用封装log4cpp(单例)并使用Cmake编译项目

4-0 log4cpp_demo.conf

#定义 rootCategory 的属性
log4cpp.rootCategory=DEBUG, RootLog

#定义 RootLog 属性
log4cpp.appender.RootLog                 = RollingFileAppender
log4cpp.appender.RootLog.layout          = PatternLayout
log4cpp.appender.RootLog.layout.ConversionPattern=%d{%m - %d %H:%M:%S %l} [%t][%p]%m%n
log4cpp.appender.RootLog.fileName        =./log4cpp_Loger.log
log4cpp.appender.RootLog.maxFileSize     =268435456 #256MB
log4cpp.appender.RootLog.fileNamePattern =log4cpp_Loger%i.log
log4cpp.appender.RootLog.maxBackupIndex  =256

4-1 Loger.h

#ifndef DISTRIBUTED_LOGGER_H_
#define DISTRIBUTED_LOGGER_H_

#include <string>
#include <log4cpp/Category.hh>

#define LOG_INFO   Logger::instance()->GetHandle()->info
#define LOG_DEBUG  Logger::instance()->GetHandle()->debug
#define LOG_ERROR  Logger::instance()->GetHandle()->error
#define LOG_WARN   Logger::instance()->GetHandle()->warn

class Logger
{
public:
        Logger();

        ~Logger();
        //初始化
        bool init(const std::string &log_conf_file);
        //获取单例
        static Logger* instance() { return &instance_; }
        //获取使用日志接口
        log4cpp::Category* GetHandle() { return category_; };

protected:
        //对象实例
        static Logger  instance_;

        log4cpp::Category* category_;

};

#endif

4-2 Loger.cpp

#include "Loger.h"
#include <iostream>
#include <log4cpp/Category.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/RemoteSyslogAppender.hh>
#include <log4cpp/PropertyConfigurator.hh>

Logger  Logger::instance_;
Logger::Logger()
{}

Logger::~Logger()
{}

bool Logger::init(const std::string& log_conf_file)
{
        try
        {
          		  //日志输出
                log4cpp::PropertyConfigurator::configure(log_conf_file);
        }
        catch (log4cpp::ConfigureFailure &f)
        {
                std::cerr << "load log config file" << log_conf_file.c_str() << "failed with result:" << f.what() << std::endl;
                return false;
        }
        category_ = &log4cpp::Category::getRoot();
        return true;
}

4-3 main.cpp

#include "Loger.h"
#include <iostream>
#include <unistd.h>

using namespace std;
int main(int argc, char **argv) {

        if (argc != 2)//传入参数不合法
        {
                printf("Please input format< your process > < .conf file config >!\n");
                return -1;
        }

        Logger* config= Logger::instance();//配置文件加载信息
        if (!config->init(std::string(argv[1]))) //配置文件加载失败
        {
                printf("load %s failed.\n", argv[1]);
                return -2;
        }
	    LOG_DEBUG("load %s finsh.",argv[1]);
	    return 0;
}

4-4 CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION  3.5)
#工程名
PROJECT(log4cpp_demo)
#将指定的目录头文件添加到编译器的头文件搜索路径之下
INCLUDE_DIRECTORIES(./third/include)

#将指定的目录库文件添加需要链接的库文件目录之下
LINK_DIRECTORIES(./third/lib/log4cpp)

#内置变量:CMAKE_SOURCE_DIR 定义了顶级CMakeLists.txt 所在文件夹
#PROJECT_SOURCE_DIR定义了包含project()命令的CmakeLists.txt所在的文件夹
#搜集所有在指定路径下的源文件名,将输出结果储存在指定的变量中
aux_source_directory(${PROJECT_SOURCE_DIR} SOURCE_FILES)

#使用给定的源文件,为工程引入一个可执行文件
ADD_EXECUTABLE(log4cpp_demo ${SOURCE_FILES})

#用来显示的定义变量(注意:加上-pthread)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}-pthread  -rdynamic -Wall -g3 -m64 -pipe -std=c++0x -lrt -Wno-reorder -Wdeprecated-declarations -fpermissive ")

#该指令的作用为目标文件与库文件进行链接
#TARGET_LINK_LIBRARIES(log4cpp_demo log4cpp)
target_link_libraries(log4cpp_demo pthread)
target_link_libraries(${PROJECT_NAME} liblog4cpp.a)
#设置默认安装目录
SET(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR})

#安装
INSTALL(TARGETS log4cpp_demo DESTINATION bin)

4-5 编译项目

  • cmake .
  • make

在这里插入图片描述

4-6 执行程序

在这里插入图片描述

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

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

相关文章

Spring循环引用和三级缓存

前言 Spring 解决 Bean 之间的循环引用关系用到了三级缓存&#xff0c;那么问题来了。三级缓存是怎么用的&#xff1f;每一层的作用是什么&#xff1f;非得用三级吗&#xff1f;两级缓存行不行&#xff1f; 理解循环引用 所谓的“循环引用”是指 Bean 之间的依赖关系形成了一…

【算法刷题】Day28

文章目录 1. 买卖股票的最佳时机 III题干&#xff1a;算法原理&#xff1a;1. 状态表示&#xff1a;2. 状态转移方程3. 初始化4. 填表顺序5. 返回值 代码&#xff1a; 2. Z 字形变换题干&#xff1a;算法原理&#xff1a;1. 模拟2. 找规律 代码&#xff1a; 1. 买卖股票的最佳时…

PostGIS学习教程二十:3-D

PostGIS学习教程二十&#xff1a;3-D 注意&#xff1a;本文介绍许多PostGIS2.0及更高版本才支持的功能。 文章目录 PostGIS学习教程二十&#xff1a;3-D一、3-D几何图形二、3-D函数三、N-D索引 一、3-D几何图形 到目前为止&#xff0c;我们一直在处理2-D几何图形&#xff08;…

firewalld防火墙命令行工具

firewall-cmd命令 &#xff08;1&#xff09;启动、停止、查看firewalld服务 在安装CentOS 7系统时&#xff0c;会自动安装firewalld 和图形化工具firewall-config.执行以下命令可 以启动 firewalld 并设置为开机自启动状态。 [rootllcgc ~]# systemctl start firewalld.serv…

【SpringCloud】之入门级及nacos的集成使用

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringCloud开发之入门级及nacos》。&#x1f3…

数据库内核那些事|细说PolarDB优化器查询变换:IN-List变换

导读 数据库的查询优化器是整个系统的"大脑"&#xff0c;一条SQL语句执行是否高效在不同的优化决策下可能会产生几个数量级的性能差异&#xff0c;因此优化器也是数据库系统中最为核心的组件和竞争力之一。阿里云瑶池旗下的云原生数据库PolarDB MySQL版作为领先的云…

36-javascript输出方式,弹框:普通,confirm弹框,prompt弹框,控制台输出:普通,warm,error

1.页面打印 <body><p>你真是一个小机灵鬼</p><script>// 页面打印document.write("打印内容");</script> </body> 2.覆盖文档 <body><p>你真是一个小机灵鬼</p><script>// 覆盖文档window.onload f…

模型容器与AlexNet构建

一、模型容器——Containers nn.Sequential 是 nn.module的容器&#xff0c;用于按顺序包装一组网络层 Sequential 容器 nn.Sequential 是 nn.module的容器&#xff0c;用于按顺序包装一组网络层 • 顺序性&#xff1a;各网络层之间严格按照顺序构建 • 自带forward()&#xf…

HACKTHEBOX通关笔记——Poison(退役)

调试网络连通性 拿到IP我们还是做一下nmap扫描&#xff0c;快速速率扫描结合-A详细扫描&#xff0c;事半功倍 nmap --rate-min 5000 -p- 10.129.58.204 -vnmap -A -p 22,80 10.129.58.204 -v 发现http是一个可以读取文件的页面 这台主机似乎没办法做目录扫描&#xff0c;一扫…

电脑找不到ffmpeg.dll的解决方法有哪些,分享5种可靠的方法

在计算机编程和多媒体处理领域&#xff0c;ffmpeg.dll是一个非常重要的动态链接库文件。它是由FFmpeg项目开发和维护的&#xff0c;FFmpeg是一个开源的音视频处理框架&#xff0c;提供了一套完整的音视频编解码、转码、流化、滤镜等功能。ffmpeg.dll是FFmpeg库的一部分&#xf…

SwiftUI之深入解析Alignment Guides的超实用实战教程

一、Alignment Guide 简介 Alignment guides 是一个强大的布局工具&#xff0c;但通常未被充分利用。在很多情况下&#xff0c;它们可以帮助我们避免更复杂的选项&#xff0c;比如锚点偏好。如下所示&#xff0c;对对齐的更改也可以自动&#xff08;并且容易地&#xff09;动画…

MySQL语法及IDEA使用MySQL大全

在项目中我们时常需要写SQL语句&#xff0c;或简单的使用注解直接开发&#xff0c;或使用XML进行动态SQL之类的相对困难的SQL&#xff0c;并在IDEA中操控我们的SQL&#xff0c;但网上大都图方便或者觉得太简单了&#xff0c;完全没一个涵盖两个方面的讲解。 单表&#xff1a; …

GO语言笔记3-指针

指针的概念 先看一段代码的输出 package main import "fmt" func main(){ var age int 18fmt.Println("age的内存地址值是:",&age)//age的内存地址值是: 0xc000012090// 定义一个指针变量// *int 是一个指针类型&#xff0c;可以理解为指向int类型的…

TEMU 新手小白必看!2024入驻流程/入驻类目/入驻资料等详细流程讲解

2023 TEMU 可谓是赚足眼球&#xff0c;流量持续上涨&#xff0c;2024年相信不少卖家们已经跃跃欲试&#xff0c;但大陆卖家如何入驻TEMU&#xff1f;哪些品类适合入驻&#xff1f;又有哪些入驻要求和资料&#xff1f;别急&#xff0c;今天东哥就一一给大家详细讲解&#xff0c;…

Python操作excel-读取、表格填充颜色区分

1.场景分析 遇到一个需要读取本地excel数据&#xff0c;处理后打入到数据库的场景&#xff0c;使用java比较重&#xff0c;python很好的解决了这类问题 2.重难点 本场景遇到的重难点在于&#xff1a; 需要根据表格内的背景颜色对数据进行筛选 读取非默认Sheet 总是出现Value…

UE5 使用动画模板创建多个动画蓝图

我们制作游戏的时候&#xff0c;角色会根据不同的武器表现出来不同的攻击动画&#xff0c;待机动画以及移动动画。如果我们在UE里面实现这个需求&#xff0c;是通过复制粘贴的方式修改&#xff0c;还是有更好的方式。 这里就需要介绍一下动画模板&#xff0c;我们可以将动画蓝图…

在黑马程序员大学的2023年终总结

起笔 时间真快&#xff0c;转眼又是年末。是时候给2023做个年终总结了&#xff0c;为这一年的学习、生活以及成长画上一个圆满的句号。 这一年相比去年经历了很多事情&#xff0c;接下来我会一一说起 全文大概4000字&#xff0c;可能会占用你15分钟左右的时间 经历 先来给大…

外包干了3个多月,技术退步明显

先说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

【STM32】WDG看门狗

1 WDG简介 WDG&#xff08;Watchdog&#xff09;看门狗 看门狗可以监控程序的运行状态&#xff0c;当程序因为设计漏洞、硬件故障、电磁干扰等原因&#xff0c;出现卡死或跑飞现象时&#xff0c;看门狗能及时复位程序&#xff0c;避免程序陷入长时间的罢工状态&#xff0c;保…

解决不同请求需要的同一实体类参数不同(分组校验validation)

问题概述 新增目录是自动生成id&#xff0c;不需要id参数&#xff1b;更新目录需要id&#xff0c;不能为空 pom.xml中已有spring-boot-starter-validation依赖 <!--validation(完成属性限制&#xff0c;参数校验)--><dependency><groupId>org.springframew…