C++ 技术中心

   :: 首页 :: 联系 ::  :: 管理
  155 Posts :: 0 Stories :: 84 Comments :: 0 Trackbacks

公告

郑重声明:本BLOG所发表的原创文章,作者保留一切权利。必须经过作者本人同意后方可转载,并注名作者(天空)和出处(CppBlog.com)。作者Email:6549168@qq.com

留言簿(6)

搜索

  •  

最新随笔

最新评论

评论排行榜

一.简介
    log4cplus是一个日志记录的库,目的很简单,就是把合适的信息送到正确的位置上去。在服务器程序上使用非常方便。
    开发库下载地址可以去baidu搜一下,是开源的哦!

二.组成
  Log4cplus 由4部分组成:
 (1) Logger          日志模块,程序中唯一一个必须得使用的模块,解决了在哪里使用日志的问题
 (2) Appenders    接收日志的各个设备,如控制台、文件、网络等。解决了输出到哪里去的问题
 (3)Layout           格式化输出信息,解决了如何输出的问题。
 (4)Filter              过滤器,解决哪些信息需要输出的问题,比如DEBUG,WARR,INFO等的输出控制.
  Log4cplus的主要部件关系图如下:


三.一些简单示例
(1) 各对象可以看下上图理解一下,以下为 严格实现步骤1-6
#include <log4cplus/logger.h>
#include 
<log4cplus/configurator.h>
#include 
<iostream>
#include 
<log4cplus/consoleappender.h>
#include 
<log4cplus/layout.h>
#include 
<conio.h>
#include 
<log4cplus/helpers/sleep.h>

using namespace log4cplus;
using namespace log4cplus::helpers;  

int _tmain(int argc, _TCHAR* argv[]){   
    
/* step 1: Instantiate an appender object */   
    SharedObjectPtr
<Appender> _append (new ConsoleAppender());    
    _append
->setName(LOG4CPLUS_TEXT("append for test"));   
    
/* step 2: Instantiate a layout object */    
    
//std::string pattern = ;   
    std::auto_ptr<Layout> _layout(new PatternLayout(LOG4CPLUS_TEXT("%d{%m/%d/%y %H:%M:%S}  - %m [%l]%n")));   
    
/* step 3: Attach the layout object to the appender */   
    _append
->setLayout( _layout );   
    
/* step 4: Instantiate a logger object */   
    Logger _logger 
= Logger::getInstance(LOG4CPLUS_TEXT("test"));  
    
/* step 5: Attach the appender object to the logger  */  
    _logger.addAppender(_append);   
    
/* step 6: Set a priority for the logger  */   
    _logger.setLogLevel(ALL_LOG_LEVEL);   
    
/* log activity */    
    LOG4CPLUS_DEBUG(_logger, 
"This is the FIRST log message");
    sleep(
1);   
    LOG4CPLUS_WARN(_logger, 
"This is the SECOND log message"); 
    
    _getch();
    
return 0;
}

(2) 简洁使用模式,appender输出到屏幕
#include "stdafx.h"
#pragma comment(lib,
"../bin/log4cplusD.lib")

#include 
<log4cplus/logger.h>
#include 
<log4cplus/configurator.h>
#include 
<iostream>
#include 
<log4cplus/consoleappender.h>
#include 
<log4cplus/layout.h>
#include 
<conio.h>
#include 
<log4cplus/helpers/sleep.h>

using namespace log4cplus;
using namespace log4cplus::helpers;  

int _tmain(int argc, _TCHAR* argv[]){   
    
    
/* step 1: Instantiate an appender object */    
    SharedAppenderPtr _append(
new ConsoleAppender());    
    _append
->setName(LOG4CPLUS_TEXT("append test"));    
    
    
/* step 4: Instantiate a logger object */    
    Logger _logger 
= Logger::getInstance(LOG4CPLUS_TEXT("test"));    
    
    
/* step 5: Attach the appender object to the logger  */    
    _logger.addAppender(_append);    
    
    
/* log activity */    
    LOG4CPLUS_DEBUG(_logger, 
"This is the FIRST log message");
    sleep(
1);
    LOG4CPLUS_WARN(_logger, 
"This is the SECOND log message");   
    
    _getch();
    
return 0;
}


