http://blog.csdn.net/sky_qing/article/details/7208645

一、安装:

我看网上好多人介绍log4c安装的时候都说有两个步骤:先下载expat安装包并安装expat,然后下载log4c安装包并安装log4c。这么看来,log4c是依赖expat的。但是有时候我们不想使用的日志系统还要依赖别的库,毕竟现在的开源日志系统很多,这样一来log4c就没有那么大的优势了。所以我仔细看了log4c的README文档,发现log4c模块默认情况下是使用expat库来作为XML文件的解析器(因为log4c的配置文件默认是一个叫log4crc的XML文件),我们可以在运行配置文件的时候加上--without-expat选项就可以不使用expat库而使用log4c自定义的解析器,该解析器是使用lex/yacc的代码进行解析的。
安装步骤跟很多其他的库一样,都是三个步骤:

  1. ./configure
  2. make
  3. make install

我们可以在configure的时候加一些选项,如果要设置log4c的安装路径为/usr/local/log4c,我们就可以加--prefix=/usr/local/log4c,如果不想依赖expat解析器,我们可以加--without-expat。如果我们要指定软件运行的系统平台,交叉环境下,我们可以用--host选项来设置,如果运行在arm平台下就加--host=arm-linux,如果是运行在mips平台下就加--host=mips-linux。

如果安装完的时候出现了以下错误,不要着急:
../../src/log4c/.libs/liblog4c.so: undefined reference to `rpl_malloc'
../../src/log4c/.libs/liblog4c.so: undefined reference to `rpl_realloc'
解决方法如下:
修改log4c_build/log4c-1.2.1/src/config.h.in文件:
将201行的#undef malloc注释掉。
将204行的#undef realloc注释掉。
然后执行以下命令:

  1. ./configure(同样有必要的情况下加上相应的选项)
  2. make clean
  3. make
  4. make install

二、介绍一下log4c的配置文件log4crc:

log4c中有三个重要的概念, category, appender, layout。
1. category(类型)用于区分不同的logger, 其实它就是个logger。在一个程序中我们可以通过category来指定很多的logger,用于不同的目的。
2. appdender用于描述输出流,通过为category来指定一个appdender,可以决定将log信息来输出到什么地方去,比如stdout, stderr, 文件, 或者是socket等等。说说常见的两种,stdout是输出到控制台,文件当然就是输出到文件咯,在log4c中默认的是使用轮询文件保存日志,假如我们设定的文件名为wlanLog(配置文件中是appender节点的prefix属性),文件的maxsize设置为102400(Bytes),文件的maxnum为10(文件的最多个数),那么日志会保存在wlanLog.0文件中,当该文件的大小达到102400Bytes是就会自动保存到wlanLog.1文件中,依次类推,当文件的个数达到maxnum且文件已满,接下来会自动保存到wlanLog.0文件中,这样循环保存的方式就是轮询。
3. layout用于指定日志信息的格式,通过为appender来指定一个layout,可以决定log信息以何种格式来输出,比如是否有带有时间戳, 是否包含文件位置信息等,以及他们在一条log信息中的输出格式的等,一般有basic和dated两种。大家感兴趣可以分别去试一下看看日志有什么区别。
最后,说一下log4crc文件放在项目工程生成的目标文件的那个目录下。

三、使用:

  1. // 初始化
  2. log4c_init();
  3. // 获取一个已有的category,这个category(此处为WLAN_Console)必须先配置到配置文件中。
  4. log4c_category_t* mycat = log4c_category_get("WLAN_Console");
  5. // 用该category进行日志输出,日志的类型为DEBUG,输出信息为 "Hello World!",
  6. log4c_category_log(mycat, LOG4C_PRIORITY_DEBUG, "Hello World!");
  7. // 去初始化
  8. log4c_fini();
  9. // log4c_category_log的原型为:
  10. static LOG4C_INLINE void log4c_category_log(const log4c_category_t* a_category,
  11. int a_priority,
  12. const char* a_format,
  13. ...)
  14. // 其中后面的日志输出的格式化字符串a_format跟printf的输出格式化字符串一样,后面的参量表也和printf一样。非常方便!

