最近由于项目开始接触这个类,用起来很方便,看了很多帖子,将针对自己比较常用的配置文件部分归纳出来。
主要参考帖子:Log4cplus使用指南
测试版本 1.2.2
测试软件 VS2010
配置文件中总共包含4部分内容:Logger、Appender、layout、filter,逻辑关系如下。
举个例子
#声明一个Logger
#SetverLog = Logger名称
#ALL = 日志输出的级别
#ALL_MSGS = Appender对象,可以有多个对象
log4cplus.logger.SetverLog = ALL, ALL_MSGS, ALL_MSGS_1
#实例化Appender对象,即输出方式:输出到控制台还是文件
log4cplus.appender.ALL_MSGS=log4cplus::RollingFileAppender
log4cplus.appender.ALL_MSGS.MaxFileSize=100MB
log4cplus.appender.ALL_MSGS.MaxBackupIndex=10
log4cplus.appender.ALL_MSGS.CreateDirs = true
log4cplus.appender.ALL_MSGS.ImmediateFlush = true
log4cplus.appender.ALL_MSGS.File=ServerLog/test.log
#日志文件的打印格式
log4cplus.appender.ALL_MSGS.layout=log4cplus::PatternLayout
log4cplus.appender.ALL_MSGS.layout.ConversionPattern=[%-5p %d{%y-%m-%d %H:%M:%S}] [%l]
#日志输出的过滤器
log4cplus.appender.ALL_MSGS.filters.1=log4cplus::spi::LogLevelMatchFilter
log4cplus.appender.DEBUG_MSGS.filters.1.LogLevelToMatch=DEBUG
log4cplus.appender.DEBUG_MSGS.filters.1.AcceptOnMatch=true
log4cplus.appender.DEBUG_MSGS.filters.2=log4cplus::spi::DenyAllFilter
配置
log4cplus.rootLogger=ALL, RemoteServer, STDOUT, ALL_MSGS
调用
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("配置文件名称"));
log4cplus::Logger logger = log4cplus::Logger::getRoot();
配置
log4cplus.logger.ClientLog = ALL, RemoteServer, STDOUT, ALL_MSGS
调用
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("配置文件名称"));
log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("ClientLog"));
级别 | 合法字符 | 说明 |
NOT_SET_LOG_LEVEL ( -1) | 接受缺省的LogLevel,如果有父logger则继承它的LogLevel | |
ALL_LOG_LEVEL (0) | ALL | 开放所有log信息输出 |
TRACE_LOG_LEVEL (0) | TRACE | 开放trace信息输出(即ALL_LOG_LEVEL) |
DEBUG_LOG_LEVEL(10000) | DEBUG | 开放debug信息输出 |
INFO_LOG_LEVEL (20000) | INFO | 开放info信息输出 |
WARN_LOG_LEVEL (30000) | WARN | 开放warning信息输出 |
ERROR_LOG_LEVEL(40000) | ERROR | 开放error信息输出 |
FATAL_LOG_LEVEL (50000) | FATAL | 开放fatal信息输出 |
OFF_LOG_LEVEL (60000) | OFF | 关闭所有log信息输出 |
级别 | 函数 | 说明 |
TRACE | LOG4CPLUS_TRACE | 1. 直接输出。将日志转导 ostringstream 流,再转字符串输出。 2. *_STR。直接字符串输出。 3. *_FMT。先格式化字符串,再转字符串输出。 4. *_METHOD。会在函数的入口和出口处输出 ENTER 和 EXIT。 |
LOG4CPLUS_TRACE_STR | ||
LOG4CPLUS_TRACE_FMT | ||
LOG4CPLUS_TRACE_METHOD | ||
DEBUG | LOG4CPLUS_DEBUG | |
LOG4CPLUS_DEBUG_STR | ||
LOG4CPLUS_DEBUG_FMT | ||
INFO | LOG4CPLUS_INFO | |
LOG4CPLUS_INFO_STR | ||
LOG4CPLUS_INFO_FMT | ||
WARN | LOG4CPLUS_WARN | |
LOG4CPLUS_WARN_STR | ||
LOG4CPLUS_WARN_FMT | ||
ERROR | LOG4CPLUS_ERROR | |
LOG4CPLUS_ERROR_STR | ||
LOG4CPLUS_ERROR_FMT | ||
FATAL | LOG4CPLUS_FATAL | |
LOG4CPLUS_FATAL_STR | ||
LOG4CPLUS_FATAL_FMT | ||
ASSERT | LOG4CPLUS_ASSERT |
代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
using namespace log4cplus::thread;
int
main()
{
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("config.txt"));
Logger logger = Logger::getInstance(LOG4CPLUS_TEXT("TestOutputMethod"));
LOG4CPLUS_TRACE(logger, LOG4CPLUS_TEXT("111"));
LOG4CPLUS_TRACE_STR(logger, LOG4CPLUS_TEXT("222"));
LOG4CPLUS_TRACE_FMT(logger, LOG4CPLUS_TEXT("%d%d%d"), 3, 3, 3);
{
LOG4CPLUS_TRACE_METHOD(logger, LOG4CPLUS_TEXT("TestFunc"));
LOG4CPLUS_TRACE(logger, LOG4CPLUS_TEXT("444"));
LOG4CPLUS_TRACE(logger, LOG4CPLUS_TEXT("555"));
LOG4CPLUS_TRACE(logger, LOG4CPLUS_TEXT("666"));
}
LOG4CPLUS_TRACE(logger, LOG4CPLUS_TEXT("777"));
log4cplus::Logger::shutdown();
return 0;
}
配置文件
log4cplus.logger.TestOutputMethod = ALL, Test
# 创建Appender对象
log4cplus.appender.Test = log4cplus::FileAppender
# FileAppender 类属性
log4cplus.appender.Test.Threshold = ALL
log4cplus.appender.Test.File = Test/FileAppenderLog.txt
log4cplus.appender.Test.ImmediateFlush = false
log4cplus.appender.Test.BufferSize = 1024
log4cplus.appender.Test.CreateDirs = true
log4cplus.appender.Test.Append = false
结果
TRACE - 111
TRACE - 222
TRACE - 333
TRACE - ENTER: TestFunc
TRACE - 444
TRACE - 555
TRACE - 666
TRACE - EXIT: TestFunc
TRACE - 777
Appender | 基础Appender类 |
ConsoleAppender | 输出到控制台 |
FileAppenderBase | 输出到文件的基础类,不可以被实例化 |
FileAppender | 输出到文件 |
RollingFileAppender | 输出到文件-可以按照文件大小或者数量滚动 |
DailyRollingFileAppender | 输出到文件-可以按照日期时间滚动 |
TimeBasedRollingFileAppender | 可以按照用户定义的时间滚动日志 |
AsyncAppender | 一个异步写入的Appender |
SocketAppender | 网络日志 |
它们的继承关系:
属性标签 | 描述 |
layout | 说明:日志打印格式 类型:Layout 默认值:SimpleLayout 可选值:SimpleLayout TTCCLayout PatternLayout |
filters | 说明:日志过滤器 类型:Filter 默认值:默认接收所有输出 可选值:DenyAllFilter LogLevelMatchFilter LogLevelRangeFilter StringMatchFilter |
Threshold | 说明:日志打印的最低级别 类型:LogLevel 默认值:NOT_SET_LOG_LEVEL 可选值:ALL TRACE DEBUG INFO WARN ERROR FATAL OFF |
属性标签 | 描述 |
logToStdErr | 说明:输出方式 类型:bool 默认值:false 可选值:true=std::cerr false=std::cout |
ImmediateFlush | 说明:立即输出 类型:bool 默认值:false 可选值:true=std::cerr false=std::cout |
代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
int main()
{
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("config.txt"));
log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TestConsoleAppender"));
LOG4CPLUS_TRACE(logger, LOG4CPLUS_TEXT("TRACE-LOG-TEST"));
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_FATAL(logger, LOG4CPLUS_TEXT("FATAL-LOG-TEST"));
log4cplus::Logger::shutdown();
return 0;
}
配置文件
log4cplus.logger.TestConsoleAppender = ALL, Test
# 创建Appender对象
log4cplus.appender.Test = log4cplus::ConsoleAppender
# Appender类属性
log4cplus.appender.Test.Threshold = INFO
输出结果
INFO - INFO-LOG-TEST
WARN - WARN-LOG-TEST
ERROR - ERROR-LOG-TEST
FATAL - FATAL-LOG-TEST
属性标签 | 描述 |
File | 说明:文件路径\文件名 类型:String 默认值:无 可选值:文件路径\文件名 |
ImmediateFlush | 说明:立即刷新 类型:bool 默认值:true 可选值:true false |
Append | 说明:追加到文件末尾继续写入 类型:bool 默认值:false 可选值:true false |
ReopenDelay | 说明:当上一次日志写入失败后延长多久后再次打开日志文件继续写入 类型:int 默认值:1(秒) 可选值:int 有效值 |
BufferSize | 说明:缓存大小 类型:unsigned long 默认值:0 可选值:unsigned long 有效值 |
UseLockFile | 说明:使用锁文件,多进程对同一文件同时写入的优化机制 类型:bool 默认值:false 可选值:true false |
LockFile | 说明:锁文件的文件名尾缀,只有在 UseLockFile 为 true 时有效 类型:String 默认值:.lock 可选值:非空即可 |
Locale | 说明:字符集 类型:String 默认值:DEFAULT 可选值:en_US.UTF-8 GLOBAL DEFAULT USER Chinese_China.936 Chinese_China.65001 chs |
CreateDirs | 说明:如果目录及文件不存在就创建 类型:bool 默认值:false 可选值:true false |
没有额外的附加属性。
代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
int main()
{
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("config.txt"));
log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TestFileAppender"));
LOG4CPLUS_TRACE(logger, LOG4CPLUS_TEXT("TRACE-LOG-TEST"));
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_FATAL(logger, LOG4CPLUS_TEXT("FATAL-LOG-TEST"));
log4cplus::Logger::shutdown();
return 0;
}
配置文件
log4cplus.logger.TestFileAppender = ALL, Test
# 创建Appender对象
log4cplus.appender.Test = log4cplus::FileAppender
# Appender 类属性
log4cplus.appender.Test.Threshold = ALL
# FileAppenderBase 类属性
log4cplus.appender.Test.File = Test/FileAppenderLog.txt
log4cplus.appender.Test.ImmediateFlush = true
log4cplus.appender.Test.Append = true
log4cplus.appender.Test.ImmediateFlush = false
log4cplus.appender.Test.CreateDirs = true
# FileAppender 类属性
# 空
结果
TRACE - TRACE-LOG-TEST
DEBUG - DEBUG-LOG-TEST
INFO - INFO-LOG-TEST
WARN - WARN-LOG-TEST
ERROR - ERROR-LOG-TEST
FATAL - FATAL-LOG-TEST
通过控制每个文件大小以及总文件数量控制日志的量
属性标签 | 描述 |
MaxFileSize | 说明:最大文件大小 类型:long 默认值:10 MB 可选值:不能小于200kb,如果小于200kb会自动调整为200kb。在配置文件中可以带上单位 10KB 10MB,代码中 10*1024 10*1024*1024 。 |
MaxBackupIndex |
说明:最大文件数量 类型:int 默认值:1 可选值:大于零即可 |
代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
int main()
{
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("config.txt"));
log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TestRollingFileAppender"));
for (int i = 0; i < 5000; i++)
{
LOG4CPLUS_TRACE(logger, LOG4CPLUS_TEXT("TRACE-LOG-TEST"));
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_FATAL(logger, LOG4CPLUS_TEXT("FATAL-LOG-TEST"));
}
log4cplus::Logger::shutdown();
return 0;
}
配置文件
log4cplus.logger.TestRollingFileAppender = ALL, Test
# 创建Appender对象
log4cplus.appender.Test = log4cplus::RollingFileAppender
# Appender 类属性
log4cplus.appender.Test.Threshold = ALL
# FileAppenderBase 类属性
log4cplus.appender.Test.File = Test/RollingFileAppenderLog.txt
log4cplus.appender.Test.ImmediateFlush = true
log4cplus.appender.Test.Append = true
log4cplus.appender.Test.ImmediateFlush = false
log4cplus.appender.Test.CreateDirs = true
# RollingFileAppender 类属性
log4cplus.appender.Test.MaxFileSize = 1kb
log4cplus.appender.Test.MaxBackupIndex = 3
结果
结果说明
MaxBackupIndex 是指最大的滚动备份数量,备份文件会以“文件名.n”的格式存在。举例MaxBackupIndex=3,则有三个备份文件。注意此处 RollingFileAppenderLog.txt 大小不为0, 备份文件大小最小是200kb。
属性标签 | 描述 |
Schedule | 说明:滚动的时间计划以及滚动的日期格式(当DatePattern为空时日期格式有效) 类型:DailyRollingFileSchedule 默认值:DAILY 可选值:MONTHLY WEEKLY DAILY TWICE_DAILY HOURLY MINUTELY |
MaxBackupIndex | 说明:最大文件数量 类型:int 默认值:10 可选值:大于零即可 |
RollOnClose | 说明:在关闭时是否滚动日志文件 类型:bool 默认值:true 可选值:true false |
DatePattern | 说明:滚动的日期格式,如果该属性不为空,则 Schedule 的日期格式无效,但滚动计划有效。 类型:String 默认值:无 可选值:参考下表“日期时间输出格式转换符”中的内容。例如:%Y-%m-%d |
代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
int main()
{
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("config.txt"));
log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TestDailyRollingFileAppender"));
//for (int i = 0; i < 5000; i++)
{
LOG4CPLUS_TRACE(logger, LOG4CPLUS_TEXT("TRACE-LOG-TEST"));
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_FATAL(logger, LOG4CPLUS_TEXT("FATAL-LOG-TEST"));
}
log4cplus::Logger::shutdown();
return 0;
}
配置文件
log4cplus.logger.TestDailyRollingFileAppender = ALL, Test
# 创建Appender对象
log4cplus.appender.Test = log4cplus::DailyRollingFileAppender
# Appender 类属性
log4cplus.appender.Test.Threshold = ALL
# FileAppenderBase 类属性
log4cplus.appender.Test.File = Test/DailyRollingFileAppenderLog.txt
log4cplus.appender.Test.ImmediateFlush = true
log4cplus.appender.Test.Append = true
log4cplus.appender.Test.ImmediateFlush = false
log4cplus.appender.Test.CreateDirs = true
# DailyRollingFileAppender 类属性
log4cplus.appender.Test.Schedule = DAILY
log4cplus.appender.Test.MaxBackupIndex = 3
log4cplus.appender.Test.RollOnClose = true
#log4cplus.appender.Test.DatePattern = 3
结果
结果说明
Schedule 是说明按天生成文件,新文件会以文件名.Schedule 的形式存在。
MaxBackupIndex 同 RollingFileAppender 的 MaxBackupIndex,只不过是按天刷新统计数量。
RollOnClose = true 则在每次关闭程序时 DailyRollingFileAppenderLog.txt 大小为0,区别于 RollingFileAppender 的滚动文件。
DatePattern 自定义滚动文件的日期格式,如果在上面配置文件最后增加 DatePattern 属性,输出文件名会改变。
log4cplus.logger.TestDailyRollingFileAppender = ALL, Test
# 创建Appender对象
log4cplus.appender.Test = log4cplus::DailyRollingFileAppender
# Appender 类属性
log4cplus.appender.Test.Threshold = ALL
# FileAppenderBase 类属性
log4cplus.appender.Test.File = Test/DailyRollingFileAppenderLog.txt
log4cplus.appender.Test.ImmediateFlush = true
log4cplus.appender.Test.Append = true
log4cplus.appender.Test.ImmediateFlush = false
log4cplus.appender.Test.CreateDirs = true
# DailyRollingFileAppender 类属性
log4cplus.appender.Test.Schedule = DAILY
log4cplus.appender.Test.MaxBackupIndex = 3
log4cplus.appender.Test.RollOnClose = true
log4cplus.appender.Test.DatePattern = %Y k %m kk %d.TestDatePattern
注意:需要改变系统时间做测试~
属性标签 | 描述 |
FilenamePattern | 说明:自定义文件名 类型:String 默认值:无 可选值:适用格式 %d{...},例如Test/%d{yyyy-MM}/%d{yyyy-MM-dd.log} |
MaxHistory | 说明:最大历史文件数量 类型:int 默认值:10 可选值:大于零即可 |
CleanHistoryOnStart | 说明:每次运行清空历史文件 类型:bool 默认值:false 可选值:true false |
RollOnClose | 说明:每次停止程序滚动日志 类型:bool 默认值:true 可选值:true false |
源代码调用方式,例如输入MMM,则调用时会识别 char=M,len=3,,然后将MM转换成%b继续格式输出。
...
case LOG4CPLUS_TEXT('M'): // Month in year
if (len == 2)
result << LOG4CPLUS_TEXT("%m");
else if (len == 3)
result << LOG4CPLUS_TEXT("%b");
else if (len > 3)
result << LOG4CPLUS_TEXT("%B");
break;
...
转换标识符整理,测试时间 2020-04-22 23:40:14。
输出含义 | 格式字符 | 输出结果 |
年 | yy | 20 |
yyyy | 2020 | |
Week year | YY | 报错,无此格式 |
YYYY | 报错,无此格式 | |
月 | MM | 04 |
MMM | Apr | |
MMMM | April | |
今年的第几周 | ww | 16 |
今年的第几天 | DDD | 113 |
这个月的第几天 | dd | 22 |
今天周几 | EEE | Wed |
EEEE | Wednesday | |
Day number of week | u | 报错,无此格式 |
AM/PM | aa | PM |
小时(24小时制) | HH | 23 |
小时(12小时制) | hh | 11 |
分钟 | mm | 40 |
秒 | ss | 14 |
Time zone name | z | 报错,无此格式 |
Time zone offset | Z | 报错,无此格式 |
代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
int main()
{
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("config.txt"));
log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TestTimeBasedRollingFileAppender"));
//for (int i = 0; i < 5000; i++)
{
LOG4CPLUS_TRACE(logger, LOG4CPLUS_TEXT("TRACE-LOG-TEST"));
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_FATAL(logger, LOG4CPLUS_TEXT("FATAL-LOG-TEST"));
}
log4cplus::Logger::shutdown();
return 0;
}
配置文件
log4cplus.logger.TestTimeBasedRollingFileAppender = ALL, Test
# 创建Appender对象
log4cplus.appender.Test = log4cplus::TimeBasedRollingFileAppender
# Appender 类属性
log4cplus.appender.Test.Threshold = ALL
# FileAppenderBase 类属性
log4cplus.appender.Test.File = Test/TimeBasedRollingFileAppenderLog.txt
log4cplus.appender.Test.ImmediateFlush = true
log4cplus.appender.Test.Append = true
log4cplus.appender.Test.ImmediateFlush = false
log4cplus.appender.Test.CreateDirs = true
# TimeBasedRollingFileAppender 类属性
log4cplus.appender.Test.FilenamePattern = Test/%d{yyyy-MM-dd-ss.log}
log4cplus.appender.Test.MaxHistory = 3
log4cplus.appender.Test.CleanHistoryOnStart = false
log4cplus.appender.Test.RollOnClose = true
结果
说明
1. FilenamePattern 这里的格式是套用 %d{yyyy-MM-dd} 的形式,和其他的地方不一样。
2. MaxHistory 配置文件最大的历史数量。需要注意这里的操作逻辑
1)历史文件的检查是在每次程序退出时 void TimeBasedRollingFileAppender::clean(Time time) 函数里进行的
2)历史文件的检查有个时间跨度,默认是天,时间跨度是根据设定的 FilenamePattern 来统计的
3)计算时间跨度的起止时间是程序刚开始运行的时间和退出的时间。也就是说,如果每天将程序运行一次(一次10秒钟),则生成一个年-月-日.log的日志文件,连续运行一个月,也不会清理历史文件,即使文件数量超过了设定值3个。因为每次程序运行的时间跨度是10秒钟,小于一天,程序认为没到清理的时候是不会清理历史文件的,只有在程序连续运行超过一天推出时才会清理历史文件。
4)RollOnClose 默认为true。程序运行时会将所有的日志文件写到 File 属性定义的文件里,在程序关闭时再将所有文件复制到 FilenamePattern 属性定义的文件里。注意,如果此时已经有个同名的 FilenamePattern 文件,会覆盖旧文件,并不是像通常理解的 追加写入,也就是说 Append 追加写入属性是在 File 属性定义的文件中完成的,在 FilenamePattern 文件的处理上是单纯的覆盖,而不是追加写入。这里可以可以将 FilenamePattern 属性定义到秒,规避同名文件来实现不覆盖历史日志。
属性标签 | 描述 |
host | 说明:主机IP 类型:String 默认值:无 可选值:localhost IP地址 |
port | 说明:端口号 类型:unsigned int 默认值:9998 可选值:端口号合法值即可 |
ServerName | 说明:服务端名称 类型:String 默认值:无 可选值:字符串即可 |
客户端
代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
int main()
{
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("client_config"));
log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("ClientLog"));
for (int i = 0; i < 10; i++)
{
LOG4CPLUS_TRACE(logger, LOG4CPLUS_TEXT("TRACE-LOG-TEST ") << i);
}
log4cplus::Logger::shutdown();
return 0;
}
配置文件
log4cplus.logger.ClientLog = ALL, RemoteServer
log4cplus.appender.RemoteServer=log4cplus::SocketAppender
log4cplus.appender.RemoteServer.host=localhost
log4cplus.appender.RemoteServer.port=9000
log4cplus.appender.RemoteServer.ServerName=ThisIsServerName
服务端
代码
#include
#include
#include
#include
#include
#include
#include
#include
namespace loggingserver
{
class ClientThread : public log4cplus::thread::AbstractThread
{
public:
ClientThread(log4cplus::helpers::Socket clientsock)
: clientsock(clientsock)
{
std::cout << "Received a client connection!!!!" << std::endl;
}
~ClientThread()
{
std::cout << "Client connection closed." << std::endl;
}
virtual void run();
private:
log4cplus::helpers::Socket clientsock;
};
void
ClientThread::run()
{
while (1) {
if (!clientsock.isOpen()) {
return;
}
log4cplus::helpers::SocketBuffer msgSizeBuffer(sizeof(unsigned int));
if (!clientsock.read(msgSizeBuffer)) {
return;
}
unsigned int msgSize = msgSizeBuffer.readInt();
log4cplus::helpers::SocketBuffer buffer(msgSize);
if (!clientsock.read(buffer)) {
return;
}
log4cplus::spi::InternalLoggingEvent event
= log4cplus::helpers::readFromBuffer(buffer);
log4cplus::tstring strLoggerName = event.getLoggerName();// strLoggerName = ClientLog
log4cplus::tstring strLoggerNDC = event.getNDC();// strLoggerNDC = ThisIsServerName
log4cplus::Logger logger
= log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("SetverLog"));
logger.callAppenders(event);
}
}
}
int
main(int argc, char** argv)
{
int port = 9000;
log4cplus::PropertyConfigurator config(LOG4CPLUS_C_STR_TO_TSTRING("server_config"));
config.configure();
log4cplus::helpers::ServerSocket serverSocket(port);
if (!serverSocket.isOpen()) {
std::cout << "Could not open server socket, maybe port "
<< port << " is already in use." << std::endl;
return 2;
}
while (1) {
loggingserver::ClientThread *thr =
new loggingserver::ClientThread(serverSocket.accept());
thr->start();
}
return 0;
}
配置文件
log4cplus.logger.SetverLog = ALL, FileOut
log4cplus.appender.FileOut = log4cplus::FileAppender
log4cplus.appender.FileOut.File = D:\\FileAppenderLog.txt
log4cplus.appender.FileOut.ImmediateFlush = true
log4cplus.appender.FileOut.Append = true
log4cplus.appender.FileOut.ImmediateFlush = true
log4cplus.appender.FileOut.CreateDirs = true
输出
TRACE - TRACE-LOG-TEST 0
TRACE - TRACE-LOG-TEST 1
TRACE - TRACE-LOG-TEST 2
TRACE - TRACE-LOG-TEST 3
TRACE - TRACE-LOG-TEST 4
TRACE - TRACE-LOG-TEST 5
TRACE - TRACE-LOG-TEST 6
TRACE - TRACE-LOG-TEST 7
TRACE - TRACE-LOG-TEST 8
TRACE - TRACE-LOG-TEST 9
官方介绍它不是一个可以作为流输出的具体类,而是一个用于多线程时控制日志有序输出的一个类。
属性标签 | 描述 |
Appender | 说明:输出对象 类型:Appender 默认值:无 可选值:ConsoleAppender FileAppender RollingFileAppender DailyRollingFileAppender TimeBasedRollingFileAppender SocketAppender |
QueueLimit | 说明:队列大小 类型:unsigned int 默认值:100 可选值:0 ~ Max Unsign Int |
代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
using namespace log4cplus::thread;
#define MILLIS_TO_NANOS 1000
#define NUM_THREADS 4
#define NUM_LOOPS 10
class SlowObject {
public:
SlowObject()
: logger(Logger::getInstance(LOG4CPLUS_TEXT("TestAsyncAppender")))
{
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Init SlowObject"));
}
void doSomething()
{
LOG4CPLUS_TRACE_METHOD(logger, LOG4CPLUS_TEXT("In SlowObject::doSomething()"));
{
// 并没有测试出这个互斥有什么作用
log4cplus::thread::MutexGuard guard(mutex);
sleep(0, 75 * MILLIS_TO_NANOS);
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Actually doing 111111111..."));
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Actually doing 222222222..."));
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Actually doing 333333333..."));
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Actually doing 444444444..."));
}
log4cplus::thread::yield();
}
~SlowObject()
{
LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Out SlowObject"));
}
private:
log4cplus::thread::Mutex mutex;
Logger logger;
};
class TestThread : public AbstractThread {
public:
TestThread(tstring const & n, SlowObject * so)
: name(n)
, slow(so)
, logger(Logger::getInstance(LOG4CPLUS_TEXT("TestAsyncAppender")))
{ }
virtual void run();
private:
tstring name;
SlowObject * slow;
Logger logger;
};
int
main()
{
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("config.txt"));
try
{
auto_ptr slowObject(new SlowObject());
Logger logger = Logger::getInstance(LOG4CPLUS_TEXT("TestAsyncAppender"));
log4cplus::helpers::SharedObjectPtr threads[NUM_THREADS];
int i = 0;
for (i = 0; istart();
}
LOG4CPLUS_DEBUG(logger, "All Threads started...");
for (i = 0; iisRunning()) {
sleep(0, 200 * MILLIS_TO_NANOS);
}
}
LOG4CPLUS_INFO(logger, "Exiting main()...");
}
catch (std::exception &e) {
LOG4CPLUS_FATAL(Logger::getRoot(), "main()- Exception occured: " << e.what());
}
catch (...) {
LOG4CPLUS_FATAL(Logger::getRoot(), "main()- Exception occured");
}
log4cplus::Logger::shutdown();
return 0;
}
void
TestThread::run()
{
try {
LOG4CPLUS_WARN(logger, name + LOG4CPLUS_TEXT(" TestThread.run()- Starting..."));
NDC& ndc = getNDC();
NDCContextCreator _first_ndc(name);
LOG4CPLUS_DEBUG(logger, "Entering Run()...");
for (int i = 0; idoSomething();
}
LOG4CPLUS_DEBUG(logger, "Exiting run()...");
ndc.remove();
}
catch (std::exception const & e) {
LOG4CPLUS_FATAL(logger, "TestThread.run()- Exception occurred: " << e.what());
}
catch (...) {
LOG4CPLUS_FATAL(logger, "TestThread.run()- Exception occurred!!");
}
LOG4CPLUS_WARN(logger, name << " TestThread.run()- Finished");
} // end "run"
配置文件
log4cplus.logger.TestAsyncAppender = ALL, Test
# 创建Appender对象
log4cplus.appender.Test = log4cplus::AsyncAppender
# AsyncAppender 类属性
log4cplus.appender.Test.QueueLimit = 1000
log4cplus.appender.Test.Appender = log4cplus::FileAppender
# FileAppender 类属性
log4cplus.appender.Test.Appender.Threshold = ALL
log4cplus.appender.Test.Appender.File = Test/FileAppenderLog.txt
log4cplus.appender.Test.Appender.ImmediateFlush = false
log4cplus.appender.Test.Appender.BufferSize = 1024
log4cplus.appender.Test.Appender.CreateDirs = true
log4cplus.appender.Test.Appender.Append = false
log4cplus.appender.Test.Appender.layout = log4cplus::TTCCLayout
结果
71 [6608] INFO TestAsyncAppender <> - Init SlowObject
73 [10984] WARN TestAsyncAppender <> - Thread-0 TestThread.run()- Starting...
73 [6608] DEBUG TestAsyncAppender <> - All Threads started...
74 [3936] WARN TestAsyncAppender <> - Thread-1 TestThread.run()- Starting...
75 [10984] DEBUG TestAsyncAppender - Entering Run()...
75 [3928] WARN TestAsyncAppender <> - Thread-3 TestThread.run()- Starting...
74 [4160] WARN TestAsyncAppender <> - Thread-2 TestThread.run()- Starting...
75 [3936] DEBUG TestAsyncAppender - Entering Run()...
75 [10984] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
76 [3928] DEBUG TestAsyncAppender - Entering Run()...
76 [4160] DEBUG TestAsyncAppender - Entering Run()...
76 [3936] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
76 [10984] INFO TestAsyncAppender - Actually doing 111111111...
76 [3928] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
76 [4160] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
76 [10984] INFO TestAsyncAppender - Actually doing 222222222...
77 [10984] INFO TestAsyncAppender - Actually doing 333333333...
77 [10984] INFO TestAsyncAppender - Actually doing 444444444...
77 [10984] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
77 [3936] INFO TestAsyncAppender - Actually doing 111111111...
77 [10984] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
77 [3936] INFO TestAsyncAppender - Actually doing 222222222...
78 [3936] INFO TestAsyncAppender - Actually doing 333333333...
78 [3936] INFO TestAsyncAppender - Actually doing 444444444...
78 [3936] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
78 [3928] INFO TestAsyncAppender - Actually doing 111111111...
78 [3936] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
78 [3928] INFO TestAsyncAppender - Actually doing 222222222...
78 [3928] INFO TestAsyncAppender - Actually doing 333333333...
79 [3928] INFO TestAsyncAppender - Actually doing 444444444...
79 [3928] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
79 [4160] INFO TestAsyncAppender - Actually doing 111111111...
79 [3928] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
79 [4160] INFO TestAsyncAppender - Actually doing 222222222...
79 [4160] INFO TestAsyncAppender - Actually doing 333333333...
79 [4160] INFO TestAsyncAppender - Actually doing 444444444...
80 [4160] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
80 [10984] INFO TestAsyncAppender - Actually doing 111111111...
80 [10984] INFO TestAsyncAppender - Actually doing 222222222...
80 [4160] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
80 [10984] INFO TestAsyncAppender - Actually doing 333333333...
80 [10984] INFO TestAsyncAppender - Actually doing 444444444...
80 [10984] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
80 [3936] INFO TestAsyncAppender - Actually doing 111111111...
81 [10984] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
81 [3936] INFO TestAsyncAppender - Actually doing 222222222...
81 [3936] INFO TestAsyncAppender - Actually doing 333333333...
81 [3936] INFO TestAsyncAppender - Actually doing 444444444...
81 [3936] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
81 [3928] INFO TestAsyncAppender - Actually doing 111111111...
82 [3936] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
82 [3928] INFO TestAsyncAppender - Actually doing 222222222...
82 [3928] INFO TestAsyncAppender - Actually doing 333333333...
82 [3928] INFO TestAsyncAppender - Actually doing 444444444...
82 [4160] INFO TestAsyncAppender - Actually doing 111111111...
82 [3928] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
82 [4160] INFO TestAsyncAppender - Actually doing 222222222...
83 [3928] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
83 [4160] INFO TestAsyncAppender - Actually doing 333333333...
83 [4160] INFO TestAsyncAppender - Actually doing 444444444...
83 [4160] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
83 [10984] INFO TestAsyncAppender - Actually doing 111111111...
83 [4160] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
83 [10984] INFO TestAsyncAppender - Actually doing 222222222...
84 [10984] INFO TestAsyncAppender - Actually doing 333333333...
84 [10984] INFO TestAsyncAppender - Actually doing 444444444...
84 [10984] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
84 [3936] INFO TestAsyncAppender - Actually doing 111111111...
84 [10984] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
84 [3936] INFO TestAsyncAppender - Actually doing 222222222...
85 [3936] INFO TestAsyncAppender - Actually doing 333333333...
85 [3936] INFO TestAsyncAppender - Actually doing 444444444...
85 [3936] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
85 [3928] INFO TestAsyncAppender - Actually doing 111111111...
85 [3936] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
85 [3928] INFO TestAsyncAppender - Actually doing 222222222...
85 [3928] INFO TestAsyncAppender - Actually doing 333333333...
86 [3928] INFO TestAsyncAppender - Actually doing 444444444...
86 [3928] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
86 [4160] INFO TestAsyncAppender - Actually doing 111111111...
86 [3928] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
86 [4160] INFO TestAsyncAppender - Actually doing 222222222...
86 [4160] INFO TestAsyncAppender - Actually doing 333333333...
87 [4160] INFO TestAsyncAppender - Actually doing 444444444...
87 [4160] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
87 [10984] INFO TestAsyncAppender - Actually doing 111111111...
87 [4160] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
87 [10984] INFO TestAsyncAppender - Actually doing 222222222...
87 [10984] INFO TestAsyncAppender - Actually doing 333333333...
87 [10984] INFO TestAsyncAppender - Actually doing 444444444...
88 [10984] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
88 [3936] INFO TestAsyncAppender - Actually doing 111111111...
88 [10984] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
88 [3936] INFO TestAsyncAppender - Actually doing 222222222...
88 [3936] INFO TestAsyncAppender - Actually doing 333333333...
88 [3936] INFO TestAsyncAppender - Actually doing 444444444...
88 [3936] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
88 [3928] INFO TestAsyncAppender - Actually doing 111111111...
89 [3928] INFO TestAsyncAppender - Actually doing 222222222...
89 [3936] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
89 [3928] INFO TestAsyncAppender - Actually doing 333333333...
89 [3928] INFO TestAsyncAppender - Actually doing 444444444...
89 [3928] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
89 [4160] INFO TestAsyncAppender - Actually doing 111111111...
89 [4160] INFO TestAsyncAppender - Actually doing 222222222...
89 [3928] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
90 [4160] INFO TestAsyncAppender - Actually doing 333333333...
90 [4160] INFO TestAsyncAppender - Actually doing 444444444...
90 [4160] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
90 [10984] INFO TestAsyncAppender - Actually doing 111111111...
90 [4160] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
90 [10984] INFO TestAsyncAppender - Actually doing 222222222...
91 [10984] INFO TestAsyncAppender - Actually doing 333333333...
91 [10984] INFO TestAsyncAppender - Actually doing 444444444...
91 [10984] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
91 [3936] INFO TestAsyncAppender - Actually doing 111111111...
91 [10984] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
91 [3936] INFO TestAsyncAppender - Actually doing 222222222...
91 [3936] INFO TestAsyncAppender - Actually doing 333333333...
92 [3936] INFO TestAsyncAppender - Actually doing 444444444...
92 [3936] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
92 [3928] INFO TestAsyncAppender - Actually doing 111111111...
92 [3936] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
92 [3928] INFO TestAsyncAppender - Actually doing 222222222...
92 [3928] INFO TestAsyncAppender - Actually doing 333333333...
92 [3928] INFO TestAsyncAppender - Actually doing 444444444...
93 [3928] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
93 [4160] INFO TestAsyncAppender - Actually doing 111111111...
93 [4160] INFO TestAsyncAppender - Actually doing 222222222...
93 [3928] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
93 [4160] INFO TestAsyncAppender - Actually doing 333333333...
93 [4160] INFO TestAsyncAppender - Actually doing 444444444...
93 [4160] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
93 [10984] INFO TestAsyncAppender - Actually doing 111111111...
94 [4160] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
94 [10984] INFO TestAsyncAppender - Actually doing 222222222...
94 [10984] INFO TestAsyncAppender - Actually doing 333333333...
94 [10984] INFO TestAsyncAppender - Actually doing 444444444...
94 [10984] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
94 [3936] INFO TestAsyncAppender - Actually doing 111111111...
95 [10984] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
95 [3936] INFO TestAsyncAppender - Actually doing 222222222...
95 [3936] INFO TestAsyncAppender - Actually doing 333333333...
95 [3936] INFO TestAsyncAppender - Actually doing 444444444...
95 [3928] INFO TestAsyncAppender - Actually doing 111111111...
95 [3936] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
95 [3928] INFO TestAsyncAppender - Actually doing 222222222...
95 [3936] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
96 [3928] INFO TestAsyncAppender - Actually doing 333333333...
96 [3928] INFO TestAsyncAppender - Actually doing 444444444...
96 [3928] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
96 [4160] INFO TestAsyncAppender - Actually doing 111111111...
96 [3928] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
96 [4160] INFO TestAsyncAppender - Actually doing 222222222...
96 [4160] INFO TestAsyncAppender - Actually doing 333333333...
96 [4160] INFO TestAsyncAppender - Actually doing 444444444...
97 [4160] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
97 [10984] INFO TestAsyncAppender - Actually doing 111111111...
97 [10984] INFO TestAsyncAppender - Actually doing 222222222...
97 [4160] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
97 [10984] INFO TestAsyncAppender - Actually doing 333333333...
97 [10984] INFO TestAsyncAppender - Actually doing 444444444...
97 [10984] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
97 [3936] INFO TestAsyncAppender - Actually doing 111111111...
98 [10984] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
98 [3936] INFO TestAsyncAppender - Actually doing 222222222...
98 [3936] INFO TestAsyncAppender - Actually doing 333333333...
98 [3936] INFO TestAsyncAppender - Actually doing 444444444...
98 [3936] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
98 [3928] INFO TestAsyncAppender - Actually doing 111111111...
98 [3936] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
98 [3928] INFO TestAsyncAppender - Actually doing 222222222...
99 [3928] INFO TestAsyncAppender - Actually doing 333333333...
99 [3928] INFO TestAsyncAppender - Actually doing 444444444...
99 [4160] INFO TestAsyncAppender - Actually doing 111111111...
99 [3928] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
99 [4160] INFO TestAsyncAppender - Actually doing 222222222...
99 [3928] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
99 [4160] INFO TestAsyncAppender - Actually doing 333333333...
100 [4160] INFO TestAsyncAppender - Actually doing 444444444...
100 [10984] INFO TestAsyncAppender - Actually doing 111111111...
100 [4160] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
100 [10984] INFO TestAsyncAppender - Actually doing 222222222...
100 [4160] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
100 [10984] INFO TestAsyncAppender - Actually doing 333333333...
100 [10984] INFO TestAsyncAppender - Actually doing 444444444...
101 [10984] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
101 [3936] INFO TestAsyncAppender - Actually doing 111111111...
101 [3936] INFO TestAsyncAppender - Actually doing 222222222...
101 [10984] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
101 [3936] INFO TestAsyncAppender - Actually doing 333333333...
101 [3936] INFO TestAsyncAppender - Actually doing 444444444...
101 [3936] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
101 [3928] INFO TestAsyncAppender - Actually doing 111111111...
102 [3936] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
102 [3928] INFO TestAsyncAppender - Actually doing 222222222...
102 [3928] INFO TestAsyncAppender - Actually doing 333333333...
102 [3928] INFO TestAsyncAppender - Actually doing 444444444...
102 [4160] INFO TestAsyncAppender - Actually doing 111111111...
102 [3928] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
102 [4160] INFO TestAsyncAppender - Actually doing 222222222...
102 [3928] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
103 [4160] INFO TestAsyncAppender - Actually doing 333333333...
103 [4160] INFO TestAsyncAppender - Actually doing 444444444...
103 [4160] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
103 [10984] INFO TestAsyncAppender - Actually doing 111111111...
103 [4160] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
103 [10984] INFO TestAsyncAppender - Actually doing 222222222...
103 [10984] INFO TestAsyncAppender - Actually doing 333333333...
104 [10984] INFO TestAsyncAppender - Actually doing 444444444...
104 [10984] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
104 [3936] INFO TestAsyncAppender - Actually doing 111111111...
104 [10984] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
104 [3936] INFO TestAsyncAppender - Actually doing 222222222...
104 [3936] INFO TestAsyncAppender - Actually doing 333333333...
104 [3936] INFO TestAsyncAppender - Actually doing 444444444...
105 [3936] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
105 [3928] INFO TestAsyncAppender - Actually doing 111111111...
105 [3936] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
105 [3928] INFO TestAsyncAppender - Actually doing 222222222...
105 [3928] INFO TestAsyncAppender - Actually doing 333333333...
105 [3928] INFO TestAsyncAppender - Actually doing 444444444...
105 [4160] INFO TestAsyncAppender - Actually doing 111111111...
105 [3928] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
106 [4160] INFO TestAsyncAppender - Actually doing 222222222...
106 [3928] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
106 [4160] INFO TestAsyncAppender - Actually doing 333333333...
106 [4160] INFO TestAsyncAppender - Actually doing 444444444...
106 [4160] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
106 [10984] INFO TestAsyncAppender - Actually doing 111111111...
106 [4160] TRACE TestAsyncAppender - ENTER: In SlowObject::doSomething()
106 [10984] INFO TestAsyncAppender - Actually doing 222222222...
107 [10984] INFO TestAsyncAppender - Actually doing 333333333...
107 [10984] INFO TestAsyncAppender - Actually doing 444444444...
107 [10984] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
107 [3936] INFO TestAsyncAppender - Actually doing 111111111...
107 [10984] DEBUG TestAsyncAppender - Exiting run()...
107 [3936] INFO TestAsyncAppender - Actually doing 222222222...
107 [10984] WARN TestAsyncAppender <> - Thread-0 TestThread.run()- Finished
108 [3936] INFO TestAsyncAppender - Actually doing 333333333...
108 [3936] INFO TestAsyncAppender - Actually doing 444444444...
109 [3936] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
109 [3928] INFO TestAsyncAppender - Actually doing 111111111...
109 [3928] INFO TestAsyncAppender - Actually doing 222222222...
109 [3936] DEBUG TestAsyncAppender - Exiting run()...
109 [3928] INFO TestAsyncAppender - Actually doing 333333333...
109 [3936] WARN TestAsyncAppender <> - Thread-1 TestThread.run()- Finished
109 [3928] INFO TestAsyncAppender - Actually doing 444444444...
110 [3928] TRACE TestAsyncAppender - EXIT: In SlowObject::doSomething()
110 [4160] INFO TestAsyncAppender - Actually doing 111111111...
110 [3928] DEBUG TestAsyncAppender - Exiting run()...
110 [4160] INFO TestAsyncAppender - Actually doing 222222222...
110 [3928] WARN TestAsyncAppender <> - Thread-3 TestThread.run()- Finished
110 [4160] INFO TestAsyncAppender