后台服务日志输出规范
在后台服务中添加程序日志记录可以跟踪代码运行时轨迹,作为日后审计的依据;并且担当集成开发环境中的调试器的作用,向文件打印代码的调试信息;同时规划化输出的日志文件,便于和其他相关人员交流分析使用。本规定C++ 后台服务项目必须使用。
日志文件
日志文件按应用需求功能分为访问日志和应用日志和系统日志。日志文件统一命名格式如下:服务名称.应用类型.时间.索引。中间采用点符号(.) 分割。
服务名称:进程名或者bin文件的名称。
应用类型:目前分为ACCESS,简写为ACC;application,简写为APP,系统日志,简写为SYS。
时间:目前按天写日志,格式是YYYYMMDD。如果文件名不能输出时间格式,可省略。
索引:目前当天的索引从0或者1开始,最好不要超过20。索引也可以是一个其他的标识。日志必须支持滚动日志输出,避免日志写满磁盘。
1.1. 访问日志文件
访问日志文件主要是为了输出服务器收到请求,以及对请求的应答;对外请求以及外部服务对请求的应答。
1.1.1. 访问日志文件格式
分为接受日志和和应答日志两种。
1.1.1.1. 网络接收日志格式
收取时间
日志级别(DEBUG,INFO,WARN,ERROR,FATAL)
日志输出标记
线程标识
文件名称(DEBUG日志需要,非DEBUG日志可以为空)
文件行号(DEBUG日志需要,非DEBUG日志可以为空)
函数名称(DEBUG日志需要,非DEBUG日志可以为空)
日志描述
处理耗时(单位:毫秒),请求一般是零。
日志标记(包括REQ,ACCEPT几种大类型)
对方地址
对方端口
数据包长度
数据包内容(16进制),如果内容太大,可以考虑只是打印一部分,多余部分用***表示。建议输出长度不要超过512字节,大于512字节的数据屏蔽输出。
需要更多字段只能增加到后面,字段内容之间采用|分开,如果输出内容之间包含有|,将|转义为#后输出.
1.1.1.2. 网络应答日志格式
应答时间
日志级别(DEBUG,INFO,WARN,ERROR,FATAL)
日志输出标记
线程标识
文件名称(DEBUG日志需要,非DEBUG日志可以为空)
文件行号(DEBUG日志需要,非DEBUG日志可以为空)
函数名称(DEBUG日志需要,非DEBUG日志可以为空)
日志描述
处理耗时(单位:毫秒)
日志标记(包括RESP,CLOSE,SHUNDOWN几种大类型)
对方地址
对方端口
数据包长度
数据包内容(16进制),如果内容太大,可以考虑只是打印一部分,多余部分用***表示。建议输出长度不要超过512字节,大于512字节的数据屏蔽输出。
需要更多字段只能增加到后面,字段内容之间采用|分开,如果输出内容之间包含有|,将|转义为#后输出.
1.1.1.3. 日志标记
RESP:表示收到对方的应答。
REQ:表示请求外部服务。
ACCEPT:表示接入一个新连接。
CONNECT:表示向外部服务发起一个新连接;
CLOSE:表示关闭一个连接;
SHUNDOWN:表示切断一个连接
1.1.1.4. 日志标记子定义
日志标记(RESP,REQ,CONNECT)里面的 RESP和REQ,CONNECT可以细化定义,增加子类型。因为一个网络服务有可能需要和A,B,C等不同的服务类别交互,该网络服务有可能既对外提供服务,也同时需要访问其他网络服务器的服务。
比如访问A进程的A1和A2服务器的服务,分别可以这样定义:
REQ_A_A1,RESP_A_A1;
REQ_A_A2,RESP_A_A2;
比如连接A进程:
CONNECT_A;
1.1.1.5. 日志输出示例
2013-09-04 10:29:43.148.000|DEBUG|ACCfilelogger.ACC[2]|4324|f:\work\mytest\log4cplus_test\log4cplus_test\log4cplus_test.cpp|34|printDebug|This is a ACC message|0|REQ|172.13.12.35|3456|845|0x 0d 0x
2013-09-04 10:29:43.148.000|DEBUG|ACCfilelogger.ACC[2]|4324|f:\work\mytest\log4cplus_test\log4cplus_test\log4cplus_test.cpp|35|printDebug|This is a ACC message|150|RESP|172.13.12.35|3456|345|0x 0d 0x 0A
2013-09-04 10:29:43.148.000|ERROR|ACCfilelogger.ACC[2]|4324|f:\work\mytest\log4cplus_test\log4cplus_test\log4cplus_test.cpp|36|printDebug|This is a ACC message|0|CONNECT_A|172.13.12.99|8888||
2013-09-04 10:29:43.148.000|INFO |ACCfilelogger.ACC[2]|4324||||This is a ACC message|0|REQ_A_A1|172.13.12.99|8888|234|0x 0d 0x 0A
1.1.2. 日志文件命名
访问日志文件命名为
服务名称.ACC.时间.索引。
比如进程 shutong 的几个日志文件命名是:
shutong.ACC.20130819.0
shutong.ACC.20130819.15
shutong.ACC.18
1.1.3. 日志输出点
对于每一个请求和应答都必须有输出。
1.1.4. 文件存放
存放目录: 必须存放在磁盘最大分区。比如/data/logs/服务名称/日志文件名称,示例:
/data/logs/shutong/shutong.ACC.20130819.0
1.1.5. 文件大小
单个日志文件建议50M~~100M之间。
1.1.6. 日志分析脚本
需要提供日志分析脚本,能方便的提取日志内容,定位分析,统计分析。
1.2. 应用日志文件
日志主要为业务应用提供业务流程的支持,需要完整的输出一个业务的多个关键流程节点信息,确保能通过查阅该日志,了解每个业务交互的具体情况,理清业务各子流程。
1.2.1. 文件命名
访问日志文件命名为
服务名称.APP.时间.索引。
比如进程 shutong 的几个日志文件命名是:
shutong.APP.20130819.0
shutong.APP.20130819.15
下面文件的 12 是索引,表示文件是12:14分产生。
shutong.APP.20130819.12-14
1.2.2. 应用日志格式
发生时间
日志级别(DEBUG,INFO,WARN,ERROR,FATAL)
日志输出标记
线程标识
文件名称(DEBUG日志需要,非DEBUG日志可以为空)
文件行号(DEBUG日志需要,非DEBUG日志可以为空)
函数名称(DEBUG日志需要,非DEBUG日志可以为空)
日志描述
订单或者消息编号
需要更多字段只能增加到后面,字段内容之间采用|分开,如果输出内容之间包含有|,将|转义为#后输出.
1.2.3. 日志输出示例
2013-09-04 10:46:59.011.000|INFO |APPfilelogger.APP[2]|5592||||This is a APP message|ORDERID_2013090412121200001
2013-09-04 10:46:59.011.000|DEBUG|APPfilelogger.APP[2]|5592|f:\work\mytest\log4cplus_test\log4cplus_test\log4cplus_test.cpp|41|printDebug|This is a APP message|MSGID_2013090412121200002
2013-09-04 10:46:59.011.000|ERROR|APPfilelogger.APP[2]|5592|f:\work\mytest\log4cplus_test\log4cplus_test\log4cplus_test.cpp|42|printDebug|This is a APP message|MSGID_2013090412121200003
2013-09-04 10:46:59.011.000|DEBUG|APPfilelogger.APP_DAILY[2]|5592|f:\work\mytest\log4cplus_test\log4cplus_test\log4cplus_test.cpp|43|printDebug|This is a APP message|MSGID_2013090412121200006
1.2.4. 文件存放
存放目录: 必须存放在磁盘最大分区。比如/data/logs/服务名称/日志文件名称,示例:
/data/logs/shutong/shutong.APP.20130819.0
1.2.5. 文件大小
单个日志文件建议50M~~100M之间。
1.2.6. 日志分析脚本
需要提供日志分析脚本,能方便的提取日志内容,定位分析,统计分析。
1.3. 系统日志文件
系统日志主要是为了记录系统运行的情况,比如消息队列当前的消息数目;还有就是为了调试方便,可以比较详细的输出交互的多个步骤,便于定位问题。
1.3.1. 文件命名
访问日志文件命名为
服务名称.SYS.时间.索引。
比如进程 shutong 的几个日志文件命名是:
shutong.SYS.20130819.0
shutong.SYS.20130819.15
1.3.2. 日志格式
发生时间
日志级别(DEBUG,INFO,WARN,ERROR,FATAL)
日志输出标记
线程标识
文件名称(DEBUG日志需要,非DEBUG日志可以为空)
文件行号(DEBUG日志需要,非DEBUG日志可以为空)
函数名称(DEBUG日志需要,非DEBUG日志可以为空)
日志描述
需要更多字段只能增加到后面,字段内容之间采用|分开,如果输出内容之间包含有|,将|转义为#后输出.
1.3.3. 日志输出示例
2013-09-04 10:49:20.296.000|INFO |SYSfilelogger.SYS[2]|5496||||This is a SYS message
2013-09-04 10:49:20.296.000|DEBUG|SYSfilelogger.SYS[2]|5496|f:\work\mytest\log4cplus_test\log4cplus_test\log4cplus_test.cpp|47|printDebug|This is a SYS message
2013-09-04 10:49:20.296.000|ERROR|SYSfilelogger.SYS[2]|5496|f:\work\mytest\log4cplus_test\log4cplus_test\log4cplus_test.cpp|48|printDebug|This is a SYS message
2013-09-04 10:49:20.296.000|DEBUG|SYSfilelogger.SYS[2]|5496|f:\work\mytest\log4cplus_test\log4cplus_test\log4cplus_test.cpp|49|printDebug|This is a SYS message
1.3.4. 文件存放
存放目录: 必须存放在磁盘最大分区。比如/data/logs/服务名称/日志文件名称,示例:
/data/logs/shutong/shutong.SYS.20130819.0
1.3.5. 文件大小
单个日志文件建议50M~~100M之间。
1.4. 日志备份机制
必须先对当天日志进行压缩,再做磁带备份,生产机上保留最近5~10个以上工作日的日志备份。
1.5. 日志内容规范
对于“敏感”的单位信息,如名称、余额等信息,禁止使用debug以上级别的日志方法记录,在开发过程中,也应减少日志对该类信息的记录。一些敏感信息可以打马赛克后输出,比如比方字符串部分内容换成*。如:身份证号 422927198806031234,可以考虑这样输出: 42292719880*****34。
对于特别敏感的交易信息,不能输出到日志文件。所有的异常(Exception)都必须写在日志中,当系统抛出异常时,必须使用log.error()记录定制信息外。
1.5. 特别敏感信息定义
密码:用户登录,交易等一切密码信息;
2. 日志信息级别规范
日志信息输出的优先级从高到低至少应分为五档,分别是Fatal、ERROR、WARN、INFO、DEBUG。这些级别用来指定这条日志信息的重要程度。在测试阶段可以打开所有级别的日志,系统上线后,建议只输出INFO以上级别(含INFO)。各级别的日志信息作用规定如下:
2.1. 致命(Fatal)
严重的错误,系统无法正常运行,如硬盘空间满等。这个级别很少被用,常暗含系统或者系统的组件迫近崩溃。
2.2. 错误(Error)
系统可以继续运行,但最好要尽快修复的错误。这个级别用的较多,常常伴随Java异常,错误(Error)的环境不一定会造成系统的崩溃,系统可以继续服务接下来的请求。
2.3. 警告(Warn)
系统可以正常运行,但需要引起注意的警告信息。这个级别预示较小的问题,由系统外部的因素造成的,比如用户输入了不符合条件的参数。
2.4. 信息(Info)
系统运行的主要关键时点的操作信息,一般用于记录业务日志。但同时,也应该有足够的信息以保证可以记录再现缺陷的路径。这个级别记录了系统日常运转中有意义的事件。
2.5. 调试(Debug)
系统运行中的调试信息,便于开发人员进行错误分析和修正,一般用于程序日志,关心程序操作(细粒度),不太关心业务操作(粗粒度)。系统出现问题时,必须抛出异常,在处理异常时记录日志,且日志级别必须是前三个级别(Fatal\Error\Warning)中的一种。
Log4cplus实现方式
3.1. Log4cplus 来源
来自开源项目 logging,项目地址位于:
http://log4cplus.sourceforge.net
https://sourceforge.net/news/?group_id=40830
3.2. 版本
目前使用比较新的版本 log4cplus(1.1.X)
3.3. 配置文件
使用配置文件 urconfig.properties 控制log 的输出。文件配置如下。
#全局默认根 logger,这里忽略
#log4cplus.rootLogger=TRACE, ALL_MSGS, TRACE_MSGS, DEBUG_INFO_MSGS, FATAL_MSGS
#log4cplus.rootLogger=TRACE,ALL_MSGS
#log4cplus.appender.ALL_MSGS=log4cplus::RollingFileAppender
#log4cplus.appender.ALL_MSGS.File=./logout/all_msgs.log
#log4cplus.appender.ALL_MSGS.layout=log4cplus::TTCCLayout
#独立的 logger 的配置语法,支持两个 appender
log4cplus.logger.APPfilelogger = TRACE,APP,APP_DAILY
og4cplus.additivity.APPfilelogger = false
#独立的 logger 的配置语法,同一个 logger 下会发送到所有文件,
#是否写入到所有文件,通过 LogLevel 来控制
log4cplus.logger.SYSfilelogger = TRACE,SYS
#log4cplus.additivity.SYSfilelogger = TRUE
#独立的 logger 的配置语法
log4cplus.logger.ACCfilelogger = TRACE,ACC
#log4cplus.additivity.ACCfilelogger = TRUE
#支持只写入同一个 logger 下的指定文件
log4cplus.appender.APP=log4cplus::RollingFileAppender
log4cplus.appender.APP.File=./logout/app_msgs.log
log4cplus.appender.APP.ImmediateFlush=false
log4cplus.appender.APP.MaxFileSize=1MB
#log4cplus.appender.APP.MinFileSize=1M
log4cplus.appender.APP.MaxBackupIndex=3
log4cplus.appender.APP.layout=log4cplus::PatternLayout
log4cplus.appender.APP.layout.ConversionPattern=%D{%Y-%m-%d %H:%M:%S.%Q}|%-5p|%c[2]|%t|%m%n
log4cplus.appender.APP.filters.1=log4cplus::spi::LogLevelRangeFilter
log4cplus.appender.APP.filters.1.LogLevelMin=TRACE
log4cplus.appender.APP.filters.1.LogLevelMax=FATAL
#支持只写入同一个 logger 下的指定文件
log4cplus.appender.APP_DAILY=log4cplus::DailyRollingFileAppender
log4cplus.appender.APP_DAILY.File=./logout/app_msgs_d.log
#MONTHLY,WEEKLY,DAILY,TWICE_DAILY,HOURLY,MINUTELY
log4cplus.appender.APP_DAILY.Schedule=MINUTELY
log4cplus.appender.APP_DAILY.DatePattern='.'yyyy-MM-dd
log4cplus.appender.APP_DAILY.ImmediateFlush=false
log4cplus.appender.APP_DAILY.MaxBackupIndex=3
log4cplus.appender.APP_DAILY.layout=log4cplus::PatternLayout
log4cplus.appender.APP_DAILY.layout.ConversionPattern==%D{%Y-%m-%d %H:%M:%S.%Q}|%-5p|%c[2]|%t|%m%n
log4cplus.appender.APP_DAILY.filters.1=log4cplus::spi::LogLevelRangeFilter
log4cplus.appender.APP_DAILY.filters.1.LogLevelMin=TARCE
log4cplus.appender.APP_DAILY.filters.1.LogLevelMax=FATAL
#支持只写入同一个 logger 下的指定文件
log4cplus.appender.SYS=log4cplus::RollingFileAppender
log4cplus.appender.SYS.File=./logout/sys_msgs.log
log4cplus.appender.SYS.MaxFileSize=1MB
log4cplus.appender.SYS.MaxBackupIndex=3
log4cplus.appender.SYS.ImmediateFlush=false
log4cplus.appender.SYS.layout=log4cplus::PatternLayout
log4cplus.appender.SYS.layout.ConversionPattern=%D{%Y-%m-%d %H:%M:%S.%Q}|%-5p|%c[2]|%t|%m%n
log4cplus.appender.SYS.filters.1=log4cplus::spi::LogLevelRangeFilter
log4cplus.appender.SYS.filters.1.LogLevelMin=TRACE
log4cplus.appender.SYS.filters.1.LogLevelMax=FATAL
#支持只写入同一个 logger 下的指定文件
log4cplus.appender.ACC=log4cplus::RollingFileAppender
log4cplus.appender.ACC.File=./logout/acc_msgs.log
log4cplus.appender.ACC.MaxFileSize=1MB
log4cplus.appender.ACC.MaxBackupIndex=3
log4cplus.appender.ACC.ImmediateFlush=false
log4cplus.appender.ACC.layout=log4cplus::PatternLayout
log4cplus.appender.ACC.layout.ConversionPattern=%D{%Y-%m-%d %H:%M:%S.%Q}|%-5p|%c[2]|%t|%m%n
log4cplus.appender.ACC.filters.1=log4cplus::spi::LogLevelRangeFilter
log4cplus.appender.ACC.filters.1.LogLevelMin=TRACE
log4cplus.appender.ACC.filters.1.LogLevelMax=FATAL
3.4. 代码实现
此处略去。