网站推广软件哪个最好,wordpress售后退货插件,图片在线高清处理,flash网站标题和网址0. 优点 提供应用程序运行上下文#xff0c;方便跟踪调试#xff1b; 可扩展的、多种方式记录日志#xff0c;包括命令行、文件、回卷文件、内存、syslog服务器、Win事件日志等#xff1b; 可以动态控制日志记录级别#xff0c;在效率和功能中进行调整#xff1b; 所有配… 0. 优点 提供应用程序运行上下文方便跟踪调试 可扩展的、多种方式记录日志包括命令行、文件、回卷文件、内存、syslog服务器、Win事件日志等 可以动态控制日志记录级别在效率和功能中进行调整 所有配置可以通过配置文件进行动态调整 多语言支持包括Javalog4jClog4cpp、log4cplusClog4cpythonlog4p等 回页首 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创建时优先级缺省NOTSETcategory缺省会继承父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 (liqunnsfocus.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替换已有的appenderwarn_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;elsepriority 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 appenderslog4cpp::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.rootCategoryDEBUG, rootAppender
log4j.category.sub1,A1
log4j.category.sub2INFO
log4j.category.sub1.sub2ERROR, A2
# 设置sub1.sub2 的additivity属性
log4j.additivity.sub1.sub2false
#定义rootAppender类型和layout属性
log4j.appender.rootAppenderorg.apache.log4j.ConsoleAppender
log4j.appender.rootAppender.layoutorg.apache.log4j.BasicLayout
#定义A1的属性
log4j.appender.A1org.apache.log4j.FileAppender
log4j.appender.A1.fileNameA1.log
log4j.appender.A1.layoutorg.apache.log4j.SimpleLayout
#定义A2的属性
log4j.appender.A2org.apache.log4j.ConsoleAppender
log4j.appender.A2.layoutorg.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPatternThe message %m at time %d%n 配置文件语法如下不是很规范结合上面的例子应该可以看懂。 log4j / log4cpp . [category / appender].[category or appender s name].[category or appender s property] [Appender / Layout / propertys 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 (liqunnsfocus.com)
// Data : 2003-6-27
#include log4cpp/Category.hh
#include log4cpp/PropertyConfigurator.hh
int main(int argc, char* argv[])
{// 1 读取解析配置文件// 读取出错, 完全可以忽略可以定义一个缺省策略或者使用系统缺省策略// BasicLayout输出所有优先级日志到ConsoleAppendertry { 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线程的支持。