Skip to content

Latest commit

 

History

History
169 lines (135 loc) · 6.37 KB

11.2_log4cpp.md

File metadata and controls

169 lines (135 loc) · 6.37 KB

11.2 log4cpp

  在上文,我们使用重定向去输入日志到日志文件中,但是这样一种处理方式,还是有很多不足,比如没有办法输出到多个文件,没有办法设置日志文件大小,不太方便设置日志的级别,如果想远程输出到日志服务器怎么办呢?等等这些问题怎么解决呢?
  log4cpp就提供了很多的功能,帮助我们应用程序更方便地记录日志,OK,我们先来看一个简单的实现吧:

wget https://nchc.dl.sourceforge.net/project/log4cpp/log4cpp-1.1.x%20%28new%29/log4cpp-1.1/log4cpp-1.1.3.tar.gz
tar xzvf log4cpp-1.1.3.tar.gz
cd log4cpp-1.1.3
./configure
make
make install
  • step 2 : 包含头文件
#include <log4cpp/Category.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/OstreamAppender.hh>

  • step 3 : 初始化日志输出的目的地(appenders)
// 输出到std::cout
log4cpp::Appender *appender = new log4cpp::OstreamAppender("root", &std::cout);
// 输出到log文件
//log4cpp::Appender *appender = new log4cpp::FileAppender("root", "test.log");

appender有以下这些:

log4cpp::IdsaAppender // 发送到IDS或者
log4cpp::FileAppender // 输出到文件
log4cpp::RollingFileAppender // 输出到回卷文件,即当文件到达某个大小后回卷
log4cpp::OstreamAppender // 输出到一个ostream类
log4cpp::RemoteSyslogAppender // 输出到远程syslog服务器
log4cpp::StringQueueAppender // 内存队列
log4cpp::SyslogAppender // 本地syslog
log4cpp::Win32DebugAppender // 发送到缺省系统调试器
log4cpp::NTEventLogAppender // 发送到win 事件日志

  上文,我们说过日志输出到终端或者文件中实际上是很慢的,会引起IO中断,所以我们可以输出到内存里StringQueueAppender,然后从StringQueueAppender输出到其它地方,这样我们的线程执行是比较高效的。

  • step 4 : 设置日志输出的格式
log4cpp::PatternLayout *patternLayout = new log4cpp::PatternLayout();
patternLayout->setConversionPattern("%d [%p] - %m%n");
appender->setLayout(patternLayout);

日志输出格式控制有: PatternLayout supports following set of format characters:
%% - a single percent sign
%c - the category
%d - the date\n Date format: The date format character may be followed by a date format specifier enclosed between braces. For example, %d{%\H:%M:%S,%l} or %d{%\d %m %Y %H:%\M:%S,%l}. If no date format specifier is given then the following format is used: "Wed Jan 02 02:03:55 1980". The date format specifier admits the same syntax as the ANSI C function strftime, with 1 addition. The addition is the specifier %l for milliseconds, padded with zeros to make 3 digits.
%m - the message
%n - the platform specific line separator
%p - the priority
%r - milliseconds since this layout was created.
%R - seconds since Jan 1, 1970
%u - clock ticks since process start
%x - the NDC
%t - thread name
By default, ConversionPattern for PatternLayout is set to "%m%n".

  • step 4 : 设置类别输出的(category)和日志优先级(priority)
log4cpp::Category &root = log4cpp::Category::getRoot();
root.setPriority(log4cpp::Priority::NOTICE);
root.addAppender(appender);

日志的级别总共有:NOTSET < DEBUG < INFO < NOTICE < WARN < ERROR < CRIT < ALERT < FATAL = EMERG。日志级别的意思是低于该级别的日志不会被记录。

  • step 5 : 定义一个宏
#define LOG(__level) log4cpp::Category::getRoot() << log4cpp::Priority::__level << __FILE__ << " " << __LINE__ << ": "

当然也可以使用Category定义的函数:

       /**
         * Log a message with the specified priority.
         * @param priority The priority of this log message.
         * @param stringFormat Format specifier for the string to write
         * in the log file.
         * @param ... The arguments for stringFormat
         **/
        virtual void log(Priority::Value priority, const char* stringFormat,
                         ...) throw();

        /**
         * Log a message with the specified priority.
         * @param priority The priority of this log message.
         * @param message string to write in the log file
         **/
        virtual void log(Priority::Value priority,
                         const std::string& message) throw();

       void debug(const char* stringFormat, ...) throw();
	   void debug(const std::string& message) throw();
	   void info(const char* stringFormat, ...) throw();
	   ...
  • step 6 : 使用宏定义记录日志
    LOG(DEBUG) << "i am happy.";
    LOG(INFO)  << "oh, you happy, we happy.";
    LOG(NOTICE)<< "please do not contact me. ";
    LOG(WARN)  << "i am very busy now.";
    LOG(ERROR) << "oh, what happed?";

当然我们在使用过程中,可以封装一个单例,oh,单例是什么?别急,我们课堂上会讲。

当然在实际工程上应用,我们是使用日志配置文件去控制日志记录的。那么我们来看一个日志配置吧:

#定义Root category的属性
log4cpp.rootCategory=DEBUG, RootLog

#定义RootLog属性
log4cpp.appender.RootLog=RollingFileAppender
log4cpp.appender.RootLog.layout=PatternLayout
<<<<<<< HEAD
log4cpp.appender.RootLog.layout.ConversionPattern=%d{% m-%d %H:%M:%S %l} [%t][%p]%m%n
=======
log4cpp.appender.RootLog.layout.ConversionPattern=%d{\%\m-%d %H:%M:%S %l} [%t][%p]%m%n
>>>>>>> ac666e2a90e167f86b8b827e78f650b852e03ad0
log4cpp.appender.RootLog.fileName=/var/log/brk.log
log4cpp.appender.RootLog.maxFileSize=268435456 #256MB
log4cpp.appender.RootLog.fileNamePattern=brk_%i.log
log4cpp.appender.RootLog.maxBackupIndex=256

那如何使用配置文件定义log呢?

BOOL Logger::init(const std::string & log_conf_file)
{
    try
    {
        log4cpp::PropertyConfigurator::configure(log_conf_file);
    }
    catch(log4cpp::ConfigureFailure& f)
    {
        std::cerr << " load log config file " << log_conf_file.c_str() << " failed with result : " << f.what()<< std::endl;
        return FALSE;
    }

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

    return TRUE;
}