本文概览介绍logback.xml配置中的logger、appender和root三个节点信息。

日志框架选择

目前常遇见的日志框架有log4j、logback、log4j 2。logback是为了优化log4j而生的,log4j2又在logback基础上做了优化。所以日志框架选型顺序为:log4j2 > logback > log4j。

1 Logback知识点概览

1. 如何使用Logback

(1)第一部分:配置lackback.xml文件,在xml中配置中配置如上三个节点<logger>、<appender>和<root>三种节点

(2) 第二部分:在程序中使用

  • 获取logger对象,定义一个static变量如下:
  • 使用定义的log对象的五个函数trace()、debug()、info()、warn()和errn()记录信息。

2.  级别理解

(1)日志记录器级别

  • 如何确定一个记录器的级别的规则? 每一个日志记录器必须有一个级别,如果没有配置,就寻找其父亲节点的级别,向上直至根 logger
  • 如何设置logger对象的级别?在logback.xml中对于<logger>的属性进行设置。

(2)信息级别获取

所有的日志信息在写入日志时,必须赋予一个级别。通过logger的trace()、debug()、info()、warn()和 error()五个方法。

(3)日志器记录日志的规则

只记录比logger对象级别高的日志

2 Logback.xml的节点说明

2.1 logger

1. 命名规则

如果 logger的名称带上一个点号后是另外一个 logger的名称的前缀,那么,前者就被称为后者的祖先。如果 logger与其后代 logger之间没有其他祖先,那么,前者就被称后者之父节点。 这个规则可以实现按模块保存日志。

2. 实践-按一个Class所属的package进行保存日志

(1)在logback.xml中,logger对象的名称,常常定义为一个包名,如下

(2)代码中

在包biz的类中或者子包的类中,进行如下定义一个logger对象,

此时这个log对象就是上面logback.xml中定义的logger对象的子节点,所以这个包下所有的类都可以共享logger对象中定义的appender。

2.2 appender

2.2.1 encoder格式配置

这里主要是<pattern>的模式,它的作用类似于C中printf()的作用,即:根据一定的格式输出一个字符串。

举例如下:

logger.info(“日志信息”)最终打印的日志信息如下

下面解析每一个参数

  • %d  和%date一样,结果举例如下: 2006-10-20 14:06:49,812
  • %level 日志级别
  • %thread  tomca的线程名字,如http-nio-8027-exec-119 ,其中8027是服务的端口号,119是线程标识线程池的线程index
  • %logger{5} ,打印logger对象的名字

untitled

  • %msg 输出logger对象记录的信息,如通过logger.info,logger.error等方法记录的信息。
  • %X{key}  MDC (mapped diagnostic context)中对应的key的值。
  • %n 输出一个回车符,进行分行。一般都是在一个日志末尾加上这个符号。

2.2.2 过滤器filter

1. 返回值

过滤器的返回值只能是ACCEPT、DENY和NEUTRAL的其中一个。

  • 如果返回DENY,那么记录事件立即被抛弃,不再经过剩余过滤器;
  • 如果返回NEUTRAL,那么有序列表里的下一个过滤器会接着处理记录事件;
  • 如果返回ACCEPT,那么记录事件被立即处理,不再经过剩余过滤器。

2. 过滤日志级别-logback自带过滤器

3. 自定义过滤器

2.2.3 rollingPollicy

参考:https://logback.qos.ch/manual/appenders.html

提供了两种滚动策略:基于大小和时间。分别对应如下两个策略类FixedWindowRollingPolicy和 TimeBasedRollingPolicy。

1、基于大小的策略

  参数解析:

  (1)minIndex和maxIndex

  如minIndex=1,maxIdex=3,表示值保留error.log.1~error.log.5五个文件,超过这个个数,就删除最老的数据

  (2)maxFileSize

如果值是5Mb,表示日志文件超过5Mb就会进行滚动。

2、基于时间

    解释参数:

   (1) fileNamePattern

常用分类格式有按日和按月

  •     按日分类,以天为单位进行滚动

  •     按月分类,以月为单位进行滚动

   (2) maxHistory:假设此时值为30,如果上面的filleNamePattern设置是按日分类,则表示30天;如果按月分类的,则此时就表示30个月了。如下是按月分类。

     <fileNamePattern>${LOG_HOME}/%d{yyyyMM}/error.log</fileNamePattern>

    (3)cleanHistoryOnStart:true表示每次启动时,会删除日志。默认是false,所以一般都是使用默认值

