DEBUG 级别: 记录调试程序相关的信息.
INFO 级别: 记录程序正常运行有意义的信息.
WARN 级别: 记录可能会出现潜在错误的信息.
ERROR 级别: 记录当前程序出错的信息, 需要被关注处理.
Fatal 级别: 表示出现了严重错误, 程序将会中断执行.
建议在项目中使用这四种级别, ERROR,WARN,INFO ,DEBUG.
正确姿势
1, 提前判断日志级别
- // 条件判断
- if(logger.isDebugEnabled){
- logger.debug("server info , id :" + id + ", user :" + user);
- }
- // 使用占位符
- logger.debug("server info , id : {}, user : {}",id,user);
对于 DEBUG,INFO 级别的日志, 在我们的程序中是比较高频的存在, 当我们的项目大了, 日志变多了, 这时候为了程序运行的效率, 我们必须以条件判断或者占位符的方式来打印日志. 为什么呢? 假如我们项目中配置的日志级别为 WARN, 那么对于我们下面的日志输出语句'logger.debug("server info , id : "+ id +", user : "+ user);', 虽然该日志不会被打印, 但是却会执行字符串拼接的操作, 这里我们的 user 是一个实例对象, 所以还会执行 toString 方法, 这样就白白浪费了不少系统的资源.
2, 避免多余日志输出
在我们的生产环境中, 一般禁止 DEBUG 日志的输出, 其打印的频率是非常高的, 容易对正常运行的程序造成严重的影响, 在我们最近的项目中就有遇到过类似的情况.
那么这时候该学会使用 additivity 属性
在这边配置成 true 的话, 也就是默认的情况, 这时候当前 Logger 会继承父 Logger 的 Appender, 说白了就是当前日志的输出除了输出在当前日志文件以外, 还会输出至父文件里. 所以一般情况下, 我们为了避免重复打印, 会将这个参数设置成 false, 以减少不必要的输出.
3, 保证日志记录信息完整
在我们的代码中, 日志记录的内容要包含异常的堆栈, 请勿随意输出 "XX 出错" 等简单的日志, 这对于错误的调试毫无帮助. 所以我们在记录异常的时候一定要带上堆栈信息, 例如
logger.error("rabbitmq consumer error,cause :"+e.getMessage(),e);
切记在输出对象实例的时候, 须确保对象重写了 toString 方法, 否则只会输出其 hashCode 值.
4, 定义 logger 变量为 static
private static final Logger logger = LoggerFactory.getLogger(XX.class);
确保一个对象只使用一个 Logger 对象, 避免每次都重新创建, 否则可能会导致 OOM.
5, 正确使用日志级别
- try{
- //..
- }catch(xx){
- logger.info(..);
- }
这样一来, 本来是 ERROR 的信息, 全都打印在 INFO 日志文件里了, 不知情的同事还会在死盯着错误日志, 而且还找不出问题, 多影响工作效率是吧?
6, 推荐使用 slf4j+logback 组合
logback 库里自身就已经实现了 slf4j 的接口, 就无需引入多余的适配器了, 而且 logback 也具有更多的优点, 建议新项目可以使用这个组合. 还有一点需要注意, 当引入 slf4j 后, 要注意其实际使用的日志库是否是由我们引入的, 也有可能会使用了我们第三方依赖包所带入的日志库, 这样就可能会导致我们的日志失效.
7, 日志的聚合分析
日志的聚合可以把位于不同服务器之间的日志统一起来分析处理, 如今 ELK 技术栈亦或者的 EFG(Fluentd+Elasticsearch+grafana) 等都是一些比较成熟的开源解决方案.
拿 ELK 来说, 可以在我们的服务器上直接通过 logstash 来读取应用打印的日志文件, 或者也可以在我们项目中的日志配置文件里配置好相关的 socket 信息, 打印的时候直接把日志信息输出至 logstash. 再交由 Elasticsearch 存储, kibana 展示.
结语
好了, 关于日志先聊这么多~ 大家有需要补充或者交流的可以在下方留言哦.
------------------------------------------------------
来源: https://www.2cto.com/kf/201904/805008.html