52

springboot+logback 日志输出企业实践(上)

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzUyNDk0NTg1MA%3D%3D&%3Bmid=2247483924&%3Bidx=1&%3Bsn=7c644d2c66579324e4ac45441baaf9ab
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

tags: springboot logback log

一句话概括:在 java 应用开发过程中,日志输出与记录是重要一环,logback 是当前的首选日志框架,本文将对 springboot+logback 的使用及在企业的实践进行详细描述。

1.引言

在 java 应用开发过程中,日志输出与记录是重要的一环,有了日志,我们可以定位错误与异常,追踪应用运行情况,记录应用访问时间等等。在学习 hello world 时就会使用 System.out.println() 来输出内容,当涉及到复杂一点的日志输出,最好是引入成熟的日志框架,曾经 log4j 是流行的日志框架,现在已被它的继任者 logback 替代,它更快,更小,更灵活。在 springboot 的开发中,默认已经自带了 logback,可直接使用。本文基本 springboot+logback,结合在企业中的实践,对日志的输出及配置进行详细说明,具体有如下内容:

  • logback 简要介绍

  • 使用 springboot+logback 构建示例工程及配置描述

  • logback 配置文件的详述及使用

如需看源码,本文 示例工程地址 [1] : https://github.com/mianshenglee/my-example/tree/master/springboot-logback-demo

2.logback 简介

logback 官网地址 [2] : http://logback.qos.ch ,从官网的介绍, logback 是 log4j 框架的作者开发的新一代日志框架,是 log4j 的继任者,它更快,更小, 效率更高、能够适应各种运行环境,同时天然支持 slf4j。slf4j,即 Simple Logging Facade For Java ,它是对各类日志框架的统一抽象,即定义了接口,具体使用哪个日志 框架由运行时绑定实现。

logback 主要由三个模块构成,分别是 logback-corelogback-classiclogback-access ,其中 logback-core 是基础核心,另外两个均依赖它。 logback-classic 实现了简单日志门面 SLF4J ;而 logback-access 主要作为一个与 Servlet 容器交互的模块,如 tomcat 或者 jetty ,提供与 HTTP 访问相关的一些功能。

3. springboot 默认日志框架-logback

本章节将使用 springboot+logback 构建示例工程,并对 logback 基本配置进行描述。

3.1 springboot 示例工程搭建

(1) 创建项目:通过 Spring Initializr 页面 [3] 生成一个添加了 web 模块及 lombok 模块的 Spring Boot 项目。

(2)添加示例功能:

  • 首先添加几个通用包:vo,controller,service,model,分别存放视图层模型,控制层,服务层,数据模型层等代码。

  • 针对用户增删改查功能,对应有数据模型 User,UserController,UserService,统一返回视图模型 ResponseResult。

(3)添加日志输出

  • 在 UserService 类中添加 lombok 提供的 @Slf4j 注解,这样可直接在此类中使用 log 进行日志输出,避免自己使用 LoggerFactory.getLogger 来新建。
  • 在对应的方法中使用 debuginfowarnerror 等方法输出日志。如 log.debug("get user by id:{}", id)

注意:此处具体代码不列出(详细可看 示例源码 [4] )。

至此,示例工程构建完成,可正常运行工程,查看工程的依赖情况,可以发现,springboot 已默认支持 logback。如下:

fq263yY.png!web logback依赖

3.2 日志输出与基本配置

3.2.1 日志默认输出

如上所示,默认情况下,springboot 使用 logback 进行日志输出,输出日志为 INFO 级别,输出位置是控制台。启动示例工程,示例输出如下:

7FF3Eju.png!web 默认日志输出

控制台日志输出的内容格式很清晰,分别是

  • 时间日期:格式是 yyyy-MM-dd HH:mm:ss.SSS
  • 日志级别:输出>=INFO 级别的日志(ERROR, WARN, INFO)

  • 进程 ID

  • 分隔符: ---
  • 线程名:线程名在方括号( [] )内
  • logger 名:类的名称

  • 日志内容

3.2.2 基本配置

在 springboot 在配置文件 application.properties 中,可以设置日志相关的内容,如下:

RBNzaaZ.png!web springboot日志配置

关于日志的配置有很多,后面我们主要使用自定义配置,因此不作详细说明,此处主要讲两个,日志级别控制及日志文件输出。

  • 日志级别控制,设置格式为 logging.leve.*=LEVEL ,其中*为包名或 logger 名,LEVEL 有: TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF

  • 日志输出到文件,默认日志只输出到控制台,不写文件,可以配置 logging.file.namelogging.file.path 来指定日志输出文件。 logging.file.name 设置文件, 会在项目的当前路径下生成此文件名的日志文件 。 logging.path 设置目录,会在此目录下创建 spring.log 文件。 默认情况下,日志文件的大小达到 10MB 时会切分一次,产生新的日志文件

    注意:二者不能同时使用,如若同时使用,则只有 logging.file 生效

3.3 自定义 logback 配置

上面在 properties 文件中对日志进行基本的配置,但配置能力较弱,不够灵活。因此一般都使用自定义配置,通过 xml 文件对 logback 的日志输出进行配置。

3.3.1 logback 配置文件加载顺序

在 springboot 应用中,对于 logback 的配置文件,默认情况下,配置文件放在 src/main/resources 下,支持的配置文件名称如下:

  • logback-spring.xml

  • logback-spring.groovy

  • logback.xml

  • logback.groovy

Spring Boot 官方推荐优先使用带有-spring 的文件名配置(如有 logback-spring.xml,则不会使用 logback.xml) 。当然,若需要对配置文件名进行修改,或者希望把配置文件放到其它目录下,可以通过 logging.config 属性指定自定义的名字,如 logging.config=classpath:config/log-config.xml ,则使用 resources/config 下的 log-config.xml 配置。

注,一般情况下,按默认规则(在 resources 目录下,使用 logback-spring.xml)即可。另外有了这个配置文件后,前面提到的在 properties 文件中的 logging 配置则不需要了。

3.3.2 logback 配置文件示例

这里先直接给出配置文件的示例,后面章节将对配置文件内容进行详细说明。如下所示,配置文件主要功能是把日志按格式输出到控制台和文件中,并且文件按日志输出级别分别输出到独立文件,文件按时间滚动(每天一个日志文件,保留 30 天)。完整配置内容可见源码中的 logback-spring.xml 文件。

<configuration scan="true" scanPeriod="1 seconds">
	...//略
    <!-- 日志输出格式 -->
    <property name="log.pattern"
              value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5level [%15thread] [%40.40logger{40}] [%10method,%line] : %msg%n"/>
    <!-- 控制台输出日志 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>${log.pattern}</pattern>
        </layout>
    </appender>

    <!-- 文件输出日志, 滚动(时间/文件大小)输出策略 -->
    <appender name="DEBUGFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 过滤器,只记录debug级别的日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <OnMismatch>DENY</OnMismatch>
            <OnMatch>ACCEPT</OnMatch>
        </filter>
        <!-- 日志文件路径及文件名 -->
        <File>${log.path}/${logfile.prefix}-debug.log</File>
        <!-- 日志记录器的滚动策略,按日期记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志输出格式 -->
            <FileNamePattern>${log.path}/${logfile.prefix}-debug.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!-- 日志保留天数 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>${log.pattern}</Pattern>
        </layout>
    </appender>
    ...//略
    <!-- 日志级别,不向上级传递日志内容,日志按appender-ref输出 -->
    <logger name="me.mason.demo.simplelogback.service.UserService" level="WARN" additivity="false">
        <appender-ref ref="STDOUT"/>
    </logger>
    <!-- 日志输出 -->
    <root level="DEBUG">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="DEBUGFILE"/>
        ...//略
    </root>
</configuration>

4. logback 配置文件详述

logback 配置文件决定日志输出格式、日志输出位置、输出文件策略等内容,因此需要对 logback 配置文件的结构及相关元素内容进行了解。

4.1 配置文件结构

配置文件总体来说内容比较简单,主要三个元素:

va2uIvM.png!web 配置主要元素

