一、介绍
1.1 log4cplus 介绍
log4cplus是一个易于使用的C++日志API,它提供了对日志管理和配置的线程安全、灵活和任意粒度的控制。它是以Java log4j API为模型的。
1.2 参考资料
- 官方资料(当前最新版本V2.1.1)
- 其他资料
1.3 工程示例
- AsyncAppender 和 RollingFileAppender
log4cplus.rootLogger=TRACE, DEBUG_MSGS, ERROR_MSGS log4cplus.appender.DEBUG_MSGS=log4cplus::AsyncAppender log4cplus.appender.DEBUG_MSGS.Appender=log4cplus::RollingFileAppender log4cplus.appender.DEBUG_MSGS.Appender.MaxFileSize=10MB log4cplus.appender.DEBUG_MSGS.Appender.MaxBackupIndex=2 log4cplus.appender.DEBUG_MSGS.Appender.RollOverAfterClose=true log4cplus.appender.DEBUG_MSGS.Appender.Append=true log4cplus.appender.DEBUG_MSGS.Appender.File=/app/v2x_service/v2x_proxy/debug.log log4cplus.appender.DEBUG_MSGS.Appender.layout=log4cplus::PatternLayout log4cplus.appender.DEBUG_MSGS.Appender.layout.DateFormat=%Y-%m-%d %H:%M:%S.%q log4cplus.appender.DEBUG_MSGS.Appender.layout.ConversionPattern=%D{%Y-%m-%d %H:%M:%S.%q} [%p] [%b:%L] %m%n log4cplus.appender.DEBUG_MSGS.Appender.filters.1=log4cplus::spi::LogLevelRangeFilter log4cplus.appender.DEBUG_MSGS.Appender.filters.1.LogLevelMin=DEBUG log4cplus.appender.DEBUG_MSGS.Appender.filters.1.LogLevelMax=DEBUG log4cplus.appender.DEBUG_MSGS.Appender.filters.1.AcceptOnMatch=true log4cplus.appender.DEBUG_MSGS.Appender.filters.2=log4cplus::spi::DenyAllFilter log4cplus.appender.ERROR_MSGS=log4cplus::AsyncAppender log4cplus.appender.ERROR_MSGS.Appender=log4cplus::RollingFileAppender log4cplus.appender.ERROR_MSGS.Appender.MaxFileSize=10MB log4cplus.appender.ERROR_MSGS.Appender.MaxBackupIndex=2 log4cplus.appender.ERROR_MSGS.Appender.RollOverAfterClose=true log4cplus.appender.ERROR_MSGS.Appender.Append=true log4cplus.appender.ERROR_MSGS.Appender.File=/app/v2x_service/v2x_proxy/error.log log4cplus.appender.ERROR_MSGS.Appender.layout=log4cplus::PatternLayout log4cplus.appender.ERROR_MSGS.Appender.layout.DateFormat=%Y-%m-%d %H:%M:%S.%q log4cplus.appender.ERROR_MSGS.Appender.layout.ConversionPattern=%D{%Y-%m-%d %H:%M:%S.%q} [%p] [%b:%L] %m%n log4cplus.appender.ERROR_MSGS.Appender.filters.1=log4cplus::spi::LogLevelRangeFilter log4cplus.appender.ERROR_MSGS.Appender.filters.1.LogLevelMin=ERROR log4cplus.appender.ERROR_MSGS.Appender.filters.1.LogLevelMax=ERROR log4cplus.appender.ERROR_MSGS.Appender.filters.1.AcceptOnMatch=true log4cplus.appender.ERROR_MSGS.Appender.filters.2=log4cplus::spi::DenyAllFilter
二、配置文件
- Log4Cplus 学习笔记 - 配置文件的使用
- 测试版本 V2.1.1
2.1 概要
配置文件中总共包含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
2.2 Logger的定义和调用
- rootLogger 根日志器:同一份配置,可指定1个
- logger 日志器:同一份配置,可指定多个
2.2.1 rootLogger
配置
#ALL = 日志输出的级别
#RemoteServer, STDOUT, ALL_MSGS, 均为Appender对象
log4cplus.rootLogger=ALL, RemoteServer, STDOUT, ALL_MSGS
调用
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("配置文件名称"));
log4cplus::Logger logger = log4cplus::Logger::getRoot();
2.2.2 logger
配置
log4cplus.logger.ClientLog = ALL, RemoteServer, STDOUT, ALL_MSGS
# ALL 日志级别
# RemoteServer, STDOUT, ALL_MSGS:多个appender
调用
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("配置文件名称"));
log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("ClientLog"));
2.3 日志的级别和输出
2.3.1 日志级别
- 可在
loglevel.cxx
查看
2.3.2 输出函数
代码
#include <log4cplus/consoleappender.h>
#include <log4cplus/layout.h>
#include <log4cplus/logger.h>
#include <log4cplus/ndc.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/thread/threads.h>
#include <log4cplus/helpers/sleep.h>
#include <log4cplus/streams.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/tracelogger.h>
#include <exception>
#include <iostream>
#include <string>
#include <log4cplus/configurator.h>
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
2.4 Appender
常用Appender类型
-
AsyncAppender:异步 Appender,异步日志记录功能,提高性能,需要包装其他 Appender使用。
-
ConsoleAppender:将日志信息输出到控制台或标准错误流。支持设置是否立即刷新输出流以及指定输出的 locale。
-
FileAppender:将日志信息输出到文件中。可以设置文件名、打开模式、是否立即刷新缓冲区等属性。
- RollingFileAppender:按文件大小日志文件,在文件达到一定大小时进行滚动,创建新的日志文件,并保留一定数量的旧日志文件。
- DailyRollingFileAppender:按日期记录日志文件,
- 注意:貌似没办法两个结合,比如又按天数记录,又指定文件大小。
-
SocketAppender:通过网络将日志信息发送到远程服务器。
-
NullAppender:不输出任何日志信息,用于关闭日志记录或作为开发调试的占位符
2.4.1 Appender 家族
官网API当前支持:
2.4.2 Appender 类
2.4.3 AsyncAppender 类
代码
#include <log4cplus/consoleappender.h>
#include <log4cplus/layout.h>
#include <log4cplus/logger.h>
#include <log4cplus/ndc.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/thread/threads.h>
#include <log4cplus/helpers/sleep.h>
#include <log4cplus/streams.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/tracelogger.h>
#include <exception>
#include <iostream>
#include <string>
#include <log4cplus/configurator.h>
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> slowObject(new SlowObject());
Logger logger = Logger::getInstance(LOG4CPLUS_TEXT("TestAsyncAppender"));
log4cplus::helpers::SharedObjectPtr<TestThread> threads[NUM_THREADS];
int i = 0;
for (i = 0; i<NUM_THREADS; ++i) {
tostringstream s;
s << "Thread-" << i;
threads[i] = new TestThread(s.str(), slowObject.get());
}
for (i = 0; i<NUM_THREADS; ++i) {
threads[i]->start();
}
LOG4CPLUS_DEBUG(logger, "All Threads started...");
for (i = 0; i<NUM_THREADS; ++i) {
while (threads[i]->isRunning()) {
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; i<NUM_LOOPS; ++i) {
NDCContextCreator _ndc(LOG4CPLUS_TEXT("loop"));
slow->doSomething();
}
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 <Thread-0> - Entering Run()...
75 [3928] WARN TestAsyncAppender <> - Thread-3 TestThread.run()- Starting...
74 [4160] WARN TestAsyncAppender <> - Thread-2 TestThread.run()- Starting...
75 [3936] DEBUG TestAsyncAppender <Thread-1> - Entering Run()...
75 [10984] TRACE TestAsyncAppender <Thread-0 loop> - ENTER: In SlowObject::doSomething()
76 [3928] DEBUG TestAsyncAppender <Thread-3> - Entering Run()...
76 [4160] DEBUG TestAsyncAppender <Thread-2> - Entering Run()...
76 [3936] TRACE TestAsyncAppender <Thread-1 loop> - ENTER: In SlowObject::doSomething()
76 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 111111111...
76 [3928] TRACE TestAsyncAppender <Thread-3 loop> - ENTER: In SlowObject::doSomething()
76 [4160] TRACE TestAsyncAppender <Thread-2 loop> - ENTER: In SlowObject::doSomething()
76 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 222222222...
77 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 333333333...
77 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 444444444...
77 [10984] TRACE TestAsyncAppender <Thread-0 loop> - EXIT: In SlowObject::doSomething()
77 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 111111111...
77 [10984] TRACE TestAsyncAppender <Thread-0 loop> - ENTER: In SlowObject::doSomething()
77 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 222222222...
78 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 333333333...
78 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 444444444...
78 [3936] TRACE TestAsyncAppender <Thread-1 loop> - EXIT: In SlowObject::doSomething()
78 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 111111111...
78 [3936] TRACE TestAsyncAppender <Thread-1 loop> - ENTER: In SlowObject::doSomething()
78 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 222222222...
78 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 333333333...
79 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 444444444...
79 [3928] TRACE TestAsyncAppender <Thread-3 loop> - EXIT: In SlowObject::doSomething()
79 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 111111111...
79 [3928] TRACE TestAsyncAppender <Thread-3 loop> - ENTER: In SlowObject::doSomething()
79 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 222222222...
79 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 333333333...
79 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 444444444...
80 [4160] TRACE TestAsyncAppender <Thread-2 loop> - EXIT: In SlowObject::doSomething()
80 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 111111111...
80 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 222222222...
80 [4160] TRACE TestAsyncAppender <Thread-2 loop> - ENTER: In SlowObject::doSomething()
80 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 333333333...
80 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 444444444...
80 [10984] TRACE TestAsyncAppender <Thread-0 loop> - EXIT: In SlowObject::doSomething()
80 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 111111111...
81 [10984] TRACE TestAsyncAppender <Thread-0 loop> - ENTER: In SlowObject::doSomething()
81 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 222222222...
81 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 333333333...
81 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 444444444...
81 [3936] TRACE TestAsyncAppender <Thread-1 loop> - EXIT: In SlowObject::doSomething()
81 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 111111111...
82 [3936] TRACE TestAsyncAppender <Thread-1 loop> - ENTER: In SlowObject::doSomething()
82 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 222222222...
82 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 333333333...
82 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 444444444...
82 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 111111111...
82 [3928] TRACE TestAsyncAppender <Thread-3 loop> - EXIT: In SlowObject::doSomething()
82 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 222222222...
83 [3928] TRACE TestAsyncAppender <Thread-3 loop> - ENTER: In SlowObject::doSomething()
83 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 333333333...
83 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 444444444...
83 [4160] TRACE TestAsyncAppender <Thread-2 loop> - EXIT: In SlowObject::doSomething()
83 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 111111111...
83 [4160] TRACE TestAsyncAppender <Thread-2 loop> - ENTER: In SlowObject::doSomething()
83 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 222222222...
84 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 333333333...
84 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 444444444...
84 [10984] TRACE TestAsyncAppender <Thread-0 loop> - EXIT: In SlowObject::doSomething()
84 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 111111111...
84 [10984] TRACE TestAsyncAppender <Thread-0 loop> - ENTER: In SlowObject::doSomething()
84 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 222222222...
85 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 333333333...
85 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 444444444...
85 [3936] TRACE TestAsyncAppender <Thread-1 loop> - EXIT: In SlowObject::doSomething()
85 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 111111111...
85 [3936] TRACE TestAsyncAppender <Thread-1 loop> - ENTER: In SlowObject::doSomething()
85 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 222222222...
85 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 333333333...
86 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 444444444...
86 [3928] TRACE TestAsyncAppender <Thread-3 loop> - EXIT: In SlowObject::doSomething()
86 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 111111111...
86 [3928] TRACE TestAsyncAppender <Thread-3 loop> - ENTER: In SlowObject::doSomething()
86 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 222222222...
86 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 333333333...
87 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 444444444...
87 [4160] TRACE TestAsyncAppender <Thread-2 loop> - EXIT: In SlowObject::doSomething()
87 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 111111111...
87 [4160] TRACE TestAsyncAppender <Thread-2 loop> - ENTER: In SlowObject::doSomething()
87 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 222222222...
87 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 333333333...
87 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 444444444...
88 [10984] TRACE TestAsyncAppender <Thread-0 loop> - EXIT: In SlowObject::doSomething()
88 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 111111111...
88 [10984] TRACE TestAsyncAppender <Thread-0 loop> - ENTER: In SlowObject::doSomething()
88 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 222222222...
88 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 333333333...
88 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 444444444...
88 [3936] TRACE TestAsyncAppender <Thread-1 loop> - EXIT: In SlowObject::doSomething()
88 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 111111111...
89 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 222222222...
89 [3936] TRACE TestAsyncAppender <Thread-1 loop> - ENTER: In SlowObject::doSomething()
89 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 333333333...
89 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 444444444...
89 [3928] TRACE TestAsyncAppender <Thread-3 loop> - EXIT: In SlowObject::doSomething()
89 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 111111111...
89 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 222222222...
89 [3928] TRACE TestAsyncAppender <Thread-3 loop> - ENTER: In SlowObject::doSomething()
90 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 333333333...
90 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 444444444...
90 [4160] TRACE TestAsyncAppender <Thread-2 loop> - EXIT: In SlowObject::doSomething()
90 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 111111111...
90 [4160] TRACE TestAsyncAppender <Thread-2 loop> - ENTER: In SlowObject::doSomething()
90 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 222222222...
91 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 333333333...
91 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 444444444...
91 [10984] TRACE TestAsyncAppender <Thread-0 loop> - EXIT: In SlowObject::doSomething()
91 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 111111111...
91 [10984] TRACE TestAsyncAppender <Thread-0 loop> - ENTER: In SlowObject::doSomething()
91 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 222222222...
91 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 333333333...
92 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 444444444...
92 [3936] TRACE TestAsyncAppender <Thread-1 loop> - EXIT: In SlowObject::doSomething()
92 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 111111111...
92 [3936] TRACE TestAsyncAppender <Thread-1 loop> - ENTER: In SlowObject::doSomething()
92 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 222222222...
92 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 333333333...
92 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 444444444...
93 [3928] TRACE TestAsyncAppender <Thread-3 loop> - EXIT: In SlowObject::doSomething()
93 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 111111111...
93 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 222222222...
93 [3928] TRACE TestAsyncAppender <Thread-3 loop> - ENTER: In SlowObject::doSomething()
93 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 333333333...
93 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 444444444...
93 [4160] TRACE TestAsyncAppender <Thread-2 loop> - EXIT: In SlowObject::doSomething()
93 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 111111111...
94 [4160] TRACE TestAsyncAppender <Thread-2 loop> - ENTER: In SlowObject::doSomething()
94 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 222222222...
94 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 333333333...
94 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 444444444...
94 [10984] TRACE TestAsyncAppender <Thread-0 loop> - EXIT: In SlowObject::doSomething()
94 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 111111111...
95 [10984] TRACE TestAsyncAppender <Thread-0 loop> - ENTER: In SlowObject::doSomething()
95 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 222222222...
95 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 333333333...
95 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 444444444...
95 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 111111111...
95 [3936] TRACE TestAsyncAppender <Thread-1 loop> - EXIT: In SlowObject::doSomething()
95 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 222222222...
95 [3936] TRACE TestAsyncAppender <Thread-1 loop> - ENTER: In SlowObject::doSomething()
96 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 333333333...
96 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 444444444...
96 [3928] TRACE TestAsyncAppender <Thread-3 loop> - EXIT: In SlowObject::doSomething()
96 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 111111111...
96 [3928] TRACE TestAsyncAppender <Thread-3 loop> - ENTER: In SlowObject::doSomething()
96 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 222222222...
96 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 333333333...
96 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 444444444...
97 [4160] TRACE TestAsyncAppender <Thread-2 loop> - EXIT: In SlowObject::doSomething()
97 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 111111111...
97 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 222222222...
97 [4160] TRACE TestAsyncAppender <Thread-2 loop> - ENTER: In SlowObject::doSomething()
97 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 333333333...
97 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 444444444...
97 [10984] TRACE TestAsyncAppender <Thread-0 loop> - EXIT: In SlowObject::doSomething()
97 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 111111111...
98 [10984] TRACE TestAsyncAppender <Thread-0 loop> - ENTER: In SlowObject::doSomething()
98 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 222222222...
98 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 333333333...
98 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 444444444...
98 [3936] TRACE TestAsyncAppender <Thread-1 loop> - EXIT: In SlowObject::doSomething()
98 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 111111111...
98 [3936] TRACE TestAsyncAppender <Thread-1 loop> - ENTER: In SlowObject::doSomething()
98 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 222222222...
99 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 333333333...
99 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 444444444...
99 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 111111111...
99 [3928] TRACE TestAsyncAppender <Thread-3 loop> - EXIT: In SlowObject::doSomething()
99 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 222222222...
99 [3928] TRACE TestAsyncAppender <Thread-3 loop> - ENTER: In SlowObject::doSomething()
99 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 333333333...
100 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 444444444...
100 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 111111111...
100 [4160] TRACE TestAsyncAppender <Thread-2 loop> - EXIT: In SlowObject::doSomething()
100 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 222222222...
100 [4160] TRACE TestAsyncAppender <Thread-2 loop> - ENTER: In SlowObject::doSomething()
100 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 333333333...
100 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 444444444...
101 [10984] TRACE TestAsyncAppender <Thread-0 loop> - EXIT: In SlowObject::doSomething()
101 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 111111111...
101 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 222222222...
101 [10984] TRACE TestAsyncAppender <Thread-0 loop> - ENTER: In SlowObject::doSomething()
101 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 333333333...
101 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 444444444...
101 [3936] TRACE TestAsyncAppender <Thread-1 loop> - EXIT: In SlowObject::doSomething()
101 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 111111111...
102 [3936] TRACE TestAsyncAppender <Thread-1 loop> - ENTER: In SlowObject::doSomething()
102 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 222222222...
102 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 333333333...
102 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 444444444...
102 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 111111111...
102 [3928] TRACE TestAsyncAppender <Thread-3 loop> - EXIT: In SlowObject::doSomething()
102 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 222222222...
102 [3928] TRACE TestAsyncAppender <Thread-3 loop> - ENTER: In SlowObject::doSomething()
103 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 333333333...
103 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 444444444...
103 [4160] TRACE TestAsyncAppender <Thread-2 loop> - EXIT: In SlowObject::doSomething()
103 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 111111111...
103 [4160] TRACE TestAsyncAppender <Thread-2 loop> - ENTER: In SlowObject::doSomething()
103 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 222222222...
103 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 333333333...
104 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 444444444...
104 [10984] TRACE TestAsyncAppender <Thread-0 loop> - EXIT: In SlowObject::doSomething()
104 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 111111111...
104 [10984] TRACE TestAsyncAppender <Thread-0 loop> - ENTER: In SlowObject::doSomething()
104 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 222222222...
104 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 333333333...
104 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 444444444...
105 [3936] TRACE TestAsyncAppender <Thread-1 loop> - EXIT: In SlowObject::doSomething()
105 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 111111111...
105 [3936] TRACE TestAsyncAppender <Thread-1 loop> - ENTER: In SlowObject::doSomething()
105 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 222222222...
105 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 333333333...
105 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 444444444...
105 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 111111111...
105 [3928] TRACE TestAsyncAppender <Thread-3 loop> - EXIT: In SlowObject::doSomething()
106 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 222222222...
106 [3928] TRACE TestAsyncAppender <Thread-3 loop> - ENTER: In SlowObject::doSomething()
106 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 333333333...
106 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 444444444...
106 [4160] TRACE TestAsyncAppender <Thread-2 loop> - EXIT: In SlowObject::doSomething()
106 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 111111111...
106 [4160] TRACE TestAsyncAppender <Thread-2 loop> - ENTER: In SlowObject::doSomething()
106 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 222222222...
107 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 333333333...
107 [10984] INFO TestAsyncAppender <Thread-0 loop> - Actually doing 444444444...
107 [10984] TRACE TestAsyncAppender <Thread-0 loop> - EXIT: In SlowObject::doSomething()
107 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 111111111...
107 [10984] DEBUG TestAsyncAppender <Thread-0> - Exiting run()...
107 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 222222222...
107 [10984] WARN TestAsyncAppender <> - Thread-0 TestThread.run()- Finished
108 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 333333333...
108 [3936] INFO TestAsyncAppender <Thread-1 loop> - Actually doing 444444444...
109 [3936] TRACE TestAsyncAppender <Thread-1 loop> - EXIT: In SlowObject::doSomething()
109 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 111111111...
109 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 222222222...
109 [3936] DEBUG TestAsyncAppender <Thread-1> - Exiting run()...
109 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 333333333...
109 [3936] WARN TestAsyncAppender <> - Thread-1 TestThread.run()- Finished
109 [3928] INFO TestAsyncAppender <Thread-3 loop> - Actually doing 444444444...
110 [3928] TRACE TestAsyncAppender <Thread-3 loop> - EXIT: In SlowObject::doSomething()
110 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 111111111...
110 [3928] DEBUG TestAsyncAppender <Thread-3> - Exiting run()...
110 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 222222222...
110 [3928] WARN TestAsyncAppender <> - Thread-3 TestThread.run()- Finished
110 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 333333333...
111 [4160] INFO TestAsyncAppender <Thread-2 loop> - Actually doing 444444444...
111 [4160] TRACE TestAsyncAppender <Thread-2 loop> - EXIT: In SlowObject::doSomething()
111 [4160] DEBUG TestAsyncAppender <Thread-2> - Exiting run()...
111 [4160] WARN TestAsyncAppender <> - Thread-2 TestThread.run()- Finished
112 [6608] INFO TestAsyncAppender <> - Exiting main()...
112 [6608] INFO TestAsyncAppender <> - Out SlowObject
2.4.4 FileAppenderBase 类
2.4.5 FileAppender 类
没有额外的附加属性。
#include <iostream>
#include <log4cplus/ndc.h>
#include <log4cplus/logger.h>
#include <log4cplus/helpers/sleep.h>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/configurator.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
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
2.4.6 RollingFileAppender 类
通过控制每个文件大小以及总文件数量控制日志的量
代码
#include <iostream>
#include <log4cplus/ndc.h>
#include <log4cplus/logger.h>
#include <log4cplus/helpers/sleep.h>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/configurator.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
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。
2.4.7 DailyRollingFileAppender 类
代码
#include <iostream>
#include <log4cplus/ndc.h>
#include <log4cplus/logger.h>
#include <log4cplus/helpers/sleep.h>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/configurator.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
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
注意:需要改变系统时间做测试~
2.4.8 SocketAppender 类
客户端
#include <iostream>
#include <log4cplus/ndc.h>
#include <log4cplus/logger.h>
#include <log4cplus/helpers/sleep.h>
#include <log4cplus/helpers/pointer.h>
#include <log4cplus/configurator.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
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 <cstdlib>
#include <iostream>
#include <log4cplus/configurator.h>
#include <log4cplus/socketappender.h>
#include <log4cplus/helpers/socket.h>
#include <log4cplus/thread/threads.h>
#include <log4cplus/spi/loggingevent.h>
#include <log4cplus\helpers\pointer.h>
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
2.5 layout
- SimpleLayout
- 描述:SimpleLayout 是一种最简单的日志格式化方式,它通常只包括日志级别和消息文本。这种布局设计得非常轻量级,适合那些不需要复杂格式化信息的场合(不包含时间戳等)。
- 输出示例:[DEBUG] This is a debug message.
- PatternLayout
- 最为灵活的 Layout 类型,允许用户通过模式字符串(Conversion Pattern)自定义日志的输出格式。模式字符串可以包含各种转换说明符,如日期时间、日志级别、线程名、日志消息等。
- log4cplus::PatternLayout Class Reference
- 转换说明符:
%d:表示日期时间,可以自定义格式。
%p:表示日志级别。
%c:表示日志器的名称。
%m:表示日志消息。
%n:表示换行符。
还有更多其他的转换说明符,如线程名、进程ID等。 - 输出示例:[2023-04-05 14:23:45] [DEBUG] myapp - This is a debug message.
- TTCCLayout
- 描述:TTCCLayout 的全称是 Time, Thread, Category, and Cost (Time in milliseconds), 它提供了一种详细的日志格式,通常用于需要完整上下文信息的场景。这种布局包含了时间戳、线程名、日志器名称以及日志消息。
- 输出示例:2023-04-05 14:23:45,123 - myapp - [Thread 12345] - DEBUG - This is a debug message.
2.5.1 PatternLayout
代码
#include <iostream>
#include <log4cplus\ndc.h>
#include <log4cplus/logger.h>
#include <log4cplus\helpers\sleep.h>
#include <log4cplus\helpers\pointer.h>
#include <log4cplus/configurator.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
int main()
{
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("PatternLayout.txt"));
log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TestPatternLayout"));
NDCContextCreator _first_ndc(LOG4CPLUS_TEXT("This-is-Thread-Name"));
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;
}
配置文件
log4cplus.logger.TestPatternLayout = ALL, Test
# 创建Appender对象
log4cplus.appender.Test = log4cplus::FileAppender
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
# layout类属性
log4cplus.appender.Test.layout = log4cplus::PatternLayout
log4cplus.appender.Test.layout.NDCMaxDepth = 5
log4cplus.appender.Test.layout.ConversionPattern = %d{%Y-%m-%d} %F-%L-%M <%x> %m %n
结果
2020-04-27 ..\..\tests\appender_test\main.cxx-23-int __cdecl main(void) <This-is-Thread-Name> DEBUG-LOG-TEST
2020-04-27 ..\..\tests\appender_test\main.cxx-24-int __cdecl main(void) <This-is-Thread-Name> INFO-LOG-TEST
2020-04-27 ..\..\tests\appender_test\main.cxx-25-int __cdecl main(void) <This-is-Thread-Name> WARN-LOG-TEST
2020-04-27 ..\..\tests\appender_test\main.cxx-26-int __cdecl main(void) <This-is-Thread-Name> ERROR-LOG-TEST
2.5.2 SimpleLayout
代码
#include <iostream>
#include <log4cplus\ndc.h>
#include <log4cplus/logger.h>
#include <log4cplus\helpers\sleep.h>
#include <log4cplus\helpers\pointer.h>
#include <log4cplus/configurator.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
int main()
{
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("SimpleLayout.txt"));
log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TestSimpleLayout"));
NDCContextCreator _first_ndc(LOG4CPLUS_TEXT("This-is-Thread-Name"));
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;
}
配置文件
log4cplus.logger.TestSimpleLayout = ALL, Test
log4cplus.appender.Test = log4cplus::FileAppender
log4cplus.appender.Test.File = Test.log
log4cplus.appender.Test.layout = log4cplus::SimpleLayout
输出结果
DEBUG - DEBUG-LOG-TEST
INFO - INFO-LOG-TEST
WARN - WARN-LOG-TEST
ERROR - ERROR-LOG-TEST
2.5.3 TTCCLayout
代码
#include <iostream>
#include <log4cplus\ndc.h>
#include <log4cplus/logger.h>
#include <log4cplus\helpers\sleep.h>
#include <log4cplus\helpers\pointer.h>
#include <log4cplus/configurator.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
int main()
{
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("TTCCLayout.txt"));
log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TestTTCCLayout"));
NDCContextCreator _first_ndc(LOG4CPLUS_TEXT("This-is-Thread-Name"));
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;
}
配置文件
log4cplus.logger.TestTTCCLayout = ALL, Test
log4cplus.appender.Test = log4cplus::FileAppender
log4cplus.appender.Test.File = Test.log
log4cplus.appender.Test.layout = log4cplus::TTCCLayout
log4cplus.appender.Test.layout.DateFormat = %Y-%m@%d
输出结果
- 格式:时间 线程ID Logger名称 线程名称 日志内容
2020-04@19 [8844] DEBUG TestSimpleLayout <This-is-Thread-Name> - DEBUG-LOG-TEST
2020-04@19 [8844] INFO TestSimpleLayout <This-is-Thread-Name> - INFO-LOG-TEST
2020-04@19 [8844] WARN TestSimpleLayout <This-is-Thread-Name> - WARN-LOG-TEST
2020-04@19 [8844] ERROR TestSimpleLayout <This-is-Thread-Name> - ERROR-LOG-TEST
2.5.4 转换标识符
关于日期时间输出的转换标志符可用在三个地方
- DailyRollingFileAppender 中的 DatePattern,格式为 %Y-%m-%d
- TTCCLayout 中的 DateFormat,格式为 %Y-%m-%d
- PatternLayout 中的 ConversionPattern,格式为 %d{%Y-%m-%d}
2.6 filter
- LogLevelMatchFilter:根据特定的日志级别进行过滤
- 过滤条件包括LogLevelToMatch和AcceptOnMatch(true|false), 只有当日志的LogLevel值与LogLevelToMatch相同,且AcceptOnMatch为true时才会匹配。
- LogLevelRangeFilter:根据根据日志级别的范围进行过滤。
- 过滤条件包括LogLevelMin、LogLevelMax和AcceptOnMatch,只有当日志的LogLevel在LogLevelMin、LogLevelMax之间同时AcceptOnMatch为true时才会匹配。
- StringMatchFilter:根据日志内容是否包含特定字符串进行过滤。
- 过滤条件包括StringToMatch和AcceptOnMatch,只有当日志包含StringToMatch字符串 且AcceptOnMatch为true时会匹配。
- DenyAllFilter:过滤掉所有消息。
过滤条件处理机制类似于Linux中IPTABLE的Responsibility chain机制,(即先deny、再allow)不过执行顺序刚好相反,后写的条件会被先执行,比如:
log4cplus.appender.append_1.filters.1=log4cplus::spi::LogLevelMatchFilter
log4cplus.appender.append_1.filters.1.LogLevelToMatch=TRACE
log4cplus.appender.append_1.filters.1.AcceptOnMatch=true
log4cplus.appender.append_1.filters.2=log4cplus::spi::DenyAllFilter
会首先执行filters.2的过滤条件,关闭所有过滤器,然后执行filters.1,仅匹配TRACE信息。
2.6.1 LogLevelRangeFilter
根据根据日志级别的范围进行过滤,只有当日志的LogLevel在LogLevelMin、LogLevelMax之间同时AcceptOnMatch为true时才会匹配。
代码
#include <iostream>
#include <log4cplus\ndc.h>
#include <log4cplus/logger.h>
#include <log4cplus\helpers\sleep.h>
#include <log4cplus\helpers\pointer.h>
#include <log4cplus/configurator.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
int main()
{
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("Filter.txt"));
log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TestFilter"));
//NDCContextCreator _first_ndc(LOG4CPLUS_TEXT("This-is-Thread-Name"));
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.TestFilter = ALL, Test
# 创建Appender对象
log4cplus.appender.Test = log4cplus::FileAppender
log4cplus.appender.Test.File = Test/FileAppenderLog.txt
log4cplus.appender.Test.ImmediateFlush = true
log4cplus.appender.Test.Append = false
log4cplus.appender.Test.ImmediateFlush = false
log4cplus.appender.Test.CreateDirs = true
# Layout类属性
log4cplus.appender.Test.layout = log4cplus::SimpleLayout
# Filter属性
log4cplus.appender.Test.filters.1 = log4cplus::spi::LogLevelRangeFilter
log4cplus.appender.Test.filters.1.LogLevelMin = TRACE
log4cplus.appender.Test.filters.1.LogLevelMax = INFO
log4cplus.appender.Test.filters.1.AcceptOnMatch = true
log4cplus.appender.Test.filters.2 = log4cplus::spi::DenyAllFilter
结果
TRACE - TRACE-LOG-TEST
DEBUG - DEBUG-LOG-TEST
INFO - INFO-LOG-TEST
2.6.2 LogLevelMatchFilter
根据特定的日志级别进行过滤,只有当日志的LogLevel值与LogLevelToMatch相同,且AcceptOnMatch为true时才会匹配。
代码
#include <iostream>
#include <log4cplus\ndc.h>
#include <log4cplus/logger.h>
#include <log4cplus\helpers\sleep.h>
#include <log4cplus\helpers\pointer.h>
#include <log4cplus/configurator.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/helpers/stringhelper.h>
using namespace std;
using namespace log4cplus;
using namespace log4cplus::helpers;
int main()
{
log4cplus::initialize();
log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("Filter.txt"));
log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("TestFilter"));
//NDCContextCreator _first_ndc(LOG4CPLUS_TEXT("This-is-Thread-Name"));
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.TestFilter = ALL, Test
# 创建Appender对象
log4cplus.appender.Test = log4cplus::FileAppender
log4cplus.appender.Test.File = Test/FileAppenderLog.txt
log4cplus.appender.Test.ImmediateFlush = true
log4cplus.appender.Test.Append = false
log4cplus.appender.Test.ImmediateFlush = false
log4cplus.appender.Test.CreateDirs = true
# Layout类属性
log4cplus.appender.Test.layout = log4cplus::SimpleLayout
# Filter属性
log4cplus.appender.Test.filters.1 = log4cplus::spi::LogLevelMatchFilter
log4cplus.appender.Test.filters.1.LogLevelToMatch = TRACE
log4cplus.appender.Test.filters.1.AcceptOnMatch = true
log4cplus.appender.Test.filters.2 = log4cplus::spi::DenyAllFilter
结果
TRACE - TRACE-LOG-TEST
三、使用
2.1 log4cplus 编译和交叉编译
log4cplus是一个易于使用的C++11日志API,它提供了对日志管理和配置的线程安全、灵活和任意粒度的控制。它是以Java log4j API为模型的。
2.1.1 源码下载
- 当前最新版本: v2.1.1:https://sourceforge.net/projects/log4cplus/
2.1.2 配置编译参数、编译安装
-
x64 本机编译
./configure --prefix=$PWD/install_x64 --enable-static make -j make install
-
imx6q 交叉编译 (./configure -h 查看手册)
export CC="arm-fslc-linux-gnueabi-gcc -march=armv7-a -mthumb -mfpu=neon -mfloat-abi=hard --sysroot=/opt/fslc-x11/2.4.4/sysroots/armv7at2hf-neon-fslc-linux-gnueabi" export CXX="arm-fslc-linux-gnueabi-g++ -march=armv7-a -mthumb -mfpu=neon -mfloat-abi=hard --sysroot=/opt/fslc-x11/2.4.4/sysroots/armv7at2hf-neon-fslc-linux-gnueabi" ./configure --prefix=$PWD/install_imx6q --host=arm-fslc-linux-gnueabi --enable-static make -j make install
2.1.3 使用
- 配置文件
- API 接口(可不用配置文件)