资料:便利的开发工具-log4cpp快速使用指南

Fish@Babylon5

Fish@Babylon5

BLoGGer

首页 联络 聚合 登录 CNDEV 网志

公告

严肃点,不许笑!!! 随笔

编程 (rss) 其他 (rss) 生活 (rss) 围棋 (rss) 影视 (rss) 运动 (rss)

随笔归档

2009-04 (4) 2009-03 (8) 2009-02 (1) 2008-12 (5) 2008-10 (2) 2008-09 (3) 2008-08 (5) 2008-07 (5) 2008-06 (7) 2008-05 (9) 2008-04 (8) 2008-03 (4) 2008-02 (2) 2008-01 (5) 2007-12 (8) 2007-11 (10) 2007-10 (6) 2007-09 (6) 2007-08 (4) 2007-07 (4) 2007-06 (3) 2007-04 (3) 2007-03 (6) 2007-02 (1) 2007-01 (4) 2006-12 (4) 2006-11 (9) 2006-10 (4) 2006-09 (1) 2006-08 (2) 2006-07 (5) 2006-06 (6) 2006-05 (8) 2006-04 (7) 2006-03 (5) 2006-02 (4) 2006-01 (7) 2005-12 (5) 2005-11 (4) 2005-10 (1) 2005-09 (9) 2005-08 (6) 2005-07 (14) 2005-06 (22) 2005-05 (6) 2005-04 (6) 2005-03 (10) 2005-02 (9) 2005-01 (7) 2004-12 (10) 2004-11 (5) 2004-10 (10) 2004-09 (1) 2004-08 (5) 2004-07 (4) 2004-06 (12) 2004-05 (3)

收藏

开发 其它 情感 生活 围棋

图库

编程 电影 朋友 其他 生活 同学

CNDEV

bjwf leejd Miracle 韩磊 花花 火炬 老猪 没脾气

PM

UMLChina 企业资源管理研究中心 软件工程专家网 软件过程研究解决方案 系统分析员之窗 项目管理者联盟

编程

资料:便利的开发工具-log4cpp快速使用指南
BEA社区 CSDN MSDN中文版 中国开发网 中国开发网(Down)

电影

电影票房 狗坛 水鱼会老论坛 水鱼会论坛 水鱼会主页

其他

Babylon5 信华花园

围棋

飞扬围棋 老鱼侃围棋@活力 老鱼侃围棋@网易 棋人论坛 棋圣道场

BLoG.Stats

随笔 - 334 收藏 - 18 评论 - 0 寻迹 - 0

资料:便利的开发工具-log4cpp快速使用指南

这个东东有点用处,比俺自己写的日志功能代码考虑的更全面,先存在这里,等有空的时候看能否改成Delphi的

---------------------------------------------------------------------------------------------------------------------------------

便利的开发工具-log4cpp快速使用指南

内容:

优点

原理

手动使用步骤

配置文件驱动方式使用步骤

相关考虑

参考资料

关于作者

在 Linux 专区还有:

教程

工具与产品

代码与组件

文章

李群 (liqun@nsfocus.com)

绿盟科技

2003 年 9 月

log4cpp是个基于LGPL的开源项目,是基于优秀的日志处理跟踪项目Java语言的log4j移植过来的。log4j介绍的文档很多,在java领域使用的也比较广泛,而这个功能强大的库对国内的C++语言开发人员却使用的不多。这里从开发人员使用的角度介绍这个库,使开发人员用最少的代价尽快掌握这种技术。下面先简单介绍一下这个项目的优点(也是log4j的优点),然后分原理,手动使用步骤,配置文件驱动方式使用步骤,其他考虑等方面进行讨论。以下讨论基于log4cpp0.3.4b。

0. 优点

提供应用程序运行上下文,方便跟踪调试;

可扩展的、多种方式记录日志,包括命令行、文件、回卷文件、内存、syslog服务器、Win事件日志等;

可以动态控制日志记录级别,在效率和功能中进行调整;

所有配置可以通过配置文件进行动态调整;

多语言支持,包括Java(log4j),C++(log4cpp、log4cplus),C(log4c),python(log4p)等;

...

1. 原理

log4cpp有3个主要的组件:categories(类别)、appenders(附加目的地)、和 layouts(布局)。(为了方便大家理解,文中尽量使用英文原词)

layout类控制输出日志消息的显示样式(看起来像什么)。log4cpp当前提供以下layout格式:

log4cpp::BasicLayout // 以“时间戳 优先级(priority,下文介绍)

// 类别(category,下文介绍)

// NDC标签(nested diagnostic contexts 下文介绍): 日志信息”。

// 如:1056638652 INFO main : This is some info

log4cpp::PatternLayout // 让用户根据类似于 C 语言 printf 函数的转换模式来指定输出格式。格式定义见代码附带文档。

log4cpp::SimpleLayout // 以“优先级(priority) - 日志信息”格式显示。

appender类用来输出日志(被layout格式化后的)到一些设备上。比如文件、syslog服务、某个socket等。可以定义自己的appender类输出日志信息到别的设备上,比如应用自身的日子处理进程、数据库等。appender和layout的关系是layout附在appender上,appender类调用layout处理完日志消息后,记录到某个设备上。log4cpp当前提供以下appender:

log4cpp::IdsaAppender // 发送到IDS或者logger, 详细见 http://jade.cs.uct.ac.za/idsa/

log4cpp::FileAppender // 输出到文件

log4cpp::RollingFileAppender // 输出到回卷文件,即当文件到达某个大小后回卷

log4cpp::OstreamAppender // 输出到一个ostream类

log4cpp::RemoteSyslogAppender // 输出到远程syslog服务器

log4cpp::StringQueueAppender // 内存队列

log4cpp::SyslogAppender // 本地syslog

log4cpp::Win32DebugAppender // 发送到缺省系统调试器

log4cpp::NTEventLogAppender // 发送到win 事件日志

category 类真正完成记录日志功能,两个主要组成部分是appenders和priority(优先级)。优先级控制哪类日志信息可以被这个category记录,当前优先级分为:NOTSET, DEBUG, INFO, NOTICE, WARN, ERROR, CRIT, ALERT 或 FATAL/EMERG 。每个日志信息有个优先级,每个category有个优先级,当消息的优先级大于等于category的优先级时,这个消息才会被category记录,否则被忽略。优先级的关系如下。category类和appender的关系是,多个appender附在category上,这样一个日志消息可以同时输出到多个设备上。

NOTSET < DEBUG < INFO < NOTICE < WARN < ERROR < CRIT < ALERT < FATAL = EMERG

category被组织成一个树,子category创建时优先级缺省NOTSET,category缺省会继承父category的appender。而如果不希望这种appender的继承关系,log4cpp允许使用additivity 标签,为false时新的appender取代category的appender列表。

为了更好的理解上面的概念下面以手动使用方式举例。

2. 手动使用步骤

手动使用log4cpp的基本步骤如下:

实例化一个layout 对象;

初始化一个appender 对象;

把layout对象附着在appender对象上;

调用log4cpp::Category::getInstance("name"). 实例化一个category对象;

把appender对象附到category上(根据additivity的值取代其他appender或者附加在其他appender后)。

设置category的优先级;

// FileName: test_log4cpp1.cpp

// Test log4cpp by manual operation.

// Announce: use as your own risk.

// Compile : g++ -otest1 -llog4cpp test_log4cpp1.cpp

// Run : ./test1

// Tested : RedHat 7.2 log4cpp0.3.4b

// Author : liqun (liqun@nsfocus.com)

// Data : 2003-6-27

#include "log4cpp/Category.hh"

#include "log4cpp/FileAppender.hh"

#include "log4cpp/BasicLayout.hh"

int main(int argc, char* argv[])

{

// 1实例化一个layout 对象

log4cpp::Layout* layout =

new log4cpp::BasicLayout();

// 2. 初始化一个appender 对象

log4cpp::Appender* appender = new

log4cpp::FileAppender("FileAppender",

"./test_log4cpp1.log");

// 3. 把layout对象附着在appender对象上

appender->setLayout(layout);

// 4. 实例化一个category对象

log4cpp::Category& warn_log =

log4cpp::Category::getInstance("mywarn");

// 5. 设置additivity为false,替换已有的appender

warn_log.setAdditivity(false);

// 5. 把appender对象附到category上

warn_log.setAppender(appender);

// 6. 设置category的优先级,低于此优先级的日志不被记录

warn_log.setPriority(log4cpp::Priority::WARN);

// 记录一些日志

warn_log.info("Program info which cannot be wirten");

warn_log.debug("This debug message will fail to write");

warn_log.alert("Alert info");

// 其他记录日志方式

warn_log.log(log4cpp::Priority::WARN, "This will be a logged warning");

log4cpp::Priority::PriorityLevel priority;

bool this_is_critical = true;

if(this_is_critical)

priority = log4cpp::Priority::CRIT;

else

priority = log4cpp::Priority::DEBUG;

warn_log.log(priority,"Importance depends on context");

warn_log.critStream() << "This will show up << as "

<< 1 << " critical message"

<< log4cpp::CategoryStream::ENDLINE;

// clean up and flush all appenders

log4cpp::Category::shutdown();

return 0;

}

3. 配置文件驱动方式使用步骤

另一个非常优秀的特征就是通过读取配置文件,确定category、appender、layout等对象。也是我们非常推荐的使用方式,可以灵活地通过配置文件定义所有地对象及其属性,不用重新编码,动态更改日志记录的策略。

Log4cpp主要提供了 log4cpp::PropertyConfigurator 和log4cpp::SimpleConfigurator两种机制(文件格式),但 log4cpp::SimpleConfigurator将来不再支持了,而且格式非常简单,这里就不多说明,自己看源码吧。

配置文件的格式和log4j的配置文件一样,是标准的java属性文件格式。下面是附带的例子配置文件:

# a simple test config

#定义了3个category sub1, sub2, sub1.sub2

log4j.rootCategory=DEBUG, rootAppender

log4j.category.sub1=,A1

log4j.category.sub2=INFO

log4j.category.sub1.sub2=ERROR, A2

# 设置sub1.sub2 的additivity属性

log4j.additivity.sub1.sub2=false

#定义rootAppender类型和layout属性

log4j.appender.rootAppender=org.apache.log4j.ConsoleAppender

log4j.appender.rootAppender.layout=org.apache.log4j.BasicLayout

#定义A1的属性

log4j.appender.A1=org.apache.log4j.FileAppender

log4j.appender.A1.fileName=A1.log

log4j.appender.A1.layout=org.apache.log4j.SimpleLayout

#定义A2的属性

log4j.appender.A2=org.apache.log4j.ConsoleAppender

log4j.appender.A2.layout=org.apache.log4j.PatternLayout

log4j.appender.A2.layout.ConversionPattern=The message '%m' at time %d%n

配置文件语法如下,不是很规范,结合上面的例子,应该可以看懂。

log4j / log4cpp . [category / appender].[category or appender 's name].[category or appender 's property]

= [Appender / Layout / property's value / Priority, appender name1 [appender name2 ...]]

[appender]

{ConsoleAppender}

{FileAppender} // 当appender的类型是FileAppender时,可以定义它下面的属性。

[fileName] string foobar // 格式是:属性名 值的类型 缺省值

[append] bool true

{RollingFileAppender}

[fileName] string foobar

[maxFileSize] num 10*1024*1024

[maxBackupIndex] num 1

[append] bool true

{SyslogAppender}

[syslogName] string syslog

[syslogHost] string localhost

[facility] num -1 // * 8 to get LOG_KERN, etc. compatible values.

[portNumber] num -1

{IdsaAppender}

[idsaName] string foobar

{Win32DebugAppender}

{NTEventLogAppender}

[source] string foobar

[threshold] string "" // 全部

// 如果此类型appender需要layout,必须定义此appender的下面属性

[layout]

{BasicLayout}

{SimpleLayout}

{PatternLayout} // 当layout的值是BasicLayout时,需要定义下面的属性。

[ConversionPattern]

[rootCategory]

[additivity]

[category name] bool true

基本使用步骤是:

读取解析配置文件;

实例化category对象;

正常使用这些category对象进行日志处理;

下面是个简单的使用代码,使用起来是非常方便的:

// FileName: test_log4cpp2.cpp

// Test log4cpp by config file.

// Announce: use as your own risk.

// Compile : g++ -llog4cpp test_log4cpp2.cpp

// Run : ./a.out

// Tested : RedHat 7.2 log4cpp0.3.4b

// Author : liqun (liqun@nsfocus.com)

// Data : 2003-6-27

#include "log4cpp/Category.hh"

#include "log4cpp/PropertyConfigurator.hh"

int main(int argc, char* argv[])

{

// 1 读取解析配置文件

// 读取出错, 完全可以忽略,可以定义一个缺省策略或者使用系统缺省策略

// BasicLayout输出所有优先级日志到ConsoleAppender

try {

log4cpp::PropertyConfigurator::configure("./log4cpp.conf");

} catch(log4cpp::ConfigureFailure& f) {

std::cout << "Configure Problem " << f.what() << std::endl;

return -1;

}

// 2 实例化category对象

// 这些对象即使配置文件没有定义也可以使用,不过其属性继承其父category

// 通常使用引用可能不太方便,可以使用指针,以后做指针使用

// log4cpp::Category* root = &log4cpp::Category::getRoot();

log4cpp::Category& root = log4cpp::Category::getRoot();

log4cpp::Category& sub1 =

log4cpp::Category::getInstance(std::string("sub1"));

log4cpp::Category& sub3 =

log4cpp::Category::getInstance(std::string("sub1.sub2"));

// 3 正常使用这些category对象进行日志处理。

// sub1 has appender A1 and rootappender.

sub1.info("This is some info");

sub1.alert("A warning");

// sub3 only have A2 appender.

sub3.debug("This debug message will fail to write");

sub3.alert("All hands abandon ship");

sub3.critStream() << "This will show up << as " << 1 << " critical message"

<< log4cpp::CategoryStream::ENDLINE;

sub3 << log4cpp::Priority::ERROR

<< "And this will be an error"

<< log4cpp::CategoryStream::ENDLINE;

sub3.log(log4cpp::Priority::WARN, "This will be a logged warning");

return 0;

}

4. 相关考虑

性能问题,可能是很多想使用log4cpp的程序员关心的问题。在参考资料2中有一段描述。结论就是log4j以及log4cpp是以性能为首要目标的;如果关闭日志记录的话,对性能影响可以忽略;打开日志记录,主要消耗是在记录动作,而不是库的管理过程;所以你尽可放心的使用。实在要深究性能的话。可以从下面方面提高:

输出的日志消息不要使用复杂的转换或者处理,比如: sub1.debug(string("Current num is") + i + GetCurStat()); 这种情况即使不进行日志处理,括号中的语句还是会执行。变通方法是:

if(sub1.isDebugEnabled())

{

sub1.debug(string("Current num is") + i + GetCurStat());

}

安全性问题对于商业软件开发可能也是问题。可能不希望别人通过修改配置文件获取程序的调试等程序内部运行情况的日志信息。比较稳妥的方案或者是加密配置文件,运行中解密,输出到临时文件后读取;或者在发行版本里读取配置文件后,强行把低于某个优先级的category设到比较高的优先级。

多线程安全性问题。当前log4cpp还没有宣称自己是多线程安全的,不过其代码中大多数可能冲突的地方都增加了线程互斥控制,对多线程环境应该问题不大。但为了加入这个特性,linux下编译log4cpp时,configure请加入--with-pthreads 或者--with-omnithreads选项。Win版本已经加入对MS线程的支持。

5. 参考资料

1. Logging and Tracing in C++ Simplified: Traveling the Road Last Traveled by a Previously Invented Wheel

http://soldc.sun.com/articles/logging.html

2. log4j 提供了对日志记录的控制

http://www-900.ibm.com/developerWorks/cn/java/jw-log4j/index.shtml

3. 使用Log4j进行日志操作

http://www-900.ibm.com/developerWorks/cn/java/l-log4j/index.shtml

4. log4cpp主页

http://sourceforge.net/projects/log4cpp/

5. log4j主页

http://jakarta.apache.org/log4j/docs/index.html

6. log4cplus主页

http://log4cplus.sourceforge.net/

7. log4c主页

http://log4c.sourceforge.net/

6. 关于作者

李群,关注于网络安全产品的开发、研究;软件开发过程等方面。您可以通过liqun@nsfocus.com和他联系。

发表于 2004-12-18 10:31

评论

#回复: 资料:便利的开发工具-log4cpp快速使用指南 2004-12-18 21:34:00 leejd



#回复: 资料:便利的开发工具-log4cpp快速使用指南 2004-12-30 22:38:00 haitao

感觉太庞大,还是给自己的log函数增加一个级别参数算了

extern int commlogInit(const char* exefilename);

extern void commlogSetLevelFlag(const int loglevel);

extern int commlogStr(const int level,const char* str,const char withdate=-1);

extern int commlogStr2(const int level,const char* str,const char* str2,const char withdate=-1);

extern int commlogStrs(const int level,const char withdate=-1,...);

extern int commlogInt(const int level,const char* str,const int d,const char withdate=-1);

extern int commlogBuffer(const int level,const char* str,const char* buf,const int len,const char withdate=-1);

#define commlogSrc(loglevel) commlogInt(loglevel,(string("SRC:")+__FILE__+":").c_str(),__LINE__)

/*

0冗余信息

1调试信息

2运行信息 包括:commlogInit、程序启动、关闭的日志

3变化信息

4警告信息

5错误信息

6异常信息

7失败信息

*/

#define loglevel0 1

#define loglevel1 2

#define loglevel2 4

#define loglevel3 8

#define loglevel4 0x10

#define loglevel5 0x20

#define loglevel6 0x40

#define loglevel7 0x80

*/

输出结果:

2004-12-29 10:40:50.096|4|

----<<< AppStart[@win32]...

10:40:50.126|4|SRC:e:srcmain.cpp:44

10:40:50.136|4|ListenPort=8000

10:40:50.146|1|setReadTimeout Ret=0

10:40:50.156|1|h=1744

10:40:50.156|4|SetCOMM:0

10:40:50.196|4|PosTest[

10:40:50.196|4|SRC:e:srcmain.cpp:122

10:40:52.099|4|[win32]Ctrl-C

10:40:52.099|4|SRC:e:srcmain.cpp:263

10:40:52.099|4|>>>21---

10:40:52.099|4|>>>22---

10:40:52.109|4|SRC:e:srcmain.cpp:247

10:40:52.119|4|AppStoped.[@win32]

>>>----



发表评论

标题: 请输入“标题”

署名: 请输入“署名”

链接:

记住我的信息以方便下次评论?

内容:

验证码:

CNDEV.ORG 博客服务商提供服务,内容由博客内容发布者负责。博客内容与托管商无关

Copyright © Fish

  

爱华网本文地址 » http://www.413yy.cn/a/25101012/144048.html

更多阅读

U盾快速使用指南 itunes快速指南无响应

U盾快速使用指南一、PC平台兼容性1.1支持操作系统:Windows2000及以上各版本32位和64位Windows系统、Mac10.9及以上Mac系统。注:Mac系统暂不支持企业用户1.2 支持浏览器:IE6.0以上版本及各种以IE为内核的浏览器,safari、火狐(Firefo

iOS开发:用xcode5开发第一个helloworld程序 精 火线精英

iOS开发:用xcode5开发第一个helloworld程序 精——简介任何程序开发的学习都是从helloworld开始的,那么如何建立ios开发的第一个helloworld程序,网上也有很多教程,但是很多是老版本的xcode来写的教程,随着ios7的普及,xcode也升级到了新的

菜鸟笔记之PHP PHP开发工具 php可视化开发工具

关于PHP的开发工具其实网站上可以搜索到非常多,对于初学者来说,太多的选择反而不知道怎么去选。本文是基于window平台上,针对PHP初学者定制了一套非常好用的开发工具。PHP开发工具其实包括以下两个:PHP服务器

自制UDK虚幻引擎开发工具入门教程 udk和虚幻4区别

转载请注明出处:DiorZhang_http://blog.sina.com.cn/ts152154539照着做了做,基本算翻译了,自制肯定是吹牛^^加了一些修正。有看法欢迎指出^^introduction介绍看完此教程您将学会:如何为您的游戏设立文件夹设立和编译unreal script使用虚

声明:《资料:便利的开发工具-log4cpp快速使用指南》为网友亱雨分享!如侵犯到您的合法权益请联系我们删除