(3)简洁使用模式,appender输出到屏幕
#include "stdafx.h"
#pragma comment(lib,
"../bin/log4cplusD.lib")

#include 
<log4cplus/logger.h>
#include 
<log4cplus/configurator.h>
#include 
<iostream>
#include 
<log4cplus/consoleappender.h>
#include 
<log4cplus/layout.h>
#include 
<conio.h>
#include 
<log4cplus/helpers/sleep.h>

using namespace log4cplus;
using namespace log4cplus::helpers;  
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){   
    
    
    
/* step 1: Instantiate an appender object */    
    SharedAppenderPtr _append(
new ConsoleAppender());   
    _append
->setName(LOG4CPLUS_TEXT("append test"));    
    
    
/* step 4: Instantiate a logger object */    
    Logger _logger 
= Logger::getInstance(LOG4CPLUS_TEXT("test"));    
    
    
/* step 5: Attach the appender object to the logger  */    
    _logger.addAppender(_append);    
    
    
/* log activity */    
    LOG4CPLUS_TRACE(_logger, 
"This is"  << " just a t" << "est." << std::endl) ;  //不会被打印 
    LOG4CPLUS_DEBUG(_logger, "This is a bool: " << true);    
    LOG4CPLUS_INFO(_logger, 
"This is a char: " << 'x') ;   
    LOG4CPLUS_WARN(_logger, 
"This is a int: " << 1000) ;   
    LOG4CPLUS_ERROR(_logger, 
"This is a long(hex): " << std::hex << 100000000) ;   
    LOG4CPLUS_FATAL(_logger, 
"This is a double: "   << 1.2345234234);
    
    _getch();
    
return 0;
}

(4)通过loglog来控制输出调试、警告或错误信息,appender输出到屏幕。
#include "stdafx.h"
#pragma comment(lib,
"../bin/log4cplusD.lib")

#include 
<log4cplus/logger.h>
#include 
<log4cplus/configurator.h>
#include 
<iostream>
#include 
<log4cplus/consoleappender.h>
#include 
<log4cplus/layout.h>
#include 
<conio.h>
#include 
<log4cplus/helpers/sleep.h>
#include 
<log4cplus/helpers/loglog.h>

using namespace log4cplus;
using namespace log4cplus::helpers;  
using namespace std;

void printMsgs(void){    
    std::cout 
<< "Entering printMsgs()" << std::endl;    
    LogLog::getLogLog()
->debug(LOG4CPLUS_TEXT("This is a Debug statement"));    
    LogLog::getLogLog()
->warn(LOG4CPLUS_TEXT("This is a Warning"));    
    LogLog::getLogLog()
->error(LOG4CPLUS_TEXT("This is a Error"));    
    std::cout 
<< "Exiting printMsgs()" << std::endl << std::endl;
}



int _tmain(int argc, _TCHAR* argv[]){   
    
/*       
    LogLog类实现了debug, warn, error 函数用于输出调试、警告或错误信息,       
    同时提供了两个方法来进一步控制所输出的信息,其中:
    setInternalDebugging方法用来控制是否屏蔽输出信息中的调试信息,当输
    入参数为false则屏蔽,缺省设置为    false。
    setQuietMode方法用来控制是否屏蔽所有输出信息,当输入参数为true则屏蔽,
    缺省设置为false。 
    LogLog::getLogLog()->setInternalDebugging(false);   
*/

    
    
//默认级别是不打印debug信息
    printMsgs();    
    std::cout 
<< "Turning on debug" << std::endl;    
    LogLog::getLogLog()
->setInternalDebugging(true);    
    
    
//打开debug方式
    
//全部打印
    printMsgs();    
    std::cout 
<< "Turning on quiet mode" << std::endl;    
    LogLog::getLogLog()
->setQuietMode(true);    
    
    
//屏蔽所有输出信息,所以不全打印各种级别信息
    printMsgs();

    _getch();
    
return 0;
}


