Java入门14---logback

java

官网:https://logback.qos.ch/

Logback 继承自 log4j,springboot默认使用的日志框架是logback,它由三个模块组成:

  1. logback-core:是其它模块的基础设施,其它模块基于它构建;
  2. logback-classic:它的地位和作用等同于 Log4J,它也被认为是 Log4J 的一个改进版,并且它实现了简单日志门面 SLF4J
  3. logback-access:作为一个与 Servlet 容器交互的模块,比如说tomcat或者 jetty,提供一些与 HTTP 访问相关的功能。

logback加载

我们简单分析一下logback加载过程,当我们使用logback-classic.jar时,应用启动,那么logback会按照如下顺序进行扫描:

  1. 在系统配置文件System Properties中寻找是否有logback.configurationFile对应的value
  2. 在classpath下寻找是否有logback.groovy(即logback支持groovy与xml两种配置方式)
  3. 在classpath下寻找是否有logback-test.xml
  4. 在classpath下寻找是否有logback.xml

以上任何一项找到了,就不进行后续扫描,按照对应的配置进行logback的初始化,具体代码实现可见ch.qos.logback.classic.util.ContextInitializer类的findURLOfDefaultConfigurationFile方法。

当所有以上四项都找不到的情况下,logback会调用ch.qos.logback.classic.BasicConfigurator的configure方法,构造一个ConsoleAppender用于向控制台输出日志,默认日志输出格式为"%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"。

二、配置文件

1.配置框架

代码解释

(1)configuration

  1. scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
  2. scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
  3. debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。

(2)property

用来定义变量值的标签,property标签有两个属性,name和value;其中name的值是变量的名称,value的值时变量定义的值。通过property定义的值会被插入到logger上下文中。定义变量后,可以使“${name}”来使用变量。如上面的xml所示。

(3)contextName

每个logger都关联到logger上下文,默认上下文名称为“default”。但可以使用contextName标签设置成其他名字,用于区分不同应用程序的记录

(4)appender

负责写日志的组件【appender让我们的应用知道怎么打、打印到哪里、打印成什么样】

(5)logger

用来设置某一个包或者具体的某一个类的日志打印级别以及指定appender。appender是一个日志打印的组件,这里组件里面定义了打印过滤的条件、打印输出方式、滚动策略、编码方式、打印格式等等。但是它仅仅是一个打印组件,如果我们不使用一个logger或者root的appender-ref指定某个具体的appender时,它就没有什么意义。【logger则是告诉应用哪些可以这么打。例如某个类下的日志可以使用这个appender打印或者某个包下的日志可以这么打印。】

(6)root

根logger,也是一种logger,且只有一个level属性;root中不能有name和additivity属性,只有一个level。

(7)filter

filter其实是appender里面的子元素。它作为过滤器存在,执行一个过滤器会有返回DENY,NEUTRAL,ACCEPT三个枚举值中的一个。

DENY:日志将立即被抛弃不再经过其他过滤器

NEUTRAL:有序列表里的下个过滤器过接着处理日志

ACCEPT:日志会被立即处理,不再经过剩余过滤器

2.appender 配置

2.1 属性

有两个属性 name和class:

name指定appender名称;

class指定appender的全限定名。

上面声明的是名为GLMAPPER-LOGGERONE,class为ch.qos.logback.core.rolling.RollingFileAppender的一个appender。

2.2 种类

ConsoleAppender:把日志添加到控制台

FileAppender:把日志添加到文件

RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。它是FileAppender的子类

2.3 子标签

(1)append 子标签

true

如果是 true,日志被追加到文件结尾,如果是false,清空现存文件,默认是true。

(2)filter 子标签

在简介中提到了filter;作用就是上面说的。可以为appender 添加一个或多个过滤器,可以用任意条件对日志进行过滤。appender 有多个过滤器时,按照配置顺序执行。
ThresholdFilter

临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝。

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">

<level>INFO</level>

</filter>

LevelFilter

级别过滤器,根据日志级别进行过滤。如果日志级别等于配置级别,过滤器会根据onMath(用于配置符合过滤条件的操作) 和 onMismatch(用于配置不符合过滤条件的操作)接收或拒绝日志。

<filter class="ch.qos.logback.classic.filter.LevelFilter">

<level>INFO</level>

<onMatch>ACCEPT</onMatch>

<onMismatch>DENY</onMismatch>

</filter>

执行一个过滤器会有返回DENY,NEUTRAL,ACCEPT三个枚举值中的一个。

DENY:日志将立即被抛弃不再经过其他过滤器

NEUTRAL:有序列表里的下个过滤器过接着处理日志

ACCEPT:日志会被立即处理,不再经过剩余过滤器

