log4cpp源码下载点击此处下载
调用对应宏定义实现日志记录功能

流程

创建一个Appender,并指定其包含的Layout

从系统中得到Category的根,将Appender添加到该Category中;

设置Category的优先级

记录日志

关闭Category

使用原则

不要手动释放Category、Appender和Layout

同一个Appender不要加入多个Category,否则它会被释放多次从而导致程序崩溃

同一个Layout不要附着到多个Appender上,否则也会被释放多次导致程序崩溃

Layout

每个Appender都设置了一个Layout,用于定义这个Appender日志的格式

设置日志的格式

log4cpp中所有的Layout子类,一共有三个:BasicLayout、PatternLayout和SimpleLayout,其中SimpleLayout并不建议使用,而BasicLayout过于简单,因此如果程序员不自己扩展Layout的话,就只能 使用PatternLayout

SimpleLayout

BasicLayout

BasicLayout是log4cpp内置的一种格式

使用实例

使用setLayout()来设置BasicLayout,BasicLayout()是无参函数

输出

PatternLayout

可以自己设定格式

使用setConversionPattern函数来设置日志的输出格式

函数声明

void log4cpp::PatternLayout::setConversionPattern
(const std::string &conversionPattern) throw (ConfigureFailure) [virtual]

函数使用方法

类似C语言中的printf,使用格式化字符串来描述输出格式

  • 格式化字符串具体含义

    %c

    category名

    %d

    日期

    日期可以进一步的设置格式,用花括号包围

    例如

    %d{ &H: %M: %S, %l}

    %d{%d %m %Y %H:%M:%S,%l}

    若不设置具体日期格式,则默认格式为

    “Wed Jan 02 02:03:55 1980”

    %m  //消息
    %n   //换行符
    %p   //优先级名
    %r  //从layout被创建后的毫秒数
    %R  //从1970年1月1日0时开始到目前为止的和秒数
    %u  //进程开始到目前为止的秒数
    %x  //NDC
    

可以将setConversionPattern的参数设置为"%d: %p %c %x: %m%n"

具体含义

“时间: 优先级 Category NDC: 消息 换行”

使用实例

log4cpp::PatternLayout* pLayout = new log4cpp::PatternLayout();
pLayout->serConversionPattern("%d: %p %c %s: %m%n");
osAppender->setLayout(pLayout);//一个appender对应一个Layout

日志对应内容

Appender

