服务器端日志规约和实践

一、日志级别

ALL、TRACE、DEBUG、INFO、WARN、ERROR、FATAL、OFF

从左至右日志输出由多到少。

生产环境使用INFO日志级别,调试时可以设置为DEBUG级别。

针对Spring Boot的程序,使用配置中的logging.level.root控制默认日志级别。

启动时可以使用logging.level.root参数做临时设置。例如:

java -jar app.jar --logging.level.root=debug

二、日志分类

  1. 监控日志

监控系统内关键点的动作,DEBUG级别可做打点使用,ERROR级别记录程序异常。

  1. 业务日志

系统内业务操作日志输出,例如:下单、支付、后台上下架商品等重要的操作。

  1. 统计日志

根据统计需要,对用户操作进行记录,例如:登录、注册、浏览商品等。

三、日志的触发点和级别

  1. 监控日志
触发点 日志级别 例子
关键方法入口 DEBUG 记录参数
调用外部服务 DEBUG REST API调用返回数据
耗时和资源占用高的方法 DEBUG 记录处理时间、记录资源消耗
定时任务启动和结束 DEBUG 启动时间及状态、结束时间及状态
容错及恢复 DEBUG 用户目录不存在,重新建立用户目录
可处置的操作异常 WARN 用户登录失败
无法处置的程序异常 ERROR logger.error(各类参数或者对象 toString + "_" + e.getMessage(), e);
主程序启动和关闭 DEBUG 启动时间及状态、结束时间及状态
重要配置或环境变量 DEBUG 配置,环境变量
  1. 业务日志
触发点 日志级别 例子
业务操作执行后 INFO 关键业务操作记录执行结果,执行人
  1. 统计日志
触发点 日志级别 例子
需要进行统计的操作 INFO 记录用户访问信息,IP、耗时、下载量;记录资源用量信息

四、日志收集方式

1. Fluentd

将日志发送到远程日志中心,由Fluentd进行收集,Elasticsearch存储,Kibana展示。

附logback配置文件片段。
logger monitor/business/stats 分别对应 监控/业务/统计日志


    ${fluentTag}
    ${fluentHost}
    ${fluentPort}
    ${logPath}
    
        
    


    
    


    


    

2. 控制台

监控日志还可以输出到控制台。


    
        %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
    

3.文件

重要的日志可以输出到文件作为备份。

可以设置保存文件个数和磁盘占用总容量限制。


    ${logPath}/business.log
    
        
        ${logPath}/business.%d{yyyy-MM-dd-HH}.log
        
        30
        3GB
    
    
        %date %level [%thread] %logger{10} [%file:%line] %msg%n
    

五、记录日志

参考阿里巴巴Java开发手册

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger monitorLogger = LoggerFactory.getLogger("monitor");
private static final Logger businessLogger = LoggerFactory.getLogger("business");
private static final Logger statsLogger = LoggerFactory.getLogger("stats");

接下来按照 三、日志的触发点和级别 的说明,在程序中记录日志。

注意点:

  1. 使用占位符而不是字符串拼接

参考阿里巴巴Java开发手册

说明:logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
    如果日志级别是 warn,上述日志不会打印,但是会执行字符串拼接操作,如果 symbol 是对象, 会执行 toString()方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。 
正例:(条件) 
if (logger.isDebugEnabled()) {
    logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
}     
正例:(占位符)
logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);
  1. 异常输出适当的日志

捕获不可控的异常,应该输出现场信息和异常堆栈信息,不要将异常再抛至上层,避免上层再次输出。

日志例:

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

异常堆栈信息是多行,在Kibana中会出现多条,不便于查看。建议在Fluent中添加合并插件,将异常堆栈信息合并为一行再输出到Elasticsearch。

你可能感兴趣的:(服务器端日志规约和实践)