1.日志级别
log.error()
适用于出现系统异常、重要错误的场景
log.warn()
适用于不影响业务场景的异常场景,但是存在告警信息
log.info()
适用于业务重要的信息,便于信息查询跟踪定位排查等。(例如调用重要接口,便于与对方系统进行问题排查)
log.debug()
适用于开发调试阶段,快速问题定位,信息查询等。
如果日志不分级别或级别不合理,则定位问题时就无法快速有效地屏蔽大量低级别信息,给快速定位带来难度。
2.异常日志规范
使用slf4j日志组件时,logger.error(与log.warn)接受Throwable参数,以打印异常名和详细的堆栈信息(可能内部调用e.printStackTrace())。
但是需要注意适用规范:
1. log.error("good log:" ,e);
可以打印异常名和堆栈信息。
2.log.error("best log: {}", e);
可以打印异常名和堆栈信息。并且增加一个大括号推荐使用。
3.log.error("bad log:"+e);
仅打印异常名;c句打印异常消息字符串。同e.toString()。以空指针异常(Runtime异常)为例,打印"java.lang.NullPointerException"。
4.log.error("bad log:"+e.getMessage());
打印具体的异常类,以空指针异常(Runtime异常)为例,打印"null"(过于简陋)。
3.日志规范风格
使用slf4j日志组件打印变量时,建议使用”{}”占位符风格(C风格),而不是”+”拼接符(C++风格)。例如:
1 log.error("Country: {}, Province: {}, City: {}", ctry, prov, city); //占位符
2 log.error("Country: "+ctry+", Province:" +prov +", City: "+city); //拼接符
4.多余的DEBUG级别判断
使用slf4j日志组件以Debug级别打印时,debug()方法内部会调用isDebugEnabled()判断调试级别。因此,下述代码里的判断没有必要:
if(logger.isDebugEnabled()){
logger.debug("handleChanges end:{}:{}(ms) ", new Object[] {changes, useTime});
}
5.日志对象log对象的创建
方式一:使用lombok的@slf4j 注解。(推荐)
方式二:private final Logger logger = LoggerFactory.getLogger(xxx.getClass());
一般建议日志对象logger声明为private static final。声明为private可防止logger对象被其他类非法使用。声明为static可防止重复new出logger对象,造成资源浪费;还可以防止logger被序列化,造成安全风险。声明为final是因为在类的生命周期内无需变更logger。
6.日志打印建议
建议加上便于定位的信息,便于日志信息的定位跟踪。
对应调度、接口可以加上调度开始,结束的日志,容易定位。