(3)file 子标签

file 标签用于指定被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。

<file>

${logging.path}/glmapper-spring-boot/glmapper-loggerone.log

</file>

这个表示当前appender将会将日志写入到${logging.path}/glmapper-spring-boot/glmapper-loggerone.log这个目录下。

(4)rollingPolicy 子标签

这个子标签用来描述滚动策略的。这个只有appender的class是RollingFileAppender时才需要配置。这个也会涉及文件的移动和重命名(a.log->a.log.2018.07.22)。
TimeBasedRollingPolicy

最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责触发滚动。包括两个属性:

  1. FileNamePattern
  2. maxHistory

下面这段配置表明每天生成一个日志文件,保存30天的日志文件

<rollingPolicy 

class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

<!--日志文件输出的文件名:按天回滚 daily -->

<FileNamePattern>

${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}

</FileNamePattern>

<!--日志文件保留天数-->

<MaxHistory>30</MaxHistory>

</rollingPolicy>

FixedWindowRollingPolicy

根据固定窗口算法重命名文件的滚动策略。

(5)encoder 子标签

对记录事件进行格式化。它干了两件事:

把日志信息转换成字节数组

把字节数组写入到输出流

<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}

- %msg%n</pattern>

<charset>UTF-8</charset>

</encoder>

目前encoder只有PatternLayoutEncoder一种类型。

定义一个只打印error级别日志的appender

 <!-- 错误日志 appender : 按照每天生成日志文件 -->

<appender name="ERROR-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">

<append>true</append>

<!-- 过滤器,只记录 error 级别的日志 -->

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">

<level>error</level>

</filter>

<!-- 日志名称 -->

<file>${logging.path}/glmapper-spring-boot/glmapper-error.log</file>

<!-- 每天生成一个日志文件,保存30天的日志文件 -->

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

<!--日志文件输出的文件名:按天回滚 daily -->

<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-error.log.%d{yyyy-MM-dd}</FileNamePattern>

<!--日志文件保留天数-->

<MaxHistory>30</MaxHistory>

</rollingPolicy>

<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>

<!-- 编码 -->

<charset>UTF-8</charset>

</encoder>

</appender>

3.logger 配置

用来设置某一个包或者具体某一个类的日志打印级别、以及指定。可以包含零个或者多个元素,标识这个appender将会添加到这个logger。仅有一个name属性、一个可选的level属性和一个可选的additivity属性:

name:用来指定受此logger约束的某一个包或者具体的某一个类。

level:用来设置打印级别(TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF),还有一个值INHERITED或者同义词NULL,代表强制执行上级的级别。如果没有设置此属性,那么当前logger将会继承上级的级别。

addtivity:用来描述是否向上级logger传递打印信息。默认是true。

<logger name="com.glmapper.spring.boot.controller"

level="${logging.level}" additivity="false">

<appender-ref ref="GLMAPPER-LOGGERONE" />

</logger>

com.glmapper.spring.boot.controller这个包下的${logging.level}级别的日志将会使用GLMAPPER-LOGGERONE来打印。

三、举例

1.通过控制台输出log

<configuration>

<!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

<Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>

</encoder>

</appender>

<root level="info">

<appender-ref ref="STDOUT"/>

</root>

</configuration>

2.控制台不打印,直接输出到日志文件

<configuration>

<!-- 属性文件:在properties文件中找到对应的配置项 -->

<springProperty scope="context" name="logging.path" source="logging.path"/>

<springProperty scope="context" name="logging.level" source="logging.level.com.glmapper.spring.boot"/>

<!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->

<appender name="STDOUT"

class="ch.qos.logback.core.ConsoleAppender">

<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

<Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>

</encoder>

</appender>

<appender name="GLMAPPER-LOGGERONE"

class="ch.qos.logback.core.rolling.RollingFileAppender">

<append>true</append>

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">

<level>${logging.level}</level>

</filter>

<file>

${logging.path}/glmapper-spring-boot/glmapper-loggerone.log

</file>

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}</FileNamePattern>

<MaxHistory>30</MaxHistory>

</rollingPolicy>

<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>

<charset>UTF-8</charset>

</encoder>

</appender>

<root level="info">

<appender-ref ref="GLMAPPER-LOGGERONE"/>

</root>

</configuration>

但是实际上我们不希望业务日志中会包括这些启动信息。所以这个时候我们就需要使用logger标签,将上面的配置文件进行简单修改:

<logger name="com.glmapper.spring.boot.controller" level="${logging.level}"

additivity="false">

<appender-ref ref="GLMAPPER-LOGGERONE" />

</logger>

<root level="${logging.level}">

<appender-ref ref="STDOUT"/>

</root>

让root指向控制台输出;logger负责打印包com.glmapper.spring.boot.controller下的日志。

3.根据包进行日志文件隔离

将com.glmapper.spring.boot.controller中的日志输出到glmapper-controller.log;将com.glmapper.spring.boot.service中的日志输出到glmapper-service.log。

<!--打印日志到glmapper-service.log的appender-->

<appender name="GLMAPPER-SERVICE"

class="ch.qos.logback.core.rolling.RollingFileAppender">

<append>true</append>

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">

<level>${logging.level}</level>

</filter>

<file>

${logging.path}/glmapper-spring-boot/glmapper-service.log

</file>

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-service.log.%d{yyyy-MM-dd}</FileNamePattern>

<MaxHistory>30</MaxHistory>

</rollingPolicy>

<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>

<charset>UTF-8</charset>

</encoder>

</appender>

<!--打印日志到glmapper-controller.log的appender-->

<appender name="GLMAPPER-CONTROLLER"

class="ch.qos.logback.core.rolling.RollingFileAppender">

<append>true</append>

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">

<level>${logging.level}</level>

</filter>

<file>

${logging.path}/glmapper-spring-boot/glmapper-controller.log

</file>

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-controller.log.%d{yyyy-MM-dd}</FileNamePattern>

<MaxHistory>30</MaxHistory>

</rollingPolicy>

<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>

<charset>UTF-8</charset>

</encoder>

</appender>

<!--此logger约束将.controller包下的日志输出到GLMAPPER-CONTROLLER,错误日志输出到GERROR-APPENDE;GERROR-APPENDE见上面-->

<logger name="com.glmapper.spring.boot.controller" level="${logging.level}" additivity="false">

<appender-ref ref="GLMAPPER-CONTROLLER" />

<appender-ref ref="ERROR-APPENDER" />

</logger>

<!--此logger约束将.service包下的日志输出到GLMAPPER-SERVICE,错误日志输出到ERROR-APPENDE;ERROR-APPENDE见上面-->

<logger name="com.glmapper.spring.boot.service" level="${logging.level}" additivity="false">

<appender-ref ref="GLMAPPER-SERVICE" />

<appender-ref ref="ERROR-APPENDER" />

</logger>

假如我们不想在info里面出现error怎么办呢?很简单,我们以APPENDER-SERVICE为例,将filter过滤器进行修改:

将下面的:

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">

<level>${logging.level}</level>

</filter>

修改为:

<filter class="ch.qos.logback.classic.filter.LevelFilter">

<level>ERROR</level>

<!-- 如果命中就禁止这条日志 -->

<onMatch>DENY</onMatch>

<!-- 如果没有命中就使用这条规则 -->

<onMismatch>ACCEPT</onMismatch>

</filter>

4.根据类进行日志文件隔离

一般情况下比如说我们有个定时任务类需要单独来记录其日志信息,这样我们就可以考虑使用基于类维度来约束打印。

<!--特殊功能单独appender 例如调度类的日志-->

<appender name="SCHEDULERTASKLOCK-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">

<append>true</append>

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">

<level>${logging.level}</level>

</filter>

<file>${logging.path}/glmapper-spring-boot/scheduler-task-lock.log</file>

<!-- 每天生成一个日志文件,保存30天的日志文件 -->

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

<!--日志文件输出的文件名:按天回滚 daily -->

<FileNamePattern>${logging.path}/glmapper-spring-boot/scheduler-task-lock.log.%d{yyyy-MM-dd}</FileNamePattern>

<!--日志文件保留天数-->

<MaxHistory>30</MaxHistory>

</rollingPolicy>

<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">

<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>

<!-- 编码 -->

<charset>UTF-8</charset>

</encoder>

</appender>

<!--这里指定到了具体的某一个类-->

<logger name="com.glmapper.spring.boot.task.TestLogTask" level="${logging.level}" additivity="true">

<appender-ref ref="SCHEDULERTASKLOCK-APPENDER" />

<appender-ref ref="ERROR-APPENDER" />

</logger>

5.调用LOG,但不打印任何信息

<logger name="xxx" additivity="false" />

6.异步写日志

日志通常来说都以文件形式记录到磁盘,例如使用,这样的话一次写日志就会发生一次磁盘IO,这对于性能是一种损耗,因此更多的,对于每次请求必打的日志(例如请求日志,记录请求API、参数、请求时间),我们会采取异步写日志的方式而不让此次写日志发生磁盘IO,阻塞线程从而造成不必要的性能损耗。

参考链接:

【1】配置 logback

【2】Java日志框架:logback详解 - 五月的仓颉 - 博客园

【3】logback 中文手册

以上是 Java入门14---logback 的全部内容, 来源链接: utcz.com/z/394061.html

回到顶部