log4c的日志优先级有11个,在src/log4c/目录下的priority.h中。我们常用的也就error、warn、info、debug和trace。

  1. /**
  2. * Predefined Levels of priorities. These correspond to the priority levels
  3. * used by syslog(3).
  4. **/
  5. typedef enum {
  6. /** fatal */        LOG4C_PRIORITY_FATAL    = 000,
  7. /** alert */        LOG4C_PRIORITY_ALERT    = 100,
  8. /** crit */         LOG4C_PRIORITY_CRIT     = 200,
  9. /** error */        LOG4C_PRIORITY_ERROR    = 300,
  10. /** warn */         LOG4C_PRIORITY_WARN     = 400,
  11. /** notice */       LOG4C_PRIORITY_NOTICE   = 500,
  12. /** info */         LOG4C_PRIORITY_INFO     = 600,
  13. /** debug */        LOG4C_PRIORITY_DEBUG    = 700,
  14. /** trace */        LOG4C_PRIORITY_TRACE    = 800,
  15. /** notset */       LOG4C_PRIORITY_NOTSET   = 900,
  16. /** unknown */      LOG4C_PRIORITY_UNKNOWN  = 1000
  17. } log4c_priority_level_t;

有时候为了方便,我们可以将log4c_category_log用宏定义封装起来,这个网上有例子,我给个链接吧:

http://www.cnblogs.com/jyli/archive/2010/02/11/1660606.html

我们也可以用一个函数封装起来,这个网上我没找到,我就把我作的封装分享一下吧,因为这个牵扯到变参函数的参数传递,所以可能好多刚接触到变参函数的童鞋不是很清楚。

  1. /**********************************************************************
  2. 函数名称          :       logOut
  3. 创建日期          :       2011-12-27
  4. 作者              :<span style="white-space:pre">     </span>  丶小小小威
  5. 函数描述          :       将日志输出到控制台
  6. 输入参数          :
  7. const LOG_LEVEL level :   日志输出的级别
  8. const char *format    :   日志输出的格式化字符串
  9. 输出参数          :
  10. 返回值            :
  11. **********************************************************************/
  12. void CLogger::logOut(const LOG_LEVEL level, const char *format, ...)
  13. {
  14. char temp[MAX_LEN] = {0};
  15. int ret = 0;
  16. va_list ap;
  17. va_start(ap, format);
  18. ret = vsnprintf(temp, MAX_LEN, format, ap);
  19. assert((-1<ret) && (MAX_LEN>ret));
  20. switch (m_logMode)
  21. {
  22. case TO_CONSOLE_AND_FILE:    //既输出到控制台又输出到文件
  23. {
  24. if (m_consoleCategory && m_fileCategory)
  25. {
  26. log4c_category_log(m_consoleCategory, level, "%s", temp);
  27. log4c_category_log(m_fileCategory, level, "%s", temp);
  28. }
  29. break;
  30. }
  31. case TO_CONSOLE:             //输出到控制台
  32. {
  33. log4c_category_log(m_consoleCategory, level, "%s", temp);
  34. break;
  35. }
  36. case TO_FILE:                //输出到文件
  37. {
  38. log4c_category_log(m_fileCategory, level, "%s", temp);
  39. break;
  40. }
  41. default:
  42. break;
  43. }
  44. va_end(ap);
  45. }

说明:我这里的LOG_LEVEL是我自己定义的一个枚举类型,成员为常用的几种日志类型(或者说优先级),m_logMode是我Log模块封装类的一个成员变量,表示日志输出的方式,上面的三种。我想这个我就不用多说了吧,你懂的,= =!

下面调用的时候也很简单:

  1. char c = '\x41';
  2. char s[20];
  3. const char *p = "How do you do";
  4. int a = 1234;
  5. int ha = 12;
  6. int *i;
  7. i = &ha;
  8. float f = 3.141592653589;
  9. double x = 0.12345678987654321;
  10. strcpy(s, "Hello, Comrade");
  11. logger->logOut(ERROR, "a=%d", a);        /*结果输出十进制整数a=1234*/
  12. printf("===============================> a=%d\n\n", a);
  13. logger->logOut(ERROR, "a=%6d", a);   /*结果输出6位十进制整数a=  1234*/
  14. printf("===============================> a=%6d\n\n", a);
  15. logger->logOut(ERROR, "a=%06d", a);  /*结果输出6位十进制整数a=001234*/
  16. printf("===============================> a=%06d\n\n", a);
  17. logger->logOut(ERROR, "a=%2d", a);   /*a超过2位,按实际值输出a=1234*/
  18. printf("===============================> a=%2d\n\n", a);
  19. logger->logOut(ERROR, "*i=%4d", *i); /*输出4位十进制整数×i=  12*/
  20. printf("===============================> *i=%4d\n\n", *i);
  21. logger->logOut(ERROR, "*i=%-4d", *i);    /*输出左对齐4位十进制整数×i=12*/
  22. printf("===============================> *i=%-4d\n\n", *i);
  23. logger->logOut(ERROR, "i=%p", i);        /*输出地址i=0xbf96538c*/
  24. printf("===============================> i=%p\n\n", i);
  25. logger->logOut(ERROR, "f=%f", f);        /*输出浮点数f=3.141593*/
  26. printf("===============================> f=%f\n\n", f);
  27. logger->logOut(ERROR, "f=6.4f", f);  /*输出6位其中小数点后4位的浮点数 f=3.1416*/
  28. printf("===============================> f=6.4f\n", f);
  29. logger->logOut(ERROR, "x=%lf", x);   /*输出长浮点数x=0.123457*/
  30. printf("===============================> x=%lf\n\n", x);
  31. logger->logOut(ERROR, "x=%18.16lf", x);  /*输出18位其中小数点后16位的长浮点数 x=0.1234567898765432*/
  32. printf("===============================> x=%18.16lf\n\n", x);
  33. logger->logOut(ERROR, "c=%c", c);        /*输出字符c=A*/
  34. printf("===============================> c=%c\n\n", c);
  35. logger->logOut(ERROR, "c=%x", c);        /*输出字符ASCII码值c=41*/
  36. printf("===============================> c=%x\n\n", c);
  37. logger->logOut(ERROR, "s[]=%s", s);  /*输出数组字符串s[]=Hello, Comrade*/
  38. printf("===============================> s[]=%s\n\n", s);
  39. logger->logOut(ERROR, "s[]=%6.9s", s);   /*输出最多9个字符的字符串s[]=Hello, Co*/
  40. printf("===============================> s[]=%6.9s\n\n", s);
  41. logger->logOut(ERROR, "s=%p", s);        /*输出数组字符串首字符地址s=FFBE*/
  42. printf("===============================> s=%p\n\n", s);
  43. logger->logOut(ERROR, "*p=%s", p);   /*输出指针字符串p=How do you do*/
  44. printf("===============================> *p=%s\n\n", p);
  45. logger->logOut(ERROR, "p=%p", p);        /*输出指针的值p=0x8049a70*/
  46. printf("===============================> p=%p\n\n", p);

说明:logger是我写的日志封装类的一个对象,大家可以把上面的部分代码加到自己的程序中,看看输出结果和printf到底是不是一样?我测试过,完全一样,这样一看,使用log4c日志模块更让人一目了然,尤其是在一个比较大的项目中,有一个好的日志模块将是非常重要的!差点忘了还有个编译运行。

四、编译运行:

编译的时候要链接上库和头文件。编译的格式如下:

说明:我用的是mips,所以编译时使用mips-linux-g++,我的log4c安装默认的路径下:/usr/local。这里用到的libxml2是因为我涉及修改log4c的配置文件log4crc,是一个XML文件,我选择libxml2。在mips上运行的时候要先告诉mips库所在的位置,使用export LD_LIBRARY_PATH=“库所在的位置”,建议大家写个Makefile。

五、log4crc配置文件:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE log4c SYSTEM "">
  3. <log4c version="1.2.1">
  4. <config>
  5. <bufsize>0</bufsize>
  6. <debug level="2"/>
  7. <nocleanup>0</nocleanup>
  8. <reread>1</reread>
  9. </config>
  10. <category name="root" priority="notice"/>
  11. <category name="six13log.log" priority="error" appender="stdout"/>
  12. <!--输出到控制台-->
  13. <category name="WLAN_Console" priority="trace" appender="stdout"/>
  14. <!--保存日志到文件-->
  15. <category name="WLAN_File" priority="trace" appender="myrollingfileappender"/>
  16. <!--logdir为日志输出路径  prefix为文件名  layout为输出格式 -->
  17. <appender name="myrollingfileappender" type="rollingfile" logdir="." prefix="wlan_log" layout="dated" rollingpolicy="myrollingpolicy"/>
  18. <!--sizewin表示达到最大值后新建日志文件  值由maxsize设定,单位Bytes     maxnum为最大文件数目-->
  19. <rollingpolicy name="myrollingpolicy" type="sizewin" maxsize="102400" maxnum="10"/>
  20. <appender name="stdout" type="stream" layout="basic"/>
  21. <appender name="stderr" type="stream" layout="dated"/>
  22. <appender name="syslog" type="syslog" layout="basic"/>
  23. <appender name="s13file" type="s13_file" layout="basic"/>
  24. <appender name="plain_stderr" type="s13_stderr" layout="none"/>
  25. <appender name="cat_stderr" type="s13_stderr" layout="catlayout"/>
  26. <appender name="xml_stderr" type="s13_stderr" layout="xmllayout"/>
  27. <appender name="user_stderr" type="s13_stderr" layout="userlayout"/>
  28. <layout name="basic" type="basic"/>
  29. <layout name="dated" type="dated"/>
  30. <layout name="catlayout" type="s13_cat"/>
  31. <layout name="xmllayout" type="s13_xml"/>
  32. <layout name="none" type="s13_none"/>
  33. <layout name="userlayout" type="s13_userloc"/>
  34. <category name="six13log.log.app.application2" priority="debug" appender="cat_stderr"/>
  35. <category name="six13log.log.app.application3" priority="debug" appender="user_stderr"/>
  36. <category name="six13log.log.app" priority="debug" appender="myrollingfileappender"/>
  37. <category name="log4c.examples.helloworld" priority="debug" appender="stdout"/>
  38. </log4c>

Over~~~
  最后祝大家工作顺利!有什么不准确的地方希望大家提出来,共同探讨。谢谢~

