# osc-sf-log4cpp
**Repository Path**: kzhuo/osc-sf-log4cpp
## Basic Information
- **Project Name**: osc-sf-log4cpp
- **Description**: 对log4cpp进行封装
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2017-12-30
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
LRTSW-log4cpp模块使用手册
LRTSW-SW-2
| 编制部门
Owner | 第23事业部 |
|---|---|
| 适用范围
Scope | LRTS系统 |
| 拟稿人
Initiated by | 卓开阔 |
| 发行
Issued by | 第23事业部文档中心 |
| 受控状态
Control type | □ 非受控 ■ 受控
受控号 NO.: D08 |
| 秘密等级
Secret Level | □ 绝密 □ 机密
■ 秘密 □ 一般 |
Table: 修订记录Revision History
| 版本 | 日期 | 修改内容 | 拟稿 | 审核 | 批准 |
|---|---|---|---|---|---|
| v0.0.1 | 2017-12-30 | 创建 | 卓开阔 | | |
# 1 概述
日志模块是UNIFW的重要组成部分,该模块提供调试日志相关的常用操作。该模块对基于sourceforge上最新版本的log4cpp进行封装,便于在C语言中使用。
Log4cpp是一个开源的C++类库,它提供了在C++程序中使用日志和跟踪调试的功能。使用log4cpp,可以很便利地将日志或者跟踪调试信息写入字符流、内存字符串队列、文件、回滚文件、调试器、Windows日志、本地syslog和远程syslog服务器中。
Log4cpp是个基于LGPL的开源项目,移植自Java的日志处理跟踪项目log4j,并保持了API上的一致。其类似的支持库还包括Java(log4j),C++(log4cpp、log4cplus),C(log4c),python(log4p)等。
Log4cpp有如下优点:
- 提供了可扩展的多种日志记录方式;
- 提供了NDC(嵌套诊断上下文),可用于多线程、多场景的跟踪调试;
- 提供了完整的日志动态优先级控制,可随时调整需要记录的日志优先级;
- 可通过配置文件完成所有配置并动态加载;
- 代码级的平台无关性,Log4cpp源代码经过编译后,适用于大多数主流的操作系统和开发工具;
- 概念清晰,学习和使用方便。
## 1.1 基本概念
Log4cpp中的概念继承自log4j,最重要的是Category(种类)、Appender(附加目的地)和Layout(布局)三个概念,此外还有Priority(优先级)和NDC(嵌套的诊断上下文)等。
简言之,Category负责向日志中写入信息,Appender负责指定日志的目的地,Layout负责设定日志的格式,Priority被用来指定Category的优先级和日志的优先级, NDC则是一种用来区分不同场景中交替出现的日志的手段。
Log4cpp记录日志的原理如下:每个Category都有一个优先级,该优先级可以由setPriority方法设置,或者从其父Category中继承而来。每条日志也有一个优先级,当Category记录该条日志时,若日志优先级高于Category的优先级时,该日志被记录,否则被忽略。系统优先级采用通用的日志级别。
```
LOG_EMERG
LOG_FATAL
LOG_ALERT
LOG_CRIT
LOG_ERROR
LOG_WARN
LOG_NOTICE
LOG_INFO
LOG_DEBUG
LOG_NOTSET
```
注意:取值越小,优先级越高。例如一个Category的优先级为ALERT,则所有EMERG、FATAL、ALERT日志都可以记录下来,而其他则不能。
Category、Appender和Layout三者的关系如下:系统中可以有多个Category,它们都是继承自同一个根,每个Category负责记录自己的日志;每个Category可以添加多个Appender,每个Appender指定了一个日志的目的地,例如文件、字符流或者Windows日志,当Category记录一条日志时,该日志被写入所有附加到此Category的Appender;每个Append都包含一个Layout,该Layout定义了这个Appender上日志的格式。
目前主要支持以下Appender:
```cpp
log4cpp::FileAppender // 输出到文件
log4cpp::DailyRollingFileAppender // 输出到日期回卷文件,即当文件到达某个时间条件后回卷
log4cpp::RollingFileAppender // 输出到回卷文件,即当文件到达某个大小后回卷
log4cpp::OstreamAppender // 输出到一个ostream类
log4cpp::SyslogAppender // 输出到syslog
log4cpp::RemoteSyslogAppender // 输出到一个远程syslog
log4cpp::StringQueueAppender // 内存队列
log4cpp::Win32DebugAppender // 发送到缺省系统调试器,windows专用
log4cpp::NTEventLogAppender // 发送到win事件日志,windows专用
log4cpp::IdsaAppender // 发送到IDSA,需要库支持
```
为了便于大家在unifw中使用,只推荐在配置文件中进行相关内容的配置,不在源代码中对相关内容进行操作。
## 1.2 常用appender介绍
### 1.2.1 FileAppender
FileAppender和RollingFileAppender是log4cpp中最常用的两个Appender,其功能是将日志写入文件中。它们之间唯一的区别就是前者会一直在文件中记录日志(直到操作系统承受不了为止),而后者会在文件长度到达指定值时循环记录日志,文件长度不会超过指定值(默认的指定值是10Mbyte)。
一般仅使用前两个参数,即“名称”和“日志文件名”。第三个参数指示是否在日志文件后继续记入日志,还是清空原日志文件再记录。第四个参数说明文件的打开方式。
它与FileAppender的创建函数很类似,但是多了两个参数:maxFileSize指出了回滚文件的最大值;maxBackupIndex指出了回滚文件所用的备份文件的最大个数。所谓备份文件,是用来保存回滚文件中因为空间不足未能记录的日志,备份文件的大小仅比回滚文件的最大值大1kb。所以如果maxBackupIndex取值为3,则回滚文件(假设其名称是rollwxb.log,大小为100kb)会有三个备份文件,其名称分别是rollwxb.log.1,rollwxb.log.2和rollwxb.log.3,大小为101kb。另外要注意:如果maxBackupIndex取值为0或者小于0,则回滚文件功能会失效,其表现如同FileAppender一样,不会有大小的限制。
### 1.2.2 NTEventLogAppender
该Appender可以将日志发送到windows的日志,在运行程序后可以打开windows的计算机管理->系统工具->事件查看器->应用程序。
### 1.2.3 注意事项
在使用log4cpp时应该遵循以下几个使用原则:
- 不要手动释放Category、Appender和Layout;
- 同一个Appender不要加入多个Category,否则它会被释放多次从而导致程序崩溃;
- 同一个Layout不要附着到多个Appender上,否则也会被释放多次导致程序崩溃;
#使用方法
## 1.3 基本使用
```cpp
#include "unifw.h"
#include "log/log4cpp.h"
int main(int argc, char *argv[])
{
log4cpp_init(zlog_conf);
VLOG_DEBUG("Get debug count %d", 1);
log4cpp_close();
return 0;
}
```
## 1.4 标注配置文件解释
```
# Set root category priority to DEBUG and its only appender to A1.
log4cpp.rootCategory=INFO,rootAppender # 主category级别为INFO,使用rootAppender
log4cpp.category.app=DEBUG,A3 # category "app"级别,Appender为A3
log4cpp.category.sc=DEBUG,A4
log4cpp.appender.rootAppender=ConsoleAppender # 设置根cat为终端输出
log4cpp.appender.rootAppender.threshold=INFO # 设置根cat日志级别为>=INFO
log4cpp.appender.rootAppender.layout=BasicLayout
log4cpp.appender.A3=RollingFileAppender # 设置app cat为回卷文件输出
log4cpp.appender.A3.fileName=APP.log # 日志文件名
log4cpp.appender.A3.maxFileSize=5000000 # 日志大小,默认为10*1024*1024
log4cpp.appender.A3.maxBackupIndex=5 # 允许保存的最大文件数量
#log4cpp.appender.A3.append=1 # 是否采用追加方式
log4cpp.appender.A3.layout=PatternLayout
log4cpp.appender.A3.layout.ConversionPattern=[%d %c %p] '%m'%n # 打印格式
log4cpp.appender.A4=DailyRollingFileAppender # 设置sc cat为每日回卷文件输出
#log4cpp.appender.A4.threshold=INFO # 设置本appender的门槛报警级别为>=INFO才打印
log4cpp.appender.A4.fileName=SC.log # 设置文件
#log4cpp.appender.A4.maxDaysKeep=3 # 设置最大文件,默认为0
log4cpp.appender.A4.layout=PatternLayout # 设置布局
log4cpp.appender.A4.layout.ConversionPattern=[%d %c %p] '%m'%n
log4cpp.appender.sl=SyslogAppender # 远程syslog
log4cpp.appender.sl.syslogName=app # 日志名称
log4cpp.appender.sl.syslogHost=localhost # 远程日志
log4cpp.appender.sl.facility=16 # 设置syslog的facility,LOCAL1从16开始
log4cpp.appender.sl.portNumber=-1 # 设置远程syslog的端口,默认值为-1,内部转换为514
log4cpp.appender.s2=LocalSyslogAppender # 本地syslog
log4cpp.appender.s2.syslogName=app # 日志名称
log4cpp.appender.sl.facility=17 # 设置syslog的facility,LOCAL1从16开始
```
## 1.5 日志布局layout详解
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".
## 1.6 自定义category
```cpp
#include "unifw.h"
#include "log/log4cpp.h"
int main(int argc, char *argv[])
{
void *p_route_logger=NULL;
log4cpp_init(zlog_conf);
VLOG_DEBUG("Get debug count %d", 1);
p_route_logger = log4cpp_getlogger("app.ci_route");
RTRACE(p_route_logger, "联锁进路模块初始化");
log4cpp_close();
return 0;
}
```
# 2 API使用说明
```c
/**
* @brief log4cpp_init 初始化函数
*
* @param conf_file 配置文件名称
* @details 按照如下优先级进行配置:
* 指定的conf_file, log4cpp.conf文件
* 如果指定为NULL或"",则使用默认配置
* 建议默认名称定义为app的值
*
* @return >=0为成功;<0为失败
*/
int16_t log4cpp_init(const char *conf_file);
/**
* @brief log4cpp_close 关闭日志
*/
void log4cpp_close();
/**
* @brief log4cpp_getlogger 获取指定的category名称
*
* @param name 名称
*
* @return 指定category的指针,返回值为void*
*/
void *log4cpp_getlogger(const char *name);
/**
* @brief RLOG 使用logger进行日志
*
* @param r logger指针
* @param pri 优先级
* @param fmt 格式
*
*/
#define RLOG log4cpp_rawlog
/**
* @brief APPLOG 使用默认logger进行日志
*
* @param pri 优先级
* @param fmt 格式
*
*/
#define APPLOG(pri, fmt, ...) RLOG(g_l4cpp_app, pri, fmt, ##__VA_ARGS__)
/**
* @brief SCLOG 使用sclogger进行日志
*
* @param pri 优先级
* @param fmt 格式
*
*/
#define SCLOG (pri, fmt, ...) RLOG(g_l4cpp_sc, pri, fmt, ##__VA_ARGS__)
/**
* @brief RLOG 使用logger进行日志
*
* @param r logger指针
* @param pri 优先级
* @param fmt 格式
*
*/
#define RLOG
/**
* @brief APPLOG 使用默认logger进行日志
*
* @param pri 优先级
* @param fmt 格式
*
*/
#define APPLOG(pri, fmt, ...) RLOG(g_l4cpp_app, pri, fmt, ##__VA_ARGS__)
/**
* @brief VLOG 使用默认logger进行打印
*
* @param pri 优先级
* @param fmt 格式
*
*/
#define VLOG APPLOG
#define VLOG_EMERG( fmt, ...) VLOG(LOG_EMERG , fmt, ##__VA_ARGS__)
#define VLOG_ALERT( fmt, ...) VLOG(LOG_ALERT , fmt, ##__VA_ARGS__)
#define VLOG_CRIT( fmt, ...) VLOG(LOG_CRIT , fmt, ##__VA_ARGS__)
#define VLOG_ERR( fmt, ...) VLOG(LOG_ERR , fmt, ##__VA_ARGS__)
#define VLOG_WARNING(fmt, ...) VLOG(LOG_WARNING, fmt, ##__VA_ARGS__)
#define VLOG_NOTICE( fmt, ...) VLOG(LOG_NOTICE , fmt, ##__VA_ARGS__)
#define VLOG_INFO( fmt, ...) VLOG(LOG_INFO , fmt, ##__VA_ARGS__)
#define VLOG_DEBUG( fmt, ...) VLOG(LOG_DEBUG , fmt, ##__VA_ARGS__)
#define RLOG_EMERG( r, fmt, ...) RLOG(r, LOG_EMERG , fmt, ##__VA_ARGS__)
#define RLOG_ALERT( r, fmt, ...) RLOG(r, LOG_ALERT , fmt, ##__VA_ARGS__)
#define RLOG_CRIT( r, fmt, ...) RLOG(r, LOG_CRIT , fmt, ##__VA_ARGS__)
#define RLOG_ERR( r, fmt, ...) RLOG(r, LOG_ERR , fmt, ##__VA_ARGS__)
#define RLOG_WARNING(r, fmt, ...) RLOG(r, LOG_WARNING, fmt, ##__VA_ARGS__)
#define RLOG_NOTICE( r, fmt, ...) RLOG(r, LOG_NOTICE , fmt, ##__VA_ARGS__)
#define RLOG_INFO( r, fmt, ...) RLOG(r, LOG_INFO , fmt, ##__VA_ARGS__)
#define RLOG_DEBUG( r, fmt, ...) RLOG(r, LOG_DEBUG , fmt, ##__VA_ARGS__)
#define RTRACE(r, fmt, ...) RLOG(r, LOG_DEBUG, "%s:%d "fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define VTRACE(fmt, ...) RTRACE(g_l4cpp_app, fmt, ##__VA_ARGS__)
#define SCTRACE(fmt, ...) RTRACE(g_l4cpp_sc, fmt, ##__VA_ARGS__)
```