使用异步模式的log4cplus

最近因为项目的原因,开始研究log4cplus这个日志库。主要是把新版中增加的异步模式log用起来。异步log目前很少有人用,网上说明的资料比较少。看了很多源码,做了很多测试,走了些许弯路。因此打算把一点心得记录下来,为后面要用此功能的人增加一点参考资料。借此机会,正式开启我的技术博客之旅:)。

 

log4cplus通常有三种使用形式:stdout(打印到屏幕),文件日志和网络日志。最常用的是文件日志。本文主要介绍本地文件日志的用法。

1. 一个简单的例子

首先来看一个简单的例子:

int main(int argc, char* argv[])
{
    log4cplus::initialize();
    log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("log4cplus.properties"));

    log4cplus::Logger logger = log4cplus::Logger::getInstance("global");
    LOG4CPLUS_DEBUG(logger, LOG4CPLUS_TEXT("DEBUG LOG TEST"));
    LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("INFO LOG TEST"));
    LOG4CPLUS_WARN(logger, LOG4CPLUS_TEXT("WARN LOG TEST"));
    LOG4CPLUS_ERROR(logger, LOG4CPLUS_TEXT("ERROR LOG TEST"));

    log4cplus::Logger::shutdown();
    return 0;
}

这个程序启动以后,首先执行initialize函数,做一些初始化工作:初始化线程本地变量及其清理函数,注册各种类型的Appender(最终打日志的类)。然后通过 doConfigure 去读取该程序所在目录下的日志的配置文件log4cplus.properties。

getInstance函数会通过global这个名字,从log4cplus.properties读取起对应的log选项中,返回一个log4cplus::Logger实例。该实例底层是一个共享指针,指向一个真正的log实例。此时,所有的log相关的初始化工作完成了,可以开始打log了。

程序使用了log4cplus提供的宏来打log。打完log,需要调用shutdown函数关闭log实例,以确保log被flush到磁盘上。

 

2. log的不同方式及其特点

log4cplus是通过不同的Appender来决定怎样打log的:

ConsoleAppender:stdout日志

FileAppender:普通文件日志

RollingFileAppender:滚动的文件日志

DailyRollingFileAppender:按天滚动的文件日志

AsyncAppender:异步日志

Log4jUdpAppender:网络日志

除了ConsoleAppender、AsyncAppender和Log4jUdpAppender,剩下的都是文件日志。这些Appender打的日志都是同步的,即打log的语句会等到log打完(log被发送到文件系统的缓冲区)才返回。如果某个时刻,系统突然打了非常大量的log,以至于

超过了系统磁盘的最大读写速度,这个时刻以后的打log的线程都会被阻塞。这会极大地减缓系统响应速度。

 

为了缓解这样的问题,通常有三种做法:减少线上系统的log量(甚至线上系统关闭log),打网络日志,使用log4cplus提供的异步日志。但是,对与有些比较重要的需要对账的线上系统,通常需要打很详细的log。为了不让log影响系统的响应速度,通常会打

网络log。而网络log需要额外的服务器来接收log,同时会占用一定的带宽。因此如果log不是特别重要的系统,通常可以使用异步log来缓解这个问题。

 

log4cplus的AsyncAppender是log4cplus-1.2.0版本库开始支持的一个新功能。AsyncAppender可以让你的系统以异步的方式来打log,从而提高系统的响应速度。在系统启动后,所有的系统log首先会发送到AsyncAppender的一个队列中去,

AsyncAppender会在系统启动时专门开一个线程来写程序发过来的log。通过这种方式将log的生产和落地放到不同的线程来完成。

 

但是,AsyncAppender并不是万灵药。如果系统生产日志的速度超过了写日志线程的消费日志的速度,AsyncApender的队列会被填满。如果队列满了,生产日志的线程的打log时候会被阻塞住,直到队列有空间放新的日志。因此,要想万无一失,最后还是打

网络log。

 

2.1 log4cplus的同步日志的配置

## synchronous log properties.
log4cplus.logger.global = INFO, SA
log4cplus.appender.SA=log4cplus::DailyRollingFileAppender
log4cplus.appender.SA.Schedule=HOURLY
log4cplus.appender.SA.DatePattern=%Y-%m-%d:%H
log4cplus.appender.SA.File=/home/work/log/imserv/imserv.log
log4cplus.appender.SA.MaxBackupIndex=100
log4cplus.appender.SA.BufferSize=131072
log4cplus.appender.SA.Append=true
log4cplus.appender.SA.layout=log4cplus::PatternLayout
log4cplus.appender.SA.layout.ConversionPattern=%D{%Y-%m-%d %H:%M:%S,%Q} [%t] %-5p %m%n

 

2.2 log4cplus的异步log的配置

## asynchronous log properties.
log4cplus.logger.global = INFO, AA
log4cplus.appender.AA=log4cplus::AsyncAppender
log4cplus.appender.AA.QueueLimit=10000
log4cplus.appender.AA.Appender=log4cplus::DailyRollingFileAppender
log4cplus.appender.AA.Appender.Schedule=HOURLY
log4cplus.appender.AA.Appender.Threshold = INFO
log4cplus.appender.AA.Appender.DatePattern=%Y-%m-%d-%H
log4cplus.appender.AA.Appender.File=./logger_test.log
log4cplus.appender.AA.Appender.ImmediateFlush=false
log4cplus.appender.AA.Appender.MaxFileSize=1000MB  
log4cplus.appender.AA.Appender.MaxBackupIndex=100
log4cplus.appender.AA.Appender.Append=true
log4cplus.appender.AA.Appender.layout=log4cplus::PatternLayout  
log4cplus.appender.AA.Appender.layout.ConversionPattern=%D{%Y-%m-%d %H:%M:%S,%Q} [%t] %-5p %m%n

 

2.3 log4cplus异步日志使用过程中需要注意的地方

程序退出前记得调用shutdown函数将所有的log flush到磁盘上。

1.2.0版本的log4cplus异步日志有BUG,会导致丢日志,下一个版本会修复。解决办法见:https://sourceforge.net/p/log4cplus/bugs/333/

 

转载于:https://www.cnblogs.com/justinezhang/p/5793532.html

你可能感兴趣的:(使用异步模式的log4cplus)