负责指向日志的目的地

  • 按日志的目的地分类

    log4cpp::OstreamAppender

    构造函数原型

    OstreamAppender(const string &name, ostream *stream)
    

    参数列表

    name

    指定OstreamAppender的名称

    stream

    指定它关联的流的指针

    添加Appender

    使用实例

    //首先创建一个Appender
    log4cpp::OstreamAppender& osAppender = new log4cpp::OstreamAppender("osAppender", &cout);log4cpp::PatternLayout* pLayout = new log4cpp::PatternLayout();
    pLayout->setConversionPattern("%d: %p %c : %m%n");
    osAppender->setLayout(pLayout);log4cpp::Category& root = log4cpp::Category::getRoot();log4cpp::Category& infoCategory = root.getInstance("infoCategory");
    //调用addAppender方法添加一个Appender
    infoCategory.addAppender(osAppender);
    infoCategory.setPriority(log4cpp::Priority::INFO);
    //只有优先级高于INFO的元素才能输出
    

    先使用构造函数声明,再添加appender到category中

    OstreamAppender用setLayout()函数设置输出格式

    log4cpp::FileAppender

    构造函数原型

    //使用文件名写入
    FileAppender(const std::string &name, const std::string &fileName,
    bool append=true, mode_t mode=00644);
    //使用文件描述符写入
    FileAppender(const std::string &name, int fd);
    

    一般仅使用前两个参数,即“名称”和“日志文件名”,第三个参数指示是否在日志文件后继续记入日志,还是清空原日志文件再记录,第四个参数说明文件的打开方式

    log4cpp::RollingFileAppender

    构造函数原型

    RollingFileAppender (const std::string &name,
    const std::string &fileName, size_t maxFileSize=10 *1024 *1024,
    unsigned int maxBackupIndex=1, bool append=true, mode_t mode=00644);
    

    它与FileAppender的创建函数很类似,但是多了两个参数:maxFileSize指出了回卷文件的最大值(单位为byte);maxBackupIndex指出了回卷文件所用的备份文件的最大个数

    备份文件

    用来保存回滚文件中因为空间不足未能记录的日志,备份文件的大小仅比回卷文件的最大值大1kb

    只有一个备份文件装满了,才会创建一个新的备份文件

    如果maxBackupIndex取值为3,则回卷文件会有三个备份文件,其名称分别是rollwxb.log.1,rollwxb.log.2和roolwxb.log.3,大小为101kb。

    如果maxBackupIndex取值为0或者小于0,则回卷文件功能会失效,其表现如同FileAppender一样,不会有大小的限制,这也许是一个bug

    FileAppender和RollingFileAppender之间的关系与区别

    FileAppender和RollingFileAppender是log4cpp中最常用的两个 Appender,其功能是将日志写入文件中。它们之间唯一的区别就是前者会移至在文件中记录日志(直到操作系统承受不了的位置),而后者会在文件长度到达指定值时循环记录日志,文件长度不会超过指定值(默认的指定值是10M byte)

  • 所有可以直接使用的Appender列表

    log4cpp::IdsaAppender

    发送到IDS

    log4cpp::FileAppender

    输出到文件

    log4cpp::RollingFileAppender

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

    回卷这个词来自磁带机年代,把”磁带绕回到磁带开始处“

    即到达某个大小后回到文件头写入

    log4cpp::OstreamAppender

    输出到一个ostream类

    log4cpp::RemoteSyslogAppender

    输出到远程syslog服务器

    log4cpp::StringQueueAppender

    输出到内存队列

    将日志记录到一个字符串队列中

    _queue变量是StringQueueAppender类中用于具体存储日志的内存队列

    StringQueueAppender的使用方法与OstreamAppender类似,其创建函数值接受一个参数”名称“,记录完成后需要程序员自己从队列中取出每条日志

    使用实例

    log4cpp::StringQueueAppender* strQAppender = newlog4cpp::StringQueueAppender("strQAppender");
    strQAppender->serLayout(new log4cpp::BasicLayout);log4cpp::Category& root = log4cpp::Category::getRoot();
    root.addAppender(strQAppender);
    root.setPriority(log4cpp::Priority::DEBUG);root.error("Hello log4cpp in a Error Message!");
    root.warn("Hello log4cpp in a Warning Message!");cout << "Get message from Memory Queue!" << endl;
    cout << "-----------------------------------" << endl;
    queue<string>&myStrQ = strQAppender->getQueue();
    while(!myStrQ.empty())
    {cout << myStrQ.front();myStrQ.pop();
    }log4cpp::Category::shutdown();
    return 0;
    

    创建StringQueueAppender,然后添加如类中,最后在用StringQueueAppener的成员函数getQueue()返回数据成员容器queue

    log4cpp::SyslogAppender

    输出到本地syslog

    Syslog是类Unix系统的一个核心服务,用来提供日志服务,在Windows系统中并没有直接提供支持,当然可以用相关工具提供Windows系统中的syslog服务

    log4cpp::Win32DebugAppender

    发送到缺省系统调试器

    log4cpp::NTEventLogAppder

    发送到win事件日志

Category

负责向日志中写入信息

负责记录日志,优先级

当日志的优先级大于等于Category时,该日志才会被记录,否则会被忽略掉

一个Category可以对应多个Appender

一个Appender对应一个Layout

回收空间

函数说明

该函数将会从Category上删除所有的Appender

函数原型

void log4cpp::Category::shutdown();

获取根日志

函数原型

Category & Category::getRoot();

获取子日志

函数原型

Catrgory & Category::getInstance(const std::string &name);

使用实例

#include "log4cpp/Category.hh"
#include "log4cpp/Appender.hh"
#include "log4cpp/FileAppender.hh"
#include "log4cpp/OstreamAppender.hh"
#include "log4cpp/Layout.hh"
#include "log4cpp/BasicLayout.hh"
#include "log4cpp/Priority.hh"int main(int argc, char** argv) {log4cpp::Appender *appender1 = new log4cpp::OstreamAppender("console", &std::cout);appender1->setLayout(new log4cpp::BasicLayout());log4cpp::Appender *appender2 = new log4cpp::FileAppender("default", "program.log");appender2->setLayout(new log4cpp::BasicLayout());//获取根日志log4cpp::Category& root = log4cpp::Category::getRoot();root.setPriority(log4cpp::Priority::WARN);root.addAppender(appender1);//获取子日志log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1"));sub1.addAppender(appender2);// use of functions for logging messagesroot.error("root error");root.info("root info");sub1.error("sub1 error");sub1.warn("sub1 warn");// printf-style for logging variablesroot.warn("%d + %d == %s ?", 1, 1, "two");// use of streams for logging messagesroot << log4cpp::Priority::ERROR << "Streamed root error";root << log4cpp::Priority::INFO << "Streamed root info";sub1 << log4cpp::Priority::ERROR << "Streamed sub1 error";sub1 << log4cpp::Priority::WARN << "Streamed sub1 warn";// or this way:root.errorStream() << "Another streamed error";Category::shutdown();return 0;
}

输出

1352973121 ERROR  : root error
1352973121 ERROR sub1 : sub1 error
1352973121 WARN sub1 : sub1 warn
1352973121 WARN  : 1 + 1 == two ?
1352973121 ERROR  : Streamed root error
1352973121 ERROR sub1 : Streamed sub1 error
1352973121 WARN sub1 : Streamed sub1 warn
1352973121 ERROR  : Another streamed error

使用log4cpp::Category::getRoot()可以得到根Category。在大多数情况下,一个应用程序只需要一个日志种类(Category),但是有时也会用到多个Category,此时可以使用根Category的getInstance方法来得到子Category。不同的子Category用于不同的场合。

Priority

每个category都有一个优先级,该优先级可以有setPriority方法设置

设计日志优先级

数字越小,优先级越高

typedef enum {EMERG = 0,FATAL = 0,ALERT = 100,CRIT = 200,ERROR = 300,WARN = 400,NOTICE = 500,INFO = 600,DEBUG = 700,NOTSET = 800,
} PriorityLevel;

设置优先级

setPriority函数

setPriority()是category类的成员函数

函数说明

设置日志记录的级别,使得日志只记录优先级比所指定优先级级别更高的记录

函数声明

virtual void setPriority(Priority::Value priority)
throw (std::invalid_argument)

参数列表

priority

输入形式为:log4cpp::Priority::<优先级>

使用实例

log4cpp::OstreamAppender* osAppender1 = new log4cpp::OstreamAppender("osAppender1", &cout);
osAppender1->setLayout(new log4cpp::BasicLayout());log4cpp::OstreamAppender* osAppender2 = new log4cpp::OstreamAppender("osAppender2", &cout);
osAppender2->setLayout(new log4cpp::BasicLayout());log4cpp::Category& root = log4cpp::Category::getRoot();
//设置该Category只记录DEBUG级以上的消息
root.setPriority(log4cpp::Priority::DEBUG);log4cpp::Category& sub1 = root.getInstance("sub1");
sub1.addAppender(osAppender1);
sub1.setPriority(log4cpp::Priority::DEBUG);
seb1.error("sub error");

Category、Appender和Layout三者的关系

系统中可以有多个Category,它们都是继承自同一个根,每个Category负责记录自己的日志;每个Category可以添加多个Appender,每个Appender指定了一个日志的目的地,例如文件、字符流或者Windows日志,当Category记录一条日志时,该日志被写入所有附加到此Category的Appender;每个Appender都包含一个Layout,该Layout定义了这个Appender上日志的格式

log4cpp的日志记录

函数原型

void debug(const std::string &message) throw();
void info(const std::string &message) throw();
void notice(const std::string &message) throw();
void warn(const std::string &message) throw();
void error(const std::string &message) throw();
void crit(const std::string &message) throw();
void alert(const std::string &message) throw();
void emerg(const std::string &message) throw();
void fatal(const std::string &message) throw();

一个封装好的c++日志类

头文件

mylogger.hpp
#include "log4cpp/Category.hh"
#include "log4cpp/Appender.hh"
#include "log4cpp/RollingFileAppender.hh"
#include "log4cpp/OstreamAppender.hh"
#include "log4cpp/Layout.hh"
#include "log4cpp/BasicLayout.hh"
#include "log4cpp/PatternLayout.hh"
#include "log4cpp/Priority.hh"
#include <string>
#include <stdio.h>
#include <pthread.h>
#define LOG(level, msg)                     \{                                       \char _msg[1024];                    \sprintf(_msg, "%s [%s@%s,%d] ",        \msg, __func__, __FILE__, __LINE__ ); \MyLogger::get_MyLogger()->level(_msg);  \}using std::string;
using namespace log4cpp;class MyLogger {public:static MyLogger * get_MyLogger();void Logger_Init();void AddAppender(const string & path);void SetPriority(Priority::Value priority);void warn(const char *msg);void error(const char *msg);void debug(const char *msg);void info(const char *msg);static void destroy();
private:MyLogger();~MyLogger(){}private:static pthread_mutex_t * mutex;static MyLogger * _pMylogger;Category * root;
};

实现文件

//mylogger.cc
#include "mylogger.hpp"MyLogger * MyLogger::_pMylogger = nullptr;
pthread_mutex_t * MyLogger::mutex = nullptr;MyLogger * MyLogger::get_MyLogger() {if(mutex == nullptr) {mutex = new pthread_mutex_t;pthread_mutex_init(mutex, NULL);}if(_pMylogger == nullptr) {pthread_mutex_lock(mutex);if(_pMylogger == nullptr) {_pMylogger = new MyLogger();}pthread_mutex_unlock(mutex);}return _pMylogger;
}MyLogger::MyLogger() {Logger_Init();SetPriority(Priority::DEBUG);
}void MyLogger::Logger_Init() {OstreamAppender * OsAppender = new OstreamAppender("console", &std::cout);PatternLayout * pLayout = new PatternLayout();pLayout->setConversionPattern("%d [%c] [%p] %m%n");OsAppender->setLayout(pLayout);root = &Category::getRoot();root->setAppender(OsAppender);
}void MyLogger::AddAppender(const string & path) {RollingFileAppender * RAppender = new RollingFileAppender("Rollingfile", path);PatternLayout * pLayout = new PatternLayout();pLayout->setConversionPattern("%d [%c] [%p] %m%n");RAppender->setLayout(pLayout);root->addAppender(RAppender);
}void MyLogger::SetPriority(Priority::Value priority) {root->setPriority(priority);
}void MyLogger::warn(const char * msg) {root->warn(msg);
}void MyLogger::error(const char * msg) {root->error(msg);
}void MyLogger::debug(const char * msg) {root->debug(msg);
}void MyLogger::info(const char * msg) {root->info(msg);
}void MyLogger::destroy() {if(_pMylogger) {Category::shutdown();delete _pMylogger;delete mutex;}
}

测试用例

//main.cc
#include "mylogger.hpp"int main() {MyLogger * mylogger = MyLogger::get_MyLogger();mylogger->AddAppender("main.log");LOG(info, "root info");LOG(error, "root error");LOG(warn, "root warn");LOG(debug, "root debug");MyLogger::destroy();return 0;
}

c++ log4cpp的实现 包含使用实例和下载源码相关推荐

  1. mac下dashboard小控件开发实例(附源码)

    1.背景          用mac的用户都应该知道,mac有一个很好的功能,就是dashboard小控件的功能,按下F12键就可以自由切换.博主最近在背GRE单词,就尝试这开发了一个背单词的dash ...

  2. 低压 伺服低压伺服方案全套,包含TI dsp和FPGA 源码和 原理图

    低压 伺服低压伺服方案全套,包含TI dsp和FPGA 源码和 原理图id=644168514874&

  3. 欧瑞伺服 欧瑞伺服方案,SD10-G015包含原理图、pcb、源码

    欧瑞伺服 欧瑞伺服方案,SD10-G015包含原理图.pcb.源码 tb860441701

  4. php读取图片文件流,详解php文件包含原理(读取文件源码、图片马、各种协议、远程getshell等)...

    详解php文件包含原理(读取文件源码.图片马.各种协议.远程getshell等) 作者是namezz (看完图相当于做了一轮实验系列) 现有文件代码如下 1.png (21.16 KB, 下载次数: ...

  5. include详解 shell_详解php文件包含原理(读取文件源码、图片马、各种协议、远程getshell等) ......

    详解php文件包含原理(读取文件源码.图片马.各种协议.远程getshell等) 作者是namezz (看完图相当于做了一轮实验系列) 现有文件代码如下 include和include_once.re ...

  6. 光伏并网逆变器资料,包含原理图,pcb,源码以及元器件明细表

    光伏并网逆变器资料,包含原理图,pcb,源码以及元器件明细表 光伏并网逆变器资料,包含原理图,pcb,源码以及元器件明细表. 如下: 功率接口板原理图和pcb,元器件明细表. 主控DSP板原理图(pd ...

  7. 微信公众平台开发4-长链接转短链接口调用实例(含源码)

    微信公众平台开发-access_token获取及应用(含源码) 作者: 孟祥磊-<微信公众平台开发实例教程> 将一条长链接转成短链接.开发者用于生成二维码的原链接(商品.支付二维码等)太长 ...

  8. Android APP:Preference使用详解和实例(附源码)

    Android APP:Preference使用详解和实例 一.Preference 是Android app中重要的控件之一,Settings 模块大部分都是通过Preference 实现的,这里将 ...

  9. zepto ajax php实例,读Zepto源码之Ajax模块

    Ajax 模块也是经常会用到的模块,Ajax 模块中包含了 jsonp 的现实,和 XMLHttpRequest 的封装. 读 Zepto 源码系列文章已经放到了github上,欢迎star: rea ...

最新文章

  1. 十六进制透明度参照表
  2. [watchtower] 自动更新 Docker 镜像与容器
  3. Dart最新消息:Angular 2 Dart及Flutter发布
  4. cCupcake---ToFu
  5. 是新最全Git命令大全及速记图
  6. Codeforces 627D Preorder Test(二分+树形DP)
  7. 人人商城小程序getUserProfile登录接口升级
  8. 身为程序猿——谷歌浏览器的这些骚操作你真的会吗
  9. 10.12 ——透明网桥,路由策略,准入技术
  10. hse是什么意思的缩写_什么是HSE
  11. 转DICOM学习笔记
  12. 鼠标悬停显示禁用图标
  13. 一文读懂生成对抗网络(GANs)【下载PDF | 长文】
  14. Wavefront OBJ 转换成OpenGL ES使用的C/C++文件
  15. java.lang.RuntimeException:Unable to start activity ComponentInfo{com.meizu.beautify/com.my.viewc.Ma
  16. 大数据不是你想有就能有,如何才能“狂拽炫酷吊炸天”
  17. MybatisX的使用方法
  18. 系统级程序设计第一课
  19. 【Redis核心原理和应用实践】应用 2:缓兵之计 —— 延时队列
  20. python爬虫登录微博_python爬虫-模拟微博登录

热门文章

  1. 从Python新手到高手的68行代码
  2. bzoj-3144 [Hnoi2013]切糕
  3. P5911 [POI2004]PRZ
  4. 关于用excel打开一个utf-8格式的csv文件的问题
  5. TXL C语言语法说明
  6. 网工内推 | 互联网大厂,字节跳动招资深网工,最高40k*15薪
  7. 【专题】2022中国AI人工智能技术应用场景市场研究及选型评估报告PDF合集分享(附原数据表)...
  8. 局域网主机状态管理工具LanNeighborManager
  9. 【工具】微信开发者工具同步代码:似乎认证方式出现了问题
  10. 计算机组成与体系结构第二次试验:存储器实验