实际开发中常常遇到很多开发人员不知道如何输出日志,在此总结了阿里的日志规范和项目中的一些经验总结,希望能帮助大家更好的书写日志。
应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架SLF4J 中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(xxx.class);
对trace/debug/info 级别的日志输出,必须使用条件输出形式或者使用占位符的方式。
说明:logger.debug("Processing trade with id: " + id + " symbol: " + symbol);如果日志级别是warn,上述日志不会打印,但是会执行字符串拼接操作,如果symbol 是对象,会执行toString()方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。
正例:(条件)
if (logger.isDebugEnabled()) {
logger.debug("Processing trade with id: " + id + " symbol: " + symbol);
}
正例:(占位符)
logger.debug("Processing trade with id: {} symbol : {} ", id, symbol);
避免重复打印日志,浪费磁盘空间,务必在xml 中设置 additivity=false
异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么往上抛。
正例:logger.error(各类参数或者对象 toString + “_” + e.getMessage(), e);
【推荐】可以使用warn 日志级别来记录用户输入参数错误的情况,避免用户投诉时,无所适从。注意日志输出的级别,error 级别只记录系统逻辑出错、异常等重要的错误信息。如非必要,请不要在此场景打出 error 级别。
【推荐】谨慎地记录日志。生产环境禁止输出 debug 日志;有选择地输出 info 日志;如果使用 warn 来记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘撑爆,并记得及时删除这些观察日志。
说明:大量地输出无效日志,不利于系统性能提升,也不利于快速定位错误点。记录日志时请
开发人员如何选择日志级别
DEBUG级别的日志应该是能帮助开发人员分析定位bug所在的位置。
INFO级别的日志应该是能帮助测试人员判断这是否是一个真正的bug,而不是自己操作失误造成的。
- 1.程序入口,这能让开发人员确认参数是否为自己所为。
- 2.计算结果,测试关心的程序的输出结果是否符合预期,那么对于计算过程不应该关心,仅给出计算结果就能判断是否符合预期。
WARN级别称之为“警告”,告警日志,可以选择忽略也可以选择重视。
- 1.某个不常走到的分支,对于常规的操作是不应该打印WARN日志的,只有在满足某个条件才能走到的分支,且这个分支引起了“警觉”,此时就应该打印WARN日志。
- 2.使用WARN日志级别来记录用户输入参数错误的情况,避免用户投诉时,无所适从。
- 3.系统异常情况,例如方法执行较慢可能影响系统正常运行时,可以通过aop切面将运行慢的方法输出到 WARN日志中。
ERROR级别称之为“错误”,这个含义就更明显了,就是系统出现了错误,需要处理。最为常见的就是捕获异常时所打印的日志,通常需要正确区分异常类型。
- 1.毫无疑问出现错误,程序不能继续运行下去就应该打印ERROR日志,这个错误并不是业务上的错误。 一般常用于中间件故障程序不能继续运行,客户化业务异常不影响系统继续运行的请使用WARN日志。
- 2.异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么通过关键字throws往上抛出。
批量日志
应用系统批量日志指批量流程中由应用记录的批量任务相关信息,可供事件处理系统采集分析。
批量日志中至少应包含但不限于如下内容:
- 批量名称、批量执行用户名、批量开始时间、批量结束时间、批量返回码。
- 作业步名称、作业步开始时间、作业步结束时间、作业返回码等。
- 对于存在文件生成或传输的批量步骤,需在批量日志中明确执行结果检查情况。
- 应用可侦知的批量前后应用系统日切完成情况及应用联机可用状态。
- 业务数据备份作为批量流程中重要部分,批量日志中应包含其执行情况。
批量日志应记录在系统的单独文件中。批量日志在每日/次批量开始时新建,不宜采用追加方式,以方便快速检索查询。批量日志文件命名格式原则上各应用系统应保持一致,应包含系统标识、执行日期、批次等唯一性信息,避免日志文件相互覆盖。
应用系统的批量日志信息应具有标准的结构,每条日志信息应使用结构化描述:
- 批量流程中每步骤时点记录信息应在一行内显示。
- 各项信息以统一的分隔符进行分隔,每行字符数不超过约定限制。
- 批量日志中代表成功或失败的关键字应保持一致。
- 批量过程中不能对批量日志文件中的内容进行覆盖、删除等操作。
意见
- 严格按照正确的日志级别输出日志信息,在生产环境禁止使用debug日志,不要在日志中输出大对象文件,大JSON文件,日志打印限制在1M以内
- 日志代码应遵守代码规范,也是Code review的主要组成部分,包含变量名定义,方法名等
- 使用链路追踪,比如前端web层使用sessionid或者requestId,后端服务层一些典型业务场景使用全局交易流水号等(Dapper模式)
- 禁止直接用JSON工具将对象转换成String,输出对象必须包含toString()方法