这三个元素中,logger 和 root 可视为同一类,都是日志组件,可以把 root 当作是特殊 logger,是根,必须配置。logger 配置解答从哪里获取日志,输出什么级别日志问题。appender 配置是指出日志以什么格式输出,日志如何过滤,输出文件后如何处理的问题。另外,还有可选的 property 及 contextName 元素,分别变量和应用上下文名称。

4.2 根元素 configuration

4.2.1 属性配置

根元素 configuration 有三个属性可以设置,如下:

  • debug:默认为 false,若设置为 true,则打印出 logback 内部日志信息

  • scan:默认值为 true,若设置为 true,配置文件如果发生改变,将会被重新加载。

  • scanPeriod:与 scan 配合使用,当 scan 为 true 时,此属性生效,默认的时间间隔为 1 分钟,设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。如可以设置为 scanPeriod="30 seconds" 每 30 秒检测一次。

4.2.2 定义上下文名称和变量

  • contextName 元素,每一个日志组件(logger)都会关联到日志上下文,默认上下文名称是'default',用于标识应用,如果多个应用输出到同一个地方,就有必要使用 %contextName 来区别。
  • property 元素,定义变量,有 name 和 value 属性,定义变量后,可以使“${name}”来使用变量。在配置中多个地方的值使用到相同的内容时,就有必要把相同内容设置变量,通过引用来设置。如示例工程中的日志文件名称前缀、日志路径、日志输出格式。

注意,定义的变量只能在配置文件的值中进行引用,不能在元素属性中引用。如配置文件中有很多属性是 class ,里面的内容只能写类的全路径,尽管类前缀都相同,但不能用变量替换。

4.3 日志输出组件 appender

此元素是主要配置项,表示以什么格式输出,日志如何过滤,输出文件后如何处理。appender 结构如下:

JvYNJfE.png!web appendero结构

appender 有两个属性 nameclass ; name 指定 appender 名称, class 指定 appender 的全限定名。appender 默认有以下几种:

  • ConsoleAppender:把日志添加到控制台,类名 ch.qos.logback.core.ConsoleAppender
  • FileAppender:把日志添加到文件,类名 ch.qos.logback.core.FileAppender
  • RollingFileAppender:滚动记录文件,FileAppender 的子类,当符合条件(大小、时间),日志进行切分,记录到其他文件。类名: ch.qos.logback.core.rolling.RollingFileAppender

实践过程中,一般使用 ConsoleAppender 及 RollingFileAppender 即可,若需要自定义如把日志输出到消息队列,可以自定义实现 AppenderBase 接口。

ConsoleAppender 比较简单,只需要使用 layout 元素,按日志输出格式即可,如下:

<!-- 控制台输出日志 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <layout class="ch.qos.logback.classic.PatternLayout">
        <pattern>${log.pattern}</pattern>
    </layout>
</appender>

RollingFileAppender 的配置相对多一点,包括 File、filter,rollingPolicy,encoder 和 layout 元素。其中 filter 可以过滤日志,因此,若需要把日志按级别输出到不同的文件中,因此,定义多个 RollingFileAppender(如对应 DEBUG、INFO、WARN、ERROR),分别按日志级别过滤即可。下面分别进行说明:

4.3.1 File 配置

配置文件输出的路径及文件名,一般把路径和文件名前缀定义到变量(property 中),如下:

<!--日志文件前缀,即应用名称 -->
<property name="logfile.prefix" value="logback-demo"/>
<!--日志路径,可写相对路径,也可写绝对路径 -->
<property name="log.path" value="logs"/>
...//略
<File>${log.path}/${logfile.prefix}-debug.log</File>

4.3.2 filter 配置

filter 可以为 appender 添加一个或多个过滤器,对日志进行过滤。过滤器有 ThresholdFilterLevelFilter ,前者是临界值过滤器,过滤掉低于指定临界值的日志;后者是级别过滤器,根据日志级别进行过滤, 如果日志级别等于配置级别 ,过滤器会根据 onMath (符合过滤条件的操作) 和 onMismatch (不符合过滤条件的操作)接收(ACCEPT)或拒绝(DENY)日志。按前面需求,把日志按不同级别分别输出到各自文件中,需要多个 RollingFileAppender 元素,每个元素下对应的 level 是 DEBUG,INFO,WARN 和 ERROR。