/*输入结果如下:
Entering printMsgs()
log4cplus:WARN This is a Warning
log4cplus:ERROR This is a Error
Exiting printMsgs()

Turning on debug
Entering printMsgs()
log4cplus: This is a Debug statement
log4cplus:WARN This is a Warning
log4cplus:ERROR This is a Error
Exiting printMsgs()

Turning on quiet mode
Entering printMsgs()
Exiting printMsgs()
都有个log4cplus:打头,可以自定义修改以下部分代码
LogLog::LogLog() : mutex(LOG4CPLUS_MUTEX_CREATE),   debugEnabled(false),  
 quietMode(false),   PREFIX( LOG4CPLUS_TEXT("log4cplus: ") ),  
  WARN_PREFIX( LOG4CPLUS_TEXT("log4cplus:WARN ") ),   
  ERR_PREFIX( LOG4CPLUS_TEXT("log4cplus:ERROR ") ){}
*/


(5)文件模式,appender输出到文件
#include "stdafx.h"
#pragma comment(lib,
"../bin/log4cplusD.lib")

#include 
<log4cplus/logger.h>
#include 
<log4cplus/fileappender.h>
#include 
<conio.h>

using namespace log4cplus;
int _tmain(int argc, _TCHAR* argv[]){   
    
    
/* step 1: Instantiate an appender object */    
    SharedAppenderPtr _append(
new FileAppender(LOG4CPLUS_TEXT("Test.log")));    
    _append
->setName(LOG4CPLUS_TEXT("file log test"));    
    
    
/* step 4: Instantiate a logger object */    
    Logger _logger 
= Logger::getInstance(LOG4CPLUS_TEXT("test.subtestof_filelog"));    
    
    
/* step 5: Attach the appender object to the logger  */   
    _logger.addAppender(_append);    
    
    
/* log activity */    
    
int i;    
    
for( i = 0; i < 5++i ) 
    
{        
        LOG4CPLUS_DEBUG(_logger, 
"Entering loop #" << i << "End line #");
    }

    
    _getch();

}

一、简介:

log4cplus是C++编写的开源的日志系统. 具有线程安全、灵活、以及多粒度控制的特点,通过将信息划分优先级使其可以面向程序调试、运行、测试、和维护等全生命周期; 你可以选择将信息输出到屏幕、文件、NT event log、甚至是远程服务器;通过指定策略对日志进行定期备份等等。 

二、基本要素

将log4cplus文件夹下的msvc10文件夹拷贝出来,使用VS10打开工程,编译源代码和用例。

Layouts:布局器,控制输出消息的格式。

Appenders:挂接器,与布局器紧密配合,将特定格式的消息输出到所挂接

的设备终端如屏幕,文件等等)。

Logger:记录器,保存并跟踪对象日志信息变更的实体,当你需要对一个对

象进行记录时,就需要生成一个logger。

Categories:分类器,层次化(hierarchy)的结构,用于对被记录信息的

分类,层次中每一个节点维护一个logger的所有信息。

Priorities:优先权,包括TRACE, DEBUG, INFO, WARNING, ERROR, FATAL。

三、基本使用
使用log4cplus的六个步骤:

1. 实例化一个appender对象: new ConsoleAppender();

2. 实例化一个layout对象:new PatternLayout(格式);

3. 将layout对象绑定(attach)到appender对象:

appender->setLayout(layout);

    4. 实例化一个logger对象,调用静态函数:

log4cplus ::Logger ::getInstance("logger_name");        

    5. 将appender对象绑定(attach)到logger对象:

