03 日志规约
【强制】 应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架(SLF4J、JCL—Jakarta Commons Logging)中的 API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
说明
日志框架(SLF4J、JCL--Jakarta Commons Logging)的使用方式(推荐使用 SLF4J)
使用 SLF4J:
javaimport org.slf4j.Logger; import org.slf4j.LoggerFactory; private static final Logger logger = LoggerFactory.getLogger(Test.class);使用 JCL:
javaimport org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; private static final Log log = LogFactory.getLog(Test.class);
【强制】 日志文件至少保存 15 天,因为有些异常具备以“周”为频次发生的特点。当天日志保存为
{应用名}.log,存放在{统一目录}/{应用名}/logs/目录下,过往日志格式为{logname}.log.{保存日期},日期格式:yyyy-MM-dd。正例
以 mppserver 应用为例,日志保存为
/home/admin/mppserver/logs/mppserver.log,历史日志名称为mppserver.log.2021-11-28。【强制】 根据国家法律,网络运行状态、网络安全事件、个人敏感信息操作等相关记录的日志应至少留存六个月,并进行网络多机备份。
【强制】 应用中的扩展日志(如打点、临时监控、访问日志等)的命名方式应为:
appName_logType_logName.log。- logType:日志类型,如 stats / monitor / access 等;
- logName:日志描述。
这种命名的好处:通过文件名就可知道日志文件属于什么应用,什么类型,什么目的,也有利于归类查找。
说明
推荐对日志进行分类,将错误日志和业务日志分开放,便于开发人员查看,也便于通过日志对系统进行及时监控。
正例
mppserver 应用中单独监控时区转换异常,日志命名为
mppserver_monitor_timeZoneConvert.log。【强制】 日志输出时,字符串变量之间的拼接应使用占位符的方式。
说明
字符串拼接会使用
StringBuilder的append()方法,有一定的性能损耗。而占位符替换仅是替换动作,可以有效提升性能。正例
javalogger.debug("Processing trade with id : {} and symbol : {}", id, symbol);【强制】 对于
trace、debug、info级别的日志输出,必须进行日志级别的开关判断。说明
虽然在 debug(参数) 的方法体内第一行代码
isDisabled(Level.DEBUG_INT)为真时(Slf4j 的常见实现 Log4j 和 Logback),就直接 return,但是参数可能会进行字符串拼接运算。此外,如果debug(getName())这种参数内有getName()方法调用,无谓浪费方法调用的开销。正例
java// 如果判断为真,那么可以输出 trace 和 debug 级别的日志 if (logger.isDebugEnabled()) { logger.debug("Current ID is: {} and name is: {}", id, getName()); }【强制】 避免重复打印日志,浪费磁盘空间,务必在日志配置文件中设置
additivity=false。正例
xml<logger name="com.taobao.dubbo.config" additivity="false">【强制】 生产环境禁止使用
System.out或System.err输出日志,或使用e.printStackTrace()打印异常堆栈。说明
标准日志输出与标准错误输出文件仅在 JBoss 重启时滚动,如果大量输出至这两个文件,容易造成文件大小超过操作系统大小限制。
【强制】 异常信息应包括两类信息:案发现场信息和异常堆栈信息。如果不处理异常,应通过关键字
throws往上抛出。正例
javalogger.error("inputParams: {} and errorMessage: {}", 各类参数或者对象 toString(), e.getMessage(), e);【强制】 日志打印时禁止直接使用 JSON 工具将对象转换为
String。说明
如果对象里某些
get方法被覆写,存在抛出异常的情况,则可能会因为打印日志而影响正常业务流程的执行。正例
打印日志时仅打印业务相关属性值或调用对象的
toString()方法。【推荐】 谨慎记录日志。生产环境禁止输出
debug日志;有选择地输出info日志;如使用warn记录刚上线时的业务行为信息,应注意日志输出量,避免服务器磁盘撑爆,并及时删除这些观察日志。说明
大量输出无效日志不利于系统性能提升,也不利于快速定位错误。记录日志时请思考:这些日志是否有实际意义?看到这条日志能做什么?是否有助于问题排查?
【推荐】 可使用
warn日志级别记录用户输入参数错误的情况,避免用户投诉时无所适从。如非必要,请勿在此场景下打出error级别日志,以避免频繁报警。说明
注意日志输出的级别,
error级别仅记录系统逻辑出错、异常或重要错误信息。【推荐】 尽量使用英文描述日志错误信息;如英文描述不清楚则使用中文,否则容易产生歧义。
说明
国际化团队或海外部署的服务器可能因字符集问题,建议使用英文注释和描述日志错误信息。
【推荐】 为保护用户隐私,日志文件中的用户敏感信息应进行脱敏处理。
说明
在日志排查问题时,推荐使用订单号、UUID 之类的唯一编号进行查询。