应用日志实践准则

1 日志级别概述

ERROR
ERROR是最高级别错误,反映系统发生了非常严重的故障,无法自动恢复到正常态工作,需要人工介入处理。系统需要将错误相关痕迹以及错误细节记录ERROR日志中,方便后续人工回溯解决。

WARN
WARN是稍微低级别异常日志,反映系统在业务处理时触发了异常流程,但系统可恢复到正常态,下一次业务可以正常执行。但WARN级别问题需要开发人员给予足够关注,往往表示有参数校验问题或者程序逻辑缺陷,当功能逻辑走入异常逻辑时,应该考虑记录WARN日志。

INFO
INFO日志主要记录系统关键信息,旨在保留系统正常工作期间关键运行指标,可以将初始化系统配置、业务状态变化信息,或者用户业务流程中的核心处理记录到INFO日志中,方便日常运维工作以及错误回溯时上下文场景复现。

DEBUG
DEBUG日志是INFO日志的好帮手,开发人员可以将各类详细信息记录到DEBUG里,起到调试的作用,包括参数信息,调试细节信息,返回值信息等等。其他等级不方便显示的信息都可以通过DEBUG日志来记录。

2 记录日志的时机

2.1 异常

捕获的异常是系统告知开发人员需要加以关注的,应当适当记录日志,根据实际结合业务的情况使用warn或者error级别

2.2 业务流程预期不符

结果与期望不符时也是日志场景之一,简单来说所有流程分支都可以加入考虑。取决于开发人员判断能否容忍情形发生。常见的合适场景包括外部参数不正确

2.3 系统核心组件关键动作

系统中核心角色触发的业务动作是需要多加关注的,是衡量系统正常运行的重要指标,建议记录INFO级别日志,比如电商系统用户从登录到下单的整个流程;微服务各服务节点交互;核心数据表增删改;核心组件运行等等

2.4系统初始化

系统或者服务的启动参数。核心模块或者组件初始化过程中往往依赖一些关键配置,根据参数不同会提供不一样的服务

不同级别的使用

ERROR

错误日志。级别比较高,如果发生一些异常,并且任何时候都需要打印时使用。
1. 打开配置文件失败
2. 所有第三方对接的异常(包括第三方返回错误码)
3. 所有影响功能使用的异常,包括:SQLException和除了业务异常之外的所有异常(RuntimeException和Exception)

PS1

如果有Throwable信息,需要记录完成的堆栈信息:

log.error("获取用户[{}]的用户信息时出错",userName,e);
PS2

如果进行了抛出异常操作,请不要记录error日志,由最终处理方进行处理

//反例(不要这么做)
try{
    ....
}catch(Exception ex){
  String errorMessage=String.format("Error while reading information of user [%s]",userName);
  logger.error(errorMessage,ex);
  throw new UserServiceException(errorMessage,ex);
}

WARN

不应该出现但是不影响程序、当前请求正常运行的异常情况

  1. 有容错机制的时候出现的错误情况
  2. 找不到配置文件,但是系统能自动创建配置文件
  3. 即将接近临界值的时候

INFO

系统运行信息

  1. Service方法中对于系统/业务状态的变更
  2. 主要逻辑中的分步骤
  3. 调用第三方时的调用参数和调用结果

DEBUG

  1. 可以填写所有的想知道的相关信息(但不代表可以随便写,debug信息要有意义,最好有相关参数)
  2. 生产环境需要关闭DEBUG信息
  3. 如果在生产情况下需要开启DEBUG,需要使用开关进行管理,不能一直开启。

3 日志内容

时间
包含时区信息和毫秒,这个工作往往日志框架足以支持。核心属性之一。

日志级别
例如 debug、info 以及warn、error

会话标识
能知道是哪个客户端或者是哪个用户触发,登陆账号,seesion信息等

功能标识
功能标识的意义在于方便日志搜索,跟踪指定功能的完整轨迹,是INFO,DEBUG日志的常见技巧。跟logger分类同一道理,更细分功能标识则是方法标识,更多使用在DEBUG做在线调试使用。

精炼的内容
内容永远是日志的核心,结合上述使用场景,简单来说包括场景信息(谁,什么功能等),状态信息(开始,中断,结束)以及重要参数.

其他信息
其他可能的有用信息包括:版本号,线程号等等。

4 日志格式

log.debug("[接口名或操作名] what/how, params");
log.info("[接口名或操作名] what/how, params");
log.warn("[接口名或操作名] [Some Error Msg] happens, params");
log.error("[接口名或操作名] [Some Error Msg] happens, [Probably Because] [Probably need to do], params");

5规范

Logger实例
应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架SLF4J中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

private static final Logger logger = LoggerFactory.getLogger(Abc.class);

占位符的方式
logger.debug(“Processing trade with id: ” + id + ” symbol: ” + symbol); 如果日志级别是warn,上述日志不会打印,但是会执行字符串拼接操作,如果symbol是对象,会执行toString()方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。

logger.debug("Processing trade with id: {} symbol : {} ", id, symbol);  

避免重复打印日志
additivity默认为true,即通过该logger输出的日志会同时输出到root logger,如果还为该logger指定了独立的appender,就会导致这部分日志重复输出

避免重复打印日志,浪费磁盘空间,务必在配置中设置additivity=false。

案发现场信息和异常堆栈信息
异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么通过关键字throws往上抛出。

记录异常日志的常见错误:

        logger.error(e);
        logger.error(e.getMessage());
        logger.error("上下文"+e.getMessage());        

上面这几种都是错的!请确保使用的是两个入参的API,如error(String s, Throwable t)

logger.error(各类参数或者对象toString + "_" + e.getMessage(), e);  

记录日志又抛异常
不允许记录日志后又抛出异常,因为这样会多次记录日志,只允许记录一次日志。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值