logger.addAppender(appender),如省略此步骤,标准输出(屏幕)appender

对象会绑定到logger;

    6. 设置logger的优先级: logger.setLogLevel(ALL_LOG_LEVEL),如

省略此步骤,各种有限级的消息都将被记录。

例如:

1、appender输出到屏幕:

LOG4CPLUS_DEBUG(logger,"This is the FIRST log message...");

sleep(1);    

LOG4CPLUS_WARN(logger,"This is the SECOND log message...");

2、iostream模式,appender输出到屏幕:

                  LOG4CPLUS_INFO(logger,"This is a char: " << 'x');

    LOG4CPLUS_ERROR(logger, "This is a long( hex ): " << std::hex <<

   100000000);

    LOG4CPLUS_FATAL(logger, "This is a double: " <<

   std::setprecision(15) << 1.2345234234);

    3、调试模式,通过loglog来控制输出调试、警告或错误信息,appender输出到屏幕:

    LogLog::getLogLog()->debug("This is a Debug statement...");

  LogLog::getLogLog()->warn("This is a Warning...");

  LogLog::getLogLog()->error("This is a Error...");

    LogLog::getLogLog()->setInternalDebugging(true);

    LogLog::getLogLog()->setQuietMode(true);

    LogLog类实现了debug, warn, error 函数用于输出调试、警告或错误信息,同时提供了两个方法来进一步控制所输出的信息,其中:setInternalDebugging方法用来控制是否屏蔽输出信息中的调试信息,当输入参数为false则屏蔽,缺省设置为false;setQuietMode方法用来控制是否屏蔽所有输出信息,当输入参数为true则屏蔽,缺省设置为false。

注:LogLog在实现时,写死了输出信息前缀:

LogLog::LogLog():mutex(LOG4CPLUS_MUTEX_CREATE),

                   debugEnabled(false),quietMode(false),

                    PREFIX( LOG4CPLUS_TEXT("log4cplus: ")),

                    WARN_PREFIX( LOG4CPLUS_TEXT("log4cplus:WARN ")), ERR_PREFIX( LOG4CPLUS_TEXT("log4cplus:ERROR "))

{

}

   4、文件模式,appender输出到文件:

   SharedAppenderPtr _append(new FileAppender("Test.log"));

  _append->setName("filelog");

   Logger _logger = Logger::getInstance("test.subtestof_filelog");

  _logger.addAppender(_append);

  LOG4CPLUS_DEBUG(_logger,"Entering text");

四、输出格式

    1、SimpleLayout是一种简单格式的布局器,在输出的原始信息之前加上LogLevel和一个"-"。

   std::auto_ptr _layout(new log4cplus::SimpleLayout());

   2、PatternLayout是一种有词法分析功能的模式布局器,一提起模式就会想起正则表达式,这里的模式和正则表达式类似,但是远比后者简单,能够对预定义的标识符进行解析,转换成特定格式输出。

   std::string pattern = "%d{%m/%d/%y %H:%M:%S} - %m [%l] %n";

  std::auto_ptr _layout(new PatternLayout(pattern));

注:

1、"pattern"可以包含普通字符串和预定义的标识符,其中:

(1)普通字符串,能够被直接显示的信息;

(2)预定义标识符,通过"%"与一个或多个字符共同构成预定义的标识符,

能够产生出特定格式信息。

2、各种消息格式:

   (1)"%%",转义为%;

   (2)"%c{n}",输出logger名称,也可以控制logger名称的显示层次其中数字表示层次。

   (3)"%D",显示本地时间,%d显示标准时间,可以通过%d{...}定义更详细的显示格式,比如%d{%H:%M:%s}表示要显示小时:分钟:秒。大括号中可显示的预定义标识符如下:

%a -- 表示礼拜几,英文缩写形式,比如"Fri"

%A -- 表示礼拜几,比如"Friday"

%b -- 表示几月份,英文缩写形式,比如"Oct"

%B -- 表示几月份,"October"

%c -- 标准的日期+时间格式,如 "Sat Oct 16 18:56:19 2004"

%d -- 表示今天是这个月的几号(1-31)"16"

%H -- 表示当前时刻是几时(0-23),如 "18"

%I -- 表示当前时刻是几时(1-12),如 "6"

%j -- 表示今天是哪一天(1-366),如 "290"

%m -- 表示本月是哪一月(1-12),如 "10"

%M -- 表示当前时刻是哪一分钟(0-59),如 "59"

%p -- 表示现在是上午还是下午, AM or PM

%q -- 表示当前时刻中毫秒部分(0-999),如 "237"

%Q -- 表示当前时刻中带小数的毫秒部分(0-999.999),如 "430.732"

%S -- 表示当前时刻的多少秒(0-59),如 "32"

%U -- 表示本周是今年的第几个礼拜,以周日为第一天开始计算(0-53)。

%w -- 表示礼拜几,(0-6, 礼拜天为0),如 "6"

%W -- 表示本周是今年的第几个礼拜,以周一为第一天开始计算(0-53)。

%x -- 标准的日期格式,如 "10/16/04"

%X -- 标准的时间格式,如 "19:02:34"

%y -- 两位数的年份(0-99),如 "04"

%Y -- 四位数的年份,如 "2004"

%Z -- 时区名,比如 "GMT"

    (4)"%F",输出当前记录器所在的文件名称;

(5)"%L",输出当前记录器所在的文件行号;

(6)"%l",输出当前记录器所在的文件名称和行号;

(7)"%m",输出原始信息,这种实现机制可以确保原始信息被嵌入到带格式的信息中。

(8)"%n",换行符;

(9)"%p",输出LogLevel;

(10)"%t",输出记录器所在的线程ID

(11)"%x",嵌套诊断上下文NDC输出,从堆栈中弹出上下文信息,NDC可以用对不同源的log信息(同时地)交叉输出进行区分。

(12)格式对齐:"%-10m"时表示左对齐,宽度是10。

   3、TTCCLayout是在PatternLayout基础上发展的一种缺省的带格式输出的布局器,其格式由时间,线程ID,Logger和NDC 组成,其在构造时选择显示本地时间(默认false)或GMT时间

五、文件操作类

log4cplus提供了FileAppender类、DailyRollingFileAppender类和RollingFileAppender类用于文件操作:

1、FileAppender类实现了基本的文件操作功能,构造函数如下:

FileAppender(const log4cplus::tstring& filename ,

            LOG4CPLUS_OPEN_MODE_TYPE mode =

            LOG4CPLUS_FSTREAM_NAMESPACE::ios::trunc,

            bool immediateFlush = true);

filename: 文件名;

mode: 文件类型,可选择的文件类型包括app、ate、binary、in、out、trunc,缺省是trunc,表示将先前文件删除。

    immediateFlush :缓冲刷新标志,如果为true表示每向文件写一条记录就刷新一次缓存,否则直到FileAppender被关闭或文件缓存已满才更新文件,默认true。

2、RollingFileAppender类可以根据预先设定的大小来决定是否转储,当超过该大小,后续log信息会另存到新文件中,除了定义每个记录文件的大小之外,还要确定在RollingFileAppender类对象构造时最多需要多少个这样的记录文件(maxBackupIndex+1),当存储的文件数目超过maxBackupIndex+1时,会删除最早生成的文件,保证整个文件数目等于maxBackupIndex+1,然后继续记录。

            构造函数如下:

log4cplus::RollingFileAppender::RollingFileAppender(

                const log4cplus::tstring& filename, long maxFileSize,

                int maxBackupIndex, bool immediateFlush);

filename : 文件名
maxFileSize : 文件的最大尺寸,尺寸小于200k时等于200k;

maxBackupIndex : 最大记录文件数

immediateFlush : 缓冲刷新标志

   SharedAppenderPtr _append(new RollingFileAppender("Test.log", size

                                * n, size));

3、DailyRollingFileAppender类可以根据你预先设定的频度来决定是否转储,当超过该频度,后续log信息会另存到新文件中,这里的频度包括:MONTHLY (每月)、WEEKLY(每周)、DAILY(每日)、TWICE_DAILY(每两天)、HOURLY(每时)、MINUTELY(每分)。构造函数如下:

DailyRollingFileAppender::DailyRollingFileAppender(

                                 const log4cplus::tstring& filename,

                                 DailyRollingFileSchedule schedule,

                                 bool immediateFlush,

                         int maxBackupIndex);

filename : 文件名

schedule : 存储频度

immediateFlush : 缓冲刷新标志

maxBackupIndex : 最大记录文件数

SharedAppenderPtr _append(new DailyRollingFileAppender("Test.log",

                                          MINUTELY, true, 5));

五、进阶

    通过LogLevelManager、LogLog、Filter三种方式,实现任意时刻输出的LogLevel的信息。

1、背景知识:

     log4cplus中logger的存储机制是通过一个层次化的结构(如:hash表)来组织的。

     获取Root级别的logger: Logger::getRoot();

     自定义的logger:Logger::getInstance("test");

定义其子logger: Logger::getInstance("test.subtest");

设置其LogLevel: Test.setLogLevel( ... );

     subTest.setLogLevel( ... );

     log4cplus将输出的log信息按照LogLevel(从低到高)分为:

     NOT_SET_LOG_LEVEL(-1) :接受缺省的LogLevel,如果有父logger则继承它的LogLevel;

     ALL_LOG_LEVEL(0) :开放所有log信息输出;

TRACE_LOG_LEVEL(0) :开放trace信息输出(即ALL_LOG_LEVEL);

DEBUG_LOG_LEVEL(10000) :开放debug信息输出;

INFO_LOG_LEVEL(20000) :开放info信息输出;

WARN_LOG_LEVEL(30000) :开放warning信息输出;

ERROR_LOG_LEVEL(40000) :开放error信息输出;

FATAL_LOG_LEVEL(50000) :开放fatal信息输出;

OFF_LOG_LEVEL(60000) :关闭所有log信息输出;

    2、LogLevelManager负责设置logger的优先级,各logger通过setLogLevel设置自己的优先级,当某个logger的LogLevel设置成NOT_SET_LOG_LEVEL时,该logger会继承父logger的优先级,另外,如果定义了重名的多个logger, 对其中任何一个的修改都会同时改变其它logger。

例1:

    SharedAppenderPtr _append(new ConsoleAppender());

  _append->setName("test");

   Logger root = Logger::getRoot();

  root.addAppender(_append);

    Logger test = Logger::getInstance("test");

  Logger subTest = Logger::getInstance("test.subtest");

  LogLevelManager& llm = getLogLevelManager();

    test.setLogLevel(INFO_LOG_LEVEL);

    LOG4CPLUS_FATAL(root,"root:"<<llm.toString(root.getChainedLogLevel()));

LOG4CPLUS_FATAL(root,"test:"<<llm.toString(test.getChainedLogLevel()));

LOG4CPLUS_FATAL(root,"test.subtest:"<<llm.toString(subTest.getChainedLogLevel()));

例2:通过设置LogLevel来控制用户的log信息输出:

      一下级别逐渐升高:

LOG4CPLUS_TRACE(Logger::getRoot(),"info")

LOG4CPLUS_DEBUG(Logger::getRoot(),"info")

LOG4CPLUS_INFO(Logger::getRoot(),"info")

LOG4CPLUS_WARN(Logger::getRoot(),"info")

LOG4CPLUS_ERROR(Logger::getRoot(),"info")

LOG4CPLUS_FATAL(Logger::getRoot(),"info")

Logger root = Logger::getRoot();

root.setLogLevel(ALL_LOG_LEVEL);   //全部显示

root.setLogLevel(TRACE_LOG_LEVEL); //全部显示

root.setLogLevel(ERROR_LOG_LEVEL); //只显示ERROR、FATAL

root.setLogLevel(OFF_LOG_LEVEL);   //显示log disabled

 

    3、自行定义LogLevel:

       定义NEW_LOG_LEVEL:

       //DEBUG_LOG_LEVEL  < NEW_LOG_LEVEL < INFO_LOG_LEVEL

       const LogLevel NEW_LOG_LEVEL = 15000;

       定义宏:

       #define LOG4CPLUS_NEW(logger, logEvent) \

if(logger.isEnabledFor(NEW_LOG_LEVEL)) { \

  log4cplus::tostringstream _log4cplus_buf; \

  _log4cplus_buf << logEvent; \

  logger.forcedLog(NEW_LOG_LEVEL, _log4cplus_buf.str(),   

      __FILE__, __LINE__);}

      在loglevel.cxx中加入#define _HELLO_STRING LOG4CPLUS_TEXT("HELLO") 然后修改log4cplus::tstring defaultLogLevelToStringMethod(LogLevel ll)函数,增加一个判断:case HELLO_LOG_LEVEL:return _HELLO_STRING;重新编译log4cplus源代码。

    4、基于脚本配置来过滤log信息:

     log4cplus通过PropertyConfigurator类实现基于脚本配置实现对logger、appender和layout的配置及log环境的配置(通过程序也可以)。从而过滤log信息及利用脚本配置来配合实现性能测试,

脚本语法规则:

1、Appender的配置语法:

(1)设置名称:

//设置方法

log4cplus.appender.appenderName=fully.qualified.name.of.appender.class

例如:

log4cplus.appender.append_1=log4cplus::ConsoleAppender

log4cplus.appender.append_2=log4cplus::FileAppender

log4cplus.appender.append_3=log4cplus::RollingFileAppender

log4cplus.appender.append_4=log4cplus::DailyRollingFileAppender

log4cplus.appender.append_4=log4cplus::SocketAppender

(2)设置Filter:

过滤器:LogLevelMatchFilter、LogLevelRangeFilter、StringMatchFilter。

 

        LogLevelMatchFilter:过滤条件包括LogLevelToMatch和

AcceptOnMatch(true|false), 只有当log信息的LogLevel值与

LogLevelToMatch相同,且AcceptOnMatch为true时才会匹配。

        LogLevelRangeFilter:过滤条件包括LogLevelMin、LogLevelMax和

AcceptOnMatch,只有当log信息的LogLevel在LogLevelMin、LogLevelMax之间同时AcceptOnMatch为true时才会匹配。

        StringMatchFilter:过滤条件包括StringToMatch和AcceptOnMatch,

只有当log信息的LogLevel值与StringToMatch对应的LogLevel值相同,

且AcceptOnMatch为true时会匹配。

        过滤条件处理机制:先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信息。

     (3)设置Layout:不设置(默认)、TTCCLayout、或PatternLayout

设置TTCCLayout:

    log4cplus.appender.ALL_MSGS.layout=log4cplus::TTCCLayout

设置PatternLayout:

log4cplus.appender.append_1.layout=log4cplus::PatternLayout

log4cplus.appender.append_1.layout.ConversionPattern=%d{%m/%d/%y %H:%M:%S,%Q} [%t] %-5p - %m%n               

2、logger的配置语法:rootLogger和non-root logger。

    rootLogger:

      log4cplus.rootLogger=[LogLevel], appenderName, appenderName, ...

non-root logger:

       log4cplus.logger.logger_name=[LogLevel|INHERITED], appenderName, appenderName, ...

  脚本方式使用:加载urconfig.properties自定义的配置文件。

        PropertyConfigurator::doConfigure("urconfig.properties");

例:

//定义

    log4cplus.rootLogger=TRACE, ALL_MSGS, TRACE_MSGS, DEBUG_INFO_MSGS, FATAL_MSGS

log4cplus.appender.FATAL_MSGS=log4cplus::RollingFileAppender

log4cplus.appender.FATAL_MSGS.File=fatal_msgs.log

log4cplus.appender.FATAL_MSGS.layout=log4cplus::TTCCLayout

log4cplus.appender.FATAL_MSGS.filters.1=log4cplus::spi::StringMatchFilter

log4cplus.appender.FATAL_MSGS.filters.1.StringToMatch=FATAL

log4cplus.appender.FATAL_MSGS.filters.1.AcceptOnMatch=true

log4cplus.appender.FATAL_MSGS.filters.2=log4cplus::spi::DenyAllFilter

//加载

  Logger root = Logger::getRoot();

  PropertyConfigurator::doConfigure("urconfig.properties");

六、嵌入诊断上下文

    NDC是线程特有的,利用了线程局部存储机制,称为线程私有数据(Thread-specificData,或TSD)。

     (1)默认格式输出NDC:

NDC& ndc = log4cplus::getNDC();

ndc.push("ur ndc string");

ndc.pop();

ndc.remove();

(2)自定义的输出格式中使用NDC(用%x):

std::string pattern = "NDC:[%x]  - %m %n";

std::auto_ptr<layout></layout> _layout(new PatternLayout(pattern));

NDC& ndc = log4cplus::getNDC();
ndc.push("ur ndc string");

ndc.pop();

ndc.remove();

(3)线程中直接用NDCContextCreator,不必显式地调用push/pop了,而且当出现异常时,能够确保push与pop的调用是匹配的。

NDCContextCreator _first_ndc("ur ndc string");

七、线程

log4cplus的线程没有考虑同步、死锁,有互斥,使用时派生类中直接重载run函数。如下:

class TestThread : public AbstractThread

{

public:

 virtual void run();

};                              

void TestThread::run()

{

}

八、套接字

定义在namespace log4cplus::helpers中,实现了C/S方式的日志记录。

1、 客户端程序需要做的工作:

    //定义一个SocketAppender类型的挂接器:

       SharedAppenderPtr _append(new SocketAppender(host, 8888, "ServerName"));

    //把_append加入到logger中:

       Logger::getRoot().addAppender(_append);

注:SocketAppender类型不需要Layout,直接调用宏将信息发往loggerServer。

对宏的调用其实是调用了SocketAppender::append,里面有一个数据传输约定,即先发送一个后续数据的总长度,然后再发送实际的数据。如下:

    SocketBuffer buffer = convertToBuffer(event, serverName);

    SocketBuffer msgBuffer(LOG4CPLUS_MAX_MESSAGE_SIZE);

    msgBuffer.appendSize_t(buffer.getSize());

    msgBuffer.appendBuffer(buffer);                 

2、服务器端程序需要做的工作:

     //定义一个ServerSocket

  ServerSocket serverSocket(port);

     //调用accept函数创建一个新的socket与客户端连接

       Socket sock = serverSocket.accept();

     //进行数据read/write

SocketBuffer msgSizeBuffer(sizeof(unsigned int));

if(!clientsock.read(msgSizeBuffer))

{

    return;

}

unsigned int msgSize = msgSizeBuffer.readInt();

SocketBuffer buffer(msgSize);

if(!clientsock.read(buffer))

{

    return;

}

注:为了将读到的数据正常显示出来,需要将SocketBuffer存放的内容转换成InternalLoggingEvent格式:spi::InternalLoggingEvent event = readFromBuffer(buffer);然后输出:Logger logger = Logger::getInstance(event.getLoggerName());logger.callAppenders(event);     read/write是按照阻塞方式实现的,对其调用直到满足了所接收或发送的个数才返回。


posted on 2011-04-02 15:25 C++技术中心 阅读(7572) 评论(0)  编辑 收藏 引用 所属分类: 三方库

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理