开源日志系统 log4c 使用心得+总结的更多相关文章

  1. 开源日志系统比较:scribe、chukwa、kafka、flume

    1. 背景介绍 许多公司的平台每天会产生大量的日志(一般为流式数据,如,搜索引擎的pv,查询等),处理这些日志需要特定的日志系统,一般而言,这些系统需要具有以下特征: (1) 构建应用系统和分析系统的 ...

  2. 使用 SLF4J + LogBack 构建日志系统(转)

    转载自:http://www.cnblogs.com/mailingfeng/p/3499436.html 上次我们讨论了如何选择一个好的开源日志系统方案,其中的结论是:使用 SLF4J + LogB ...

  3. c++开源日志log4cplus使用开发文档

    下载地址:http://files.cnblogs.com/files/lizhigang/LOG4CPLUS%E5%BC%80%E5%8F%91%E4%B8%8E%E4%BD%BF%E7%94%A8 ...

  4. 开源社交系统ThinkSNS v4.6.1更新日志及功能详解!

    ThinkSNS 开源社交系统 v4.6.1更新日志 [修复]聊天无法使用emoji问题 [修复]后台禁用用户后,app第三方登录可登录问题 [修复]部分接口问题 [修复]h5个人中心获取用户信息问题 ...

  5. 利用开源架构ELK构建分布式日志系统

    问题导读 1.ELK产生的背景?2.ELK的基本组成模块以及各个模块的作用?3.ELK的使用总计有哪些? 背景 日志,对每个系统来说,都是很重要,又很容易被忽视的部分.日志里记录了程序执行的关键信息, ...

  6. C++ 高性能无锁日志系统

    服务器编程中,日志系统需要满足几个条件 .高效,日志系统不应占用太多资源 .简洁,为了一个简单的日志功能引入大量第三方代码未必值得 .线程安全,服务器中各个线程都能同时写出日志 .轮替,服务器不出故障 ...

  7. [Asp.net 5] Logging-其他日志系统的实现

    Microsoft.Framework.Logging.NLog 使用Nlog扩展日志系统:按照我们上节说的,对于扩展的日志系统都要实现俩个接口ILogger.ILoggerProvider.所以在当 ...

  8. 【转载】scribe、chukwa、kafka、flume日志系统对比

    原文地址:http://www.ttlsa.com/log-system/scribe-chukwa-kafka-flume-log-system-contrast/ 1. 背景介绍许多公司的平台每天 ...

  9. 爆料喽!!!开源日志库Logger的剖析分析

    导读 Logger类提供了多种方法来处理日志活动.上一篇介绍了开源日志库Logger的使用,今天我主要来分析Logger实现的原理. 库的整体架构图 详细剖析 我们从使用的角度来对Logger库抽茧剥 ...

随机推荐

  1. 将日期yyyy-MM-dd转为数字大写的形式

    /** * 将日期转大写 * 例如:2013-05-13转为 二0一三年五月十三日 * @param date * @return */ public static String getDxDate( ...

  2. auto space advisor

    <pre name="code" class="sql">首先:oracle有自动Job,进行shrink space SQL> select ...

  3. Oracle查询死锁&杀死会话

    select object_name,machine,s.sid,s.serial#  from v$locked_object l,dba_objects o ,v$session s where ...

  4. Linux磁盘及文件系统管理 2---- 使用fdisk进行磁盘管理

    1 FDISK分区工具 1 fsidk是来自IBM的分区工具,支持绝大多数的操作系统,几乎所有的Linux都装有fdisk 2 fdisk是一个支持MBR的分区工具,如果要使用GPT的话我们无法使用f ...

  5. thinkphp分页时修改last显示标题

    需要修改Page.class.php里lastSuffix为false,这样才能修改last显示标题. 然后就可以设置了 或者直接在方法中声明: $p->lastSuffix = false; ...

  6. Javascript:作用域 学习总结

    作用域(scope): 变量与函数的可访问范围,控制着变量与函数的可见性和生命周期   作用域分类: javascript中,变量的作用域分为:全局作用域,局部作用域 局部变量的优先级大于全局变量,或 ...

  7. Ubuntu 14.04根据系统,休眠后不能启动要解决的问题

    简介: 提升Ubuntu制度14.04之后,当系统进入休眠,我们不能再次启动,直接崩溃,凡出了问题? 1.   问题纳入 Ubuntu升级系统14.04之后.通过系统的Power设置休眠时间,在系统进 ...

  8. Android 编程下模拟 HOME 键效果

    Android 应用开发中,有一种场景,就是我们不希望用户按 Back 键直接退出 Activity,而是希望应用隐藏到后台,类似于按 Home 键的效果.参考如下代码即可实现这样的效果: publi ...

  9. (转)Web.config配置文件详解(新手必看)

    花了点时间整理了一下ASP.NET Web.config配置文件的基本使用方法.很适合新手参看,由于Web.config在使用很灵活,可以自定义一些节点.所以这里只介绍一些比较常用的节点. <? ...

  10. AVL树插入和删除

    一.AVL树简介 AVL树是一种平衡的二叉查找树. 平衡二叉树(AVL 树)是一棵空树,或者是具有下列性质的二叉排序树:    1它的左子树和右子树都是平衡二叉树,    2且左子树和右子树高度之差的 ...