<!-- 过滤器,只记录debug级别的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
    <level>DEBUG</level>
    <OnMismatch>DENY</OnMismatch>
    <OnMatch>ACCEPT</OnMatch>
</filter>

4.3.3 rollingPolicy 配置

此元素描述滚动策略,有 TimeBasedRollingPolicySizeAndTimeBasedRollingPolicyFixedWindowRollingPolicySizeBasedTriggeringPolicy 。分别是基于时间滚动,基于大小和时间滚动,固定窗口滚动和大小触发,其中 FixedWindowRollingPolicy 一般和 SizeBasedTriggeringPolicy 同时使用。下面以 TimeBasedRollingPolicy 为例,以天为单位输出日志,每天一个日志。

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <!-- 日志输出格式 -->
    <FileNamePattern>${log.path}/${logfile.prefix}-debug.%d{yyyy-MM-dd}.log</FileNamePattern>
    <!-- 日志保留天数 -->
    <maxHistory>30</maxHistory>
</rollingPolicy>

FileNamePattern 表示日志的路径及名称,此处是按日期输出,即 %d{yyyy-MM-dd} 格式。 maxHistory 表示日志最多保留天数,大于这些天数后,前面的日志会删除。

对于 SizeAndTimeBasedRollingPolicy ,如下所示:

<!-- 按日期滚动 -->
<fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
<!-- 文件大小最大是100M,保存60日,总大小最大为20G -->
<maxFileSize>100MB</maxFileSize>
<maxHistory>60</maxHistory>
<totalSizeCap>20GB</totalSizeCap>

注意, %i%d 标识符都是强制性的。每当日志文件在当前时间段结束之前达到文件最大值时,它将以递增的 %d 索引存档,从 0 开始。

4.3.4 layout 配置

layout 元素较简单,只需要设置输出的格式即可。

<property name="log.pattern"
              value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5level [%15thread] %40.40logger{40} [%10method,%line] : %msg%n"/>
...//略
<layout class="ch.qos.logback.classic.PatternLayout">
    <Pattern>${log.pattern}</Pattern>
</layout>

4.3.5 输出格式控制

对于日志输出格式的控制,使用 logback 的保留字进行控制,保留字很多,建议查阅 官网文档 [5] ,下面对常用进行说明:

保留字 作用 c { length } lo { length } logger { length } 输出日志的 logger 名,可有一个整型参数,功能是缩短 logger 名,最右的点符号之后的类名始终显示,设置为 0 表示只输入 logger 最右边点符号之后的字符串。 C { length } class { length } 输出执行记录请求的调用者的全限定名。参数与上面的一样。尽量避免使用,除非执行速度不造成任何问题。 contextName cn 输出上下文名称。 d { pattern } date { pattern } 输出日志的打印日志,模式语法与 java.text.SimpleDateFormat 兼容。 L / line 输出执行日志请求的行号。尽量避免使用,除非执行速度不造成任何问题。 m / msg / message 输出应用程序提供的信息。 M / method 输出执行日志请求的方法名。尽量避免使用,除非执行速度不造成任何问题。 n 输出平台相关的分行符“\n”或者“\r\n”。 p / le / level 输出日志级别。 t / thread 输出产生日志的线程名。

另外,格式还有一个对齐功能,通过在 % 后面添加 -. 及数字进行控制。符号 - 是可选修饰符,表示是 左对齐 ,接着是可选的 最小宽度 修饰符,用十进制数表示。如果字符小于最小宽度,则左填充或右填充,默认是左填充(即右对齐),填充符为空格。 最大宽度 修饰符,符号是点号"."后面加十进制数。如果字符大于最大宽度,则从前面截断。点符号“.”后面加减号“-”在加数字,表示从尾部截断。

例如:%-40.40logger{40} 表示按 40 字符输出 logger 名,左对齐,若小于 40 字符的则填充空格,超过 40 则从左边截断。

对于控制台,还可以控制颜色,如前面 springboot 的默认输出就有颜色,如下:

格式 描述 %black 黑色 %red 红色 %green 绿色 %yellow 黄色 %blue 蓝色 %magenta 品红 %cyan 青色 %white 白色 %gray 灰色 %highlight 高亮色 %bold 强化上面的颜色,例如%boldRed,%boldBlack

4.4 日志组件 logger 及 root

logger 用来设置某一个类或者某个包的日志输出级别、以及关联 appender 指定输出位置,有三个属性:

  • name:指定的包名或者类名

  • level:输出日志级别,如果未设置此级别,那么当前 logger 会向上继承最近一个非空级别,级别以 name 区分,如 x 和 x.y,x 则是 x.y 的父级。
  • additivity:是否将日志向上级传递,默认为 true

logger 通过设置子节点 appender-ref 来指定日志输出位置,可以设置多个 appender-refroot 是一个特殊的 logger , 是所有 logger 的根节点,元素名为 root ,没有父级别,只有一个属性 level ,默认为 DEBUG 。

4.4.1 logger 配置,

此处对某个具体的类进行配置输出进行设置,由于设置了 WARN 级别, additivitytrue ,而且关联 STDOUT 的 appender,因此此类的>= WARN 的日志会输出到控制台。同时会把日志上传到父级,即 root。若 root 也有配置 STDOUT 的输出的话,会发现此日志在控制台输出两次。若 additivityfalse ,则不会。

<!-- 日志级别,不向上级传递日志内容,日志按appender-ref输出 -->
<logger name="me.mason.demo.simplelogback.service.UserService" level="WARN" additivity="true">
    <appender-ref ref="STDOUT"/>
</logger>

4.4.2 root 配置

logger 可以不配置,但 root 元素是必须配置的,需要告诉 logback 把日志输出到哪里。如下,只需要关联日志需要输出的 appender 即可。前面已经有 STDOUT 控制台及按日志级别设置了各个文件 appender ,此处直接关联即可。

<root level="DEBUG">
    <appender-ref ref="STDOUT"/>
    <appender-ref ref="DEBUGFILE"/>
    <appender-ref ref="INFOFILE"/>
    <appender-ref ref="WARNFILE"/>
    <appender-ref ref="ERRORFILE"/>
</root>

经过以上的配置,汇总到 logback-spring.xml 中,启动运行程序,即可看到控制台会按格式输出日志,同时会在应用根目录下创建 logs 目录存放日志文件,且日志格式是按配置输出,如下:

aUnQZzR.png!web 日志文件

5. 总结

本篇文章针对 springboot 应用开发中,如何使用 logback,结合在企业中的实践,创建 springboot 示例,然后对 logback 的配置进行详细说明,实现按日志级别输出日志文件功能。但在实际开发中,还有不少需要改进的地方,包括多环境配置,日志输出效率问题,分布式系统请求 ID 追踪问题等,将在下篇文章进行讲解。

本文中使用的示例代码已放在 github [6] : https://github.com/mianshenglee/my-example/tree/master/springboot-logback-demo ,有兴趣的同学可以 pull 代码,结合示例一起学习。

往期文章

参考资料

[1]

示例工程地址: https://github.com/mianshenglee/my-example/tree/master/springboot-logback-demo/logback-simple-demo

[2]

官网地址: http://logback.qos.ch/

[3]

Spring Initializr 页面: https://start.spring.io/

[4]

示例源码: https://github.com/mianshenglee/my-example/tree/master/springboot-logback-demo/logback-simple-demo

[5]

官网文档: http://logback.qos.ch/manual/layouts.html

[6]

github: https://github.com/mianshenglee/my-example/tree/master/springboot-logback-demo/logback-simple-demo

[7]

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

[8]

logback中文手册: http://www.logback.cn/

[9]

logback github: https://github.com/qos-ch/logback

[10]

看完这个不会配置 logback ,请你吃瓜: https://juejin.im/post/5b51f85c5188251af91a7525

如果文章对你有帮助,欢迎转发分享~

-   end  -

F36JRrr.gif

关注了解更多干货

↓↓↓↓  ↓↓↓   
RZJbAvB.jpg!web

关注:Mason技术记录

更多干货等着你


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK