玫琳凯网站建设与推广方案,设计手机商城网站建设,食品包装设计规范及包装标准,wordpress资源消耗1、log4cpp概述
Log4cpp是一个开源的C类库#xff0c;它提供了C程序中使用日志和跟踪调试的功能#xff0c;它的优点如下#xff1a; 提供应用程序运行上下文#xff0c;方便跟踪调试#xff1b; 可扩展的、多种方式记录日志#xff0c;包括命令行、文件、回卷文件、内…1、log4cpp概述
Log4cpp是一个开源的C类库它提供了C程序中使用日志和跟踪调试的功能它的优点如下 提供应用程序运行上下文方便跟踪调试 可扩展的、多种方式记录日志包括命令行、文件、回卷文件、内存、syslog服务器、Win事件日志等 可以动态控制日志记录级别在效率和功能中进行调整 所有配置可以通过配置文件进行动态调整 多语言支持包括Javalog4jClog4cpp、log4cplusClog4cpythonlog4p等
类似日志工具glog、boost.log、spdlog 2、原理
Log4cpp有三个主要的组件日志类别Category、输出源Appender和布局Layout。这三种类型的组件一起工作使得系统可以根据信息的类型和级别记录它们并且在运行时控制这些信息的输出格式和位置。
三个组件的介绍
1日志类别Category含义是如果配置文件中设置的级别是DEBUG则任意的log都能打印出来但如果配置的级别是ERROR,则只有高于ERROR优先级的日志才可以打印出来。
日志的常用优先级DEBUG INFO WARN ERROR FATAL
2输出源Appender用来输出日志被layout格式化后到一些设备上比如文件、命令行、内存等。也可以定义自己的appender输出日志信息到别的设备上。log4cpp提供的appender如下 FileAppender 输出到文件 RollingFileAppender 输出到回卷文件即当文件到达某个大小后回卷 ConsoleAppender 输出到控制台
3布局Layout显示样式PatternLayout表示让用户根据类似于C语言printf函数的转换模式来指定输出格式
三个组件之间的关系 Category和Appender的关系是多个Appender可以附加到一个Category上这样一个日志消息可以同时输出到多个设备上。 Appender和Layout的关系是Layout附加在Appender上appender调用layout处理完日志消息后记录到某个设备上。
3 log4cplus的安装
log4cplus是开源的源代码可在这里找到。下载源代码压缩包后解压进入主目录。和大多数autotools工程一样顺序执行以下命令即可完成安装。
./configure
make
make install
安装文件将默认安装到/usr/local库文件置于/usr/local/lib头文件置于/usr/local/include。
是的这里介绍的安装及下面介绍的应用都是基于linux系统。
4 log4cplus的使用
以下是官方提供的“hello, world”的示例程序
#include log4cplus/logger.h
#include log4cplus/loggingmacros.h
#include log4cplus/configurator.h
#include iomanipusing namespace log4cplus;int main()
{BasicConfigurator config;config.configure();Logger logger Logger::getInstance(LOG4CPLUS_TEXT(main));LOG4CPLUS_WARN(logger, LOG4CPLUS_TEXT(Hello, World!));return 0;
}
程序包含了一些必要的头文件编译时需要链接log4cplus库将这段代码保存为 test.cpp执行以下命令编译
g test.cpp -o test -llog4cplus
编译后生成 test 可执行文件运行./test得到如下输出
WARN - Hello, World!
这个程序使用的是log4cplus内置的默认配置选项实际使用中一般要自己配置选项接下来你会看到。
相关视频推荐
如何设计高效日志库
C Golang日志库Glog源码分析
c后端绕不开的7个开源项目每一个源码值得深入研究
免费学习地址c/c linux服务器开发/后台架构师
需要C/C Linux服务器架构师学习资料加qun812855908获取资料包括C/CLinuxgolang技术NginxZeroMQMySQLRedisfastdfsMongoDBZK流媒体CDNP2PK8SDockerTCP/IP协程DPDKffmpeg等免费分享 5 log4cplus配置
log4cplus配置就是定义appender, 定义输出的格式即 layout。以下列出两种常用配置以供参考。
配置输出到控制台通常用于前台程序
log4cplus.logger.logmain TRACE, console
log4cplus.appender.console log4cplus::ConsoleAppender
log4cplus.appender.console.layout log4cplus::PatternLayout
log4cplus.appender.console.layout.ConversionPattern [%D{%m/%d/%y %H:%M:%S,%q} %-5p] - %m%n
配置输出到文件通常用于后台程序
log4cplus.logger.logmain INFO, file
log4cplus.appender.file log4cplus::FileAppender
log4cplus.appender.file.File /var/log/myapp.log
log4cplus.appender.file.MaxFileSize 10M
log4cplus.appender.file.Append true
log4cplus.appender.file.layout log4cplus::PatternLayout
log4cplus.appender.file.layout.ConversionPattern [%D{%m/%d/%y %H:%M:%S,%q} %-5p] - %m%n
简单说明一下配置文件中log4cplus.logger.logmain即定义一个logmain对象后面跟的两个字段前一个表示log级别后一个指定使用的appender即日志输出对象。log级别按严重程度从低到高依次为TRACE、DEBUG、INFO、WARN、ERROR、FATAL。log4cplus.appender.xxx定义具体的appender属性如是控制台还是文件进一步配置文件名、文件大小等。
将配置保存到一个配置文件中如log4cplus.conf以下你将看到如何使用配置文件。有关更详细的配置读者可自行摸索。
6 log4cplus运用于项目
以上“hello, world”程序只是大概演示log4cplus的用法实际项目使用要有系统观念就是怎样用才更方便我们可以再做点封装。我们可以定义一个全局logger对象将log4cplus初始化配置放到一个源文件中重新定义一些简化的宏置于头文件比如笔者就定义了Log.h/Log.cpp两个文件代码如下
Log.h文件
#pragma once#include log4cplus/logger.h
#include log4cplus/loggingmacros.husing namespace log4cplus;
using namespace log4cplus::helpers;// global object
extern Logger logger;// define some macros for simplicity
#define LOG_TRACE(logEvent) LOG4CPLUS_TRACE(logger, logEvent)
#define LOG_DEBUG(logEvent) LOG4CPLUS_DEBUG(logger, logEvent)
#define LOG_INFO(logEvent) LOG4CPLUS_INFO(logger, logEvent)
#define LOG_WARN(logEvent) LOG4CPLUS_WARN(logger, logEvent)
#define LOG_ERROR(logEvent) LOG4CPLUS_ERROR(logger, logEvent)
#define LOG_FATAL(logEvent) LOG4CPLUS_FATAL(logger, logEvent)extern void InitLogger(bool daemonized);
Log.cpp文件
#include log4cplus/logger.h
#include log4cplus/consoleappender.h
#include log4cplus/fileappender.h
#include log4cplus/layout.h
#include log4cplus/configurator.h#include Log.hLogger logger Logger::getInstance(LOG4CPLUS_TEXT(logmain));void InitLogger(bool daemonized)
{if (daemonized)PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT(/your/path/log4cplusd.conf));elsePropertyConfigurator::doConfigure(LOG4CPLUS_TEXT(/your/path/log4cplus.conf));
}
将这两个文件置于你的项目中然后在 main 函数中调用 InitLogger() 初始化 log4cplus再在需要加log的文件中包含Log.h即可。注意InitLogger函数的参数daemonized该参数表示应用程序是否是守护进程后台运行一般我们开发的应用程序大多是守护进程linux后台服务大多是守护进程但调试的时候会前台运行对于守护进程我们只需要把日志记录到某个文件中就行了而对于前台调试运行我们就只需要将日志输出到控制台所以这里是一点使用技巧。做到这点我们只需分别提供两个配置文件即可/your/path就是你放置配置文件的地方一般可以设为你应用程序部署的目录下的etc目录。
至此我们可以使用log4cplus了以下是实际的日志输出效果
[11/05/12 10:28:36,002 INFO ] - TCPDomain - TCPDomain()
[11/05/12 10:28:36,002 INFO ] - TCPDomain - Connect server success!
[11/05/12 10:28:36,002 TRACE] - Session - Thread run.
[11/05/12 10:28:46,006 ERROR] - TCPDomain - SelectRead time out!
[11/05/12 10:28:56,016 ERROR] - TCPDomain - SelectRead time out!
7 log4cplus交叉编译
对于嵌入式应用 有交叉编译这么一说。以上的介绍是基于PC的如果你的平台是嵌入式平台如arm则只需编译链接arm平台的log4cplus库即可其它都一样。对于大多数autotools工程其交叉编译方法大致如下
./configure --prefix/your/install/path --hostarm-linux CXXyour-toolkit-g
make
make install
其中--prefix即指定你的安装目录如/opt/log4cplus--host指定目标平台CXX指定你的交叉编译工具确保shell环境能找到该工具。编译安装完后可在安装目录找到arm版本的库文件。
8 总结
日志固然好但也不建议随意使用用多了会导致程序性能有所下降且代码size增加不少。以上是笔者运用log4cplus的些许经验更深一步的原理机制有待进一步探究。
配置文件 1 #-------定义rootCategory的属性-------2 3 #指定rootCategory的log优先级是ERROR其Appenders有两个分别是console,TESTAppender4 log4cpp.rootCategoryERROR, console,TESTAppender5 6 #-------定义console属性-------7 8 #consoleAppender类型:控制台输出9 #下面这三条语句表示控制台输出的log输出的布局按照指定的格式输出格式是[%p] %d{%H:%M:%S.%l} (%c): %m%n
10 log4cpp.appender.consoleConsoleAppender
11 log4cpp.appender.console.layoutPatternLayout
12 log4cpp.appender.console.layout.ConversionPattern[%p] %d{%H:%M:%S.%l} (%c): %m%n
13
14 #-------定义TESTAppender的属性-------
15
16 #RollingFileAppender类型输出到回卷文件即文件到达某个大小的时候产生一个新的文件
17 #下面的语句表示文件输出到指定的log文件输出的布局按照指定的格式输出的格式是[%d{%Y-%m-%d %H:%M:%S.%l} - %p] (%c): %m%n
18 log4cpp.appender.TESTAppenderRollingFileAppender
19
20 #当日志文件到达maxFileSize大小时将会自动滚动
21 log4cpp.appender.TESTAppender.maxFileSize400000
22
23 #maxBackupIndex指定可以产生的滚动文件的最大数
24 log4cpp.appender.TESTAppender.maxBackupIndex3
25
26 #fileName指定信息输出到logs/TESTAppender.txt文件
27 log4cpp.appender.TESTAppender.fileNamelogs/TESTAppender.txt
28
29 #PatternLayout 表示可以灵活指定布局模式
30 log4cpp.appender.TESTAppender.layoutPatternLayout
31
32 #appendtrue 信息追加到上面指定的日志文件中false表示将信息覆盖指定文件内容
33 log4cpp.appender.TESTAppender.appendtrue
34 log4cpp.appender.TESTAppender.layout.ConversionPattern[%d{%Y-%m-%d %H:%M:%S.%l} - %p] (%c): %m%n ConversionPattern的参数含义%d 输出日志时间点的日期或时间可以在其后指定格式如上%d{%Y-%m-%d %H:%M:%S.%l}输出类似2017-02-14 09:25:00.953
%p 优先级即DEBUG,INFO,WARN,ERROR,FATAL
%c 输出日志信息所属的类目通常就是所在类的全名
%m 输出log的具体信息
%n 回车换行
自定义封装
将上述过程封装即可得到自己的日志类
/*采用单例模式设计包含两个category对象一个负责输出到屏幕的信息一个负责记录到日志的信息通过设置优先级差别可以实现所有信息都记录在日志中遇到error及以上的信息时打印到屏幕上*/
class MyLog
{
private:MyLog(bool b){outToScreen b;}~MyLog(){}static MyLog * log;bool outToScreen;//是否输出日志信息到屏幕static std::string _screenInfo;//屏幕日志信息static std::string _logName;//文件日志名称static log4cpp::Category logCat;static log4cpp::Category coutCat;static log4cpp::FileAppender* logFile;//文件日志输入static log4cpp::OstreamAppender* logScreen;//屏幕日志输入static log4cpp::Priority::PriorityLevel logPri;//文件日志优先级static log4cpp::Priority::PriorityLevel coutPri;//屏幕日志优先级static log4cpp::PatternLayout* logLayout;//日志布局 static log4cpp::PatternLayout* screenLayout;//屏幕布局
public://获取日志函数,默认参数选择是否输出到屏幕static MyLog* getLog(bool toScreen true,std::string coutName screenInfo,std::string logName log){if(MyLog::log NULL){MyLog::log new MyLog(toScreen);MyLog::_logName logName;MyLog::_screenInfo coutName;logScreen new log4cpp::OstreamAppender(logScreen,std::cout);logFile new log4cpp::FileAppender(logFile,MyLog::_logName);//设置布局MyLog::logLayout new log4cpp::PatternLayout();MyLog::screenLayout new log4cpp::PatternLayout();logLayout-setConversionPattern(%d{%Y/%m/%d,%H:%M:%S} -- [%p] %c: %m%n);screenLayout-setConversionPattern(%d{%Y/%m/%d %H:%M:%S} -- [%p] %c: %m%n);MyLog::logScreen-setLayout(screenLayout);MyLog::logFile-setLayout(logLayout);//追加到目录MyLog::logCat.addAppender(MyLog::logFile);MyLog::coutCat.addAppender(MyLog::logScreen);//设置优先级MyLog::logCat.setPriority(MyLog::logPri);MyLog::coutCat.setPriority(MyLog::coutPri);}MyLog::log-outToScreen toScreen;return MyLog::log;}//销毁日志对象static void destoryLog(){log4cpp::Category::shutdown();delete MyLog::log;}//设置日志记录优先级static void setPri(log4cpp::Priority::PriorityLevel coutLevel,log4cpp::Priority::PriorityLevel logLevel){MyLog::logPri logLevel;MyLog::coutPri coutLevel;MyLog::logCat.setPriority(MyLog::logPri);MyLog::coutCat.setPriority(MyLog::coutPri);}//记录日志,调用参数__FILE__, __LINE__ ,__FUNCTION__void warn(const char * msg,const char *filename __FILE__,int line __LINE__,const char *function warn){char info[4096] {0};sprintf(info,\nIn file %s,line %d,function %s:%s,filename,line,function,msg);if(this-outToScreen){logCat.warn(info);coutCat.warn(info);}else{logCat.warn(info);}}void error(const char * msg,const char *filename __FILE__,int line __LINE__,const char *function error){char info[4096] {0};sprintf(info,\nIn file %s,line %d,function %s:%s,filename,line,function,msg);if(this-outToScreen){logCat.error(info);coutCat.error(info);}else{logCat.error(info);}}void debug(const char * msg,const char *filename __FILE__,int line __LINE__,const char *function debug){char info[4096] {0};sprintf(info,\nIn file %s,line %d,function %s:%s,filename,line,function,msg);if(this-outToScreen){logCat.debug(info);coutCat.debug(info);}else{logCat.debug(info);}}void info(const char * msg,const char *filename __FILE__,int line __LINE__,const char *function info){char info[4096] {0};sprintf(info,\nIn file %s,line %d,function %s:%s,filename,line,function,msg);if(this-outToScreen){logCat.info(info);coutCat.info(info);}else{logCat.info(info);}}
};
MyLog* MyLog::log NULL;
std::string MyLog::_screenInfo screenInfo;
std::string MyLog::_logName log;log4cpp::Category root log4cpp::Category::getRoot();
log4cpp::Category MyLog::logCat root.getInstance(MyLog::_logName);
log4cpp::Category MyLog::coutCat root.getInstance(MyLog::_screenInfo);log4cpp::Priority::PriorityLevel MyLog::coutPri log4cpp::Priority::INFO;
log4cpp::Priority::PriorityLevel MyLog::logPri log4cpp::Priority::NOTSET;log4cpp::PatternLayout* MyLog::logLayout NULL;
log4cpp::PatternLayout* MyLog::screenLayout NULL;log4cpp::FileAppender* MyLog::logFile NULL;//文件日志输入
log4cpp::OstreamAppender* MyLog::logScreen NULL;//屏幕日志输入//为避免每次调用都要填写参数__FILE__,__LINE__和__FUNCTION__,可以使用带参数的宏定义
#define MyLogWARN(msg) MyLog::getLog()-warn(msg,__FILE__,__LINE__,__FUNCTION__);
#define MyLogINFO(msg) MyLog::getLog()-info(msg,__FILE__,__LINE__,__FUNCTION__);
#define MyLogERROR(msg) MyLog::getLog()-error(msg,__FILE__,__LINE__,__FUNCTION__);
#define MyLogDEBUG(msg) MyLog::getLog()-debug(msg,__FILE__,__LINE__,__FUNCTION__);
发送到远程服务器
应用程序中SocketAppender配置
前面启动了LoggingServer下面说一下需要收集其日志的各个应用程序中配置。
说白了就是在原来的基础上加一个SocketAppenderSocketAppender会自动将日志发送给loggingserver。这样直接在loggingserver上就可以查看所有服务器上的日志信息啦。哥终于不用再担心你们的运行状态啦
配置文件
log4cplus.rootLoggerTRACE,STDOUT, ALL_MSGS,RemoteServer
log4cplus.logger.rollfileTRACE,R2log4cplus.appender.STDOUTlog4cplus::ConsoleAppender
log4cplus.appender.STDOUT.layoutlog4cplus::PatternLayout
log4cplus.appender.STDOUT.layout.ConversionPattern[%d %d{%Z %Q}][pthread_id:%t][%l][%-5p][%c{2}] - %m%nlog4cplus.appender.R2log4cplus::RollingFileAppender
log4cplus.appender.R2.File./mytest.log
log4cplus.appender.R2.MaxFileSize4MB
log4cplus.appender.R2.MaxBackupIndex5
log4cplus.appender.R2.layoutlog4cplus::PatternLayout
log4cplus.appender.R2.layout.ConversionPattern[%d %d{%Z %Q}][pthread_id:%t][%l][%-5p][%c{2}] - %m%n log4cplus.appender.RemoteServerlog4cplus::SocketAppender
log4cplus.appender.RemoteServer.host192.168.2.130
log4cplus.appender.RemoteServer.port9000
还可以输出到多个server配置如下
log4cplus.rootLoggerTRACE, STDOUT, ALL_MSGS,RemoteServer,RemoteServer2
log4cplus.logger.rollfileTRACE,R2log4cplus.appender.STDOUTlog4cplus::ConsoleAppender
log4cplus.appender.STDOUT.layoutlog4cplus::PatternLayout
log4cplus.appender.STDOUT.layout.ConversionPattern[%d %d{%Z %Q}][pthread_id:%t][%l][%-5p][%c{2}] - %m%n
#log4cplus.appender.STDOUT.layout.ConversionPattern[%l][%-5p] - %m%nlog4cplus.appender.R2log4cplus::RollingFileAppender
log4cplus.appender.R2.File/opt/apps/3k/i1client/i1client.log
log4cplus.appender.R2.MaxFileSize10000KB
log4cplus.appender.R2.MaxBackupIndex100
log4cplus.appender.R2.layoutlog4cplus::PatternLayout
log4cplus.appender.R2.layout.ConversionPattern[%d %d{%Z %Q}][pthread_id:%t][%l][%-5p][%c{2}] - %m%n
#log4cplus.appender.R2.layout.ConversionPattern[%l][%-5p] - %m%nlog4cplus.appender.RemoteServerlog4cplus::SocketAppender
log4cplus.appender.RemoteServer.host192.168.2.130
log4cplus.appender.RemoteServer.port9000log4cplus.appender.RemoteServer2log4cplus::SocketAppender
log4cplus.appender.RemoteServer2.host192.168.2.131
log4cplus.appender.RemoteServer2.port9001
测试
在Log4cplus的源码包中有一个loggingServer目录该目录中实现了一个LoggingServer。
在编译Log4cplus时会自动编译该目录在目录中生成loggingServer可执行文件当然可以自己make需要依赖log4cplus库。
loggingServer使用方式如下
./loggingserver 9000 log4cplus.properties
9000表示监听的端口号不需要地址默认监听本机地址
log4cplus.properties是一个log4cplus的配置文件和普通的log4cplus配置文件相同loggingserver收到各个socket发来的日志后根据配置文件信息将其写入文件。
服务端配置文件如下
log4cplus.rootLoggerTRACE, STDOUT, ALL_MSGS#Appender输出位置类型控制台输出
log4cplus.appender.STDOUTlog4cplus::ConsoleAppender
#日志输出格式 有词法分析功能的模式布局器
log4cplus.appender.STDOUT.layoutlog4cplus::PatternLayout
log4cplus.appender.STDOUT.layout.ConversionPattern[%d %d{%Z %Q}][pthread_id:%t][%l][%-5p][%c{2}] - %m%n#Appender输出位置类型有文件输出 设置日志追加到文件尾
log4cplus.appender.ALL_MSGSlog4cplus::RollingFileAppender
#设置输出日志路径
log4cplus.appender.ALL_MSGS.Filelog/i1client.log
#设置日志文件大小
log4cplus.appender.ALL_MSGS.MaxFileSize1024KB
#设置生成日志最大个数
log4cplus.appender.ALL_MSGS.MaxBackupIndex20
#日志输出格式 有词法分析功能的模式布局器
log4cplus.appender.ALL_MSGS.layoutlog4cplus::PatternLayout
log4cplus.appender.ALL_MSGS.layout.ConversionPattern[%d %d{%Z %Q}][pthread_id:%t][%l][%-5p][%c{2}] - %m%n