3、两种策略比较

对于基于大小的策略,都是在磁盘空间有限的情况下一种选择,如部署到docker容器中,虚拟机磁盘有限,所以一般使用这种策略。

对于时间策略,只要磁盘空间不是特别紧张,都建议使用这种策略。(最最常用的策略)

2.2.4 Appender叠加性

叠加性,就是一个记录器logger记录记录了一个信息,那么这个信息就会发送给此记录器logger绑定的所有Appender和此logger父亲祖先的所有Appender。

如对于一个com.baidu.logger记录器记录信息是。则会com,com.baidu,com.baidu.logger三个记录器的所有appender都会接受到消息。这种行为成为累积行为。可以设置logger的addivitity为false就可以了

在日志配置过程中,一般都把“additivity属性”设置为false。如下,否则所有日志都会重复让root中apenders重新输出一份。

2.3 root的配置

1. 配置root的作用

可以通过“继承”的作用来理解定义root作用:

  • 如果在logback.xml中没有找到匹配的<logger>,那么此时就使用<root>的配置,如对于如下

  • Appender的叠加性。自定义的Logger,会把当前日志信息传递给root。如果additivity属性设置为false,那么此时就不会传递了。
  • 自定义的Logger可以共享root的日志级别

2.  举例

2.4 property

1. 作用

类似于pom.xml中<property>,在<property>中可以定义一些变量的值,如下:

那么在定义其他节点时,就可以使用如下

2. 在<property>中使用properties文件中值,这是怎么实现的?通过读取系统的环境变量来实现。

3 日志规范

3.1 原则

1、日志目的

日志作用,就是记录程序中快照信息,方便定位问题。所以原则是:正确使用日志级别;在方便定位问题的前提下,尽量少。

2、规范主要包括两个方面

(1) logback配置时的原则

如涉及到partern、滚动策略等。

(2)代码中打印日志时原则。

3.2 logback.xml配置的规范原则

1、 统一个parten,不要使用多种pattern

<property name=”REQUEST_PATTERN” value=”%d  %-5level   [%X{ctxLogId}][%thread] %logger{5}- %msg%n”/>

2、只使用一种回滚策略

如果磁盘空间不紧张,都建议使用基于时间回滚的策略。这样可以按照日期进行归类日志,方便查看问题。

3、appender迭代性

避免打印同一个日志到多个文件中,造成重复日志,需要设置additivity=false。

3.3 代码规范原则

1、在代码中打印日志

需要关注如下两点:正确的使用日志级别打印日志信息时,需要包含重要的参数信息

(1)Error级别

谨慎使用Error。只有系统中发生了非常严重的问题,必须马上有人进行处理的场景才需要Error。如果打印大量的Error,可能这些问题级别并不高,这样就造成我们不方便添加监控,不知道那些error是需要马上处理的。

(2)warn

(3)info日志

打印info日志时,要从“方便定位问题”的角度出发,并且突出“业务流的流向”。但是Info不要随心所欲的打,不是日志越多越好。

(4) debug

开发人员,在使用开发环境测试时打印的日志,在线上的日志级别一定是INFO级别的

2、避免重复日志

(1)logback配置

配置输出数据源时,避免同一个日志分别输出到多个文件保存。需要设置additivity=”false”。

(2) 代码

调用函数时打印了参数,在被调用函数开始地方又打印了日志,如下,f()和g()两个函数中都打印了调用传给g()的参数,所以是重复日志

4 一个完整的实例

1、pom.xml

2、logback.xml配置

选择基于时间的回滚策略,如下

3、 在代码中使用

5 扩展

5.1 打印外部依赖的日志

5.2 从log4j切换到logback

需要两步:

  • 在pom.xml引入需要的logback包,替换log4j
  • 在resource下面添加logback.xml就可以了

5.3 生成一个logID

定义一个filter,通过MDC.put(key,value)来为一个请求赋值一个唯一的logID。这个logId获取目前一般有两个方法:

  • 在代码里面通过UUID来生成,并添加到MDC中。UUID的生成参考

UUID的使用

  • nginx中通过在header中增加一个logId属性。然后在代码里面通过request.getHeader(“logId”)来获取,添加到MDC中。

6 参考资料

【1】 logback用户手册中文版,下载地址 https://pan.baidu.com/s/1eRIshXK

【2】 layout的参数的解析  http://logback.qos.ch/manual/layouts.html

(全文完)

分类&标签