我在M2公司做架构之日志管理

一、日志管理的重要性

日志是程序设计中很重要的一部分,它提供了丰富的程序运行时的信息,例如:程序运行时的逻辑信息、错误信息、事件描述信息、关键数据、状态信息、执行时间和用户登录信息等,这些信息可以帮助开发人员快速地发现和定位问题。在实际生产环境中,日志是查找问题的重要来源,良好的日志格式和记录方式可以帮助开发人员、应急人员快速定位到错误的根源,并找到解决问题的办法。

二、日志框架的选型

  • JDK Logger;
  • Apache Commons Logging;
  • Apache Log4j;
  • Slf4j;
  • Logback;
  • Apache Log4j 2。

而我们采用的是Logback。

三、日志系统的优化和最佳实践

1.开发人员的日志意识

  • 开发代码时要有意识地设想代码出现问题的场景,针对出问题的场景记录关键的程序运行的信息,这样在代码出现问题时才能通过日志恢复程序运行的过程,才容易定位问题。
  • 打印日志时必须包含环境信息,环境信息是指在打印可获得的帮助开发人员定位问题的信息,例如:用户ID、角色、参数、返回值、逻辑判断结果、循环次数、异常信息等。
  • 对异常等错误信息必须打印错误级别及以上级别的日志,对线上日志要定期检查,没有异常日志产生的服务才是健康的服务。
  • 生产环境将关闭的日志必须在打印日志前进行判断,以此来提高执行效率。
  • 必须使用占位符的方式代替字符串连接,这样程序更加简洁,并且性能有所提高。
  • 对关键业务步骤必须打点并记录耗时和结果等信息。

2.日志级别的设置

通常来说线上应用使用info级别就够了,但是刚刚交付的项目或服务质量还不稳定,换言之,还有一定数量的bug存在,如果使用info级别,则出现问题很难定位,因此没有一个完美的答案,下面是最佳实践(可供参考):

  • QA环境可以使用debug及以下级别的日志。
  • 刚刚上线的应用还没有到稳定期,使用debug级别的日志。
  • 上线后稳定的应用,使用info级别的日志。
  • 常年不出现问题的应用使用error级别的日志。

对于不同的情况应该使用的日志级别如下:

  • 使用trace级别的日志输出最细粒度的信息事件,通过这些信息可以跟踪程序执行的任一步骤。
  • 使用debug级别的日志输出细粒度的信息事件,这些信息对调试应用程序非常有用。
  • 使用info级别的日志输出粗粒度的信息事件,突出强调应用程序运行的关键逻辑和过程。
  • 使用warn级别的日志输出可能出现的错误,或者输出潜在发生错误的环境信息,或者打印用户输入的非法信息。
  • 使用error级别的输出错误事件,但仍然不影响系统的继续运行,在Java程序中发生异常一定要记录error日志,并且打印异常堆栈。异常在封装后抛出时一定要保留根源异常和错误信息,构成异常树,因为在解决线上问题时,日志中的异常堆栈和异常信息都是非常重要的线索。
  • fatal级别代表严重的错误事件,将会导致应用程序的退出。

3.日志的数量和大小

首先,我们一定要控制日志的输出量,避免由于业务上量而导致服务器磁盘占满并大量地输出无用的日志,这不利于系统性能的提升,也不利于快速定位错误点。

我们写程序时,要清晰地了解程序中的哦哪一处会发生问题,以及发生问题时打印哪些日志可以帮助定位这些问题,这样打印出来的日志才最有效。因此,我们只需打印关键的信息,不要随便把对象JSON序列化后打印出来。如果要打印对象列表,则使用JSON格式打印会占用很大空间。

4.logback.xml(参考模板)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?xml version="1.0" encoding="UTF-8"?>

<configuration scan="true" scanPeriod="60 seconds" debug="false">

<!-- 日志存放路径 -->

<property name="log.path" value="/home/tech/log/xx"/>

<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>

<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>



<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->

<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">

<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 指定打印SQL -->
<logger name="com.xx.dao" level="debug"/>
<!-- 系统模块日志级别控制 -->
<logger name="com.xx" level="info"/>
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn"/>

<root level="info">
<appender-ref ref="console"/>
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info"/>
<appender-ref ref="file_error"/>
</root>
</configuration>

四、总结

上述大部分内容来自《分布式服务架构:原理、设计与实战》,而这些内容都在我主要负责的公司分布式架构体系中实践着。

文章目录
  1. 一、日志管理的重要性
  2. 二、日志框架的选型
  3. 三、日志系统的优化和最佳实践
    1. 1.开发人员的日志意识
    2. 2.日志级别的设置
    3. 3.日志的数量和大小
    4. 4.logback.xml(参考模板)
  4. 四、总结