logback抽取公共配置

背景

目前在项目处理日志层面上,每个项目都需要引入一个logback-spring.xml文件,而且在该文件中,内容很长,很多一摸一样的东西,而且各个项目格式不同,从而对项目排查带来很大的困扰,所以目前想解决的问题如下:

  • 对于没有埋点日志的项目,不需要引入xml文件;
  • 对于需要埋点日志的项目,尽可能做到精简;
  • 统一格式(后续如果推送到skywalking、es等等日志分析工具的时候,这里统一的格式处理起来会比较方便点);
  • 方便维护,统一管理。

实践

整体分为如下部分:

  • 定义一个公共starter包,各个项目必须引用;
  • 定义xml文件,主要实现系统日志生成,默认系统全局变量(比如统一系统日志格式、埋点格式、以及一些必要字段添加)、默认日志输出
  • 项目如何使用

公共starter

该starter名字为commons-starter

pom引用

项目需要支持springboot web功能,因为springboot 项目已经默认集成了logback,需要在这里我直接引用了springwebstarter(也可以单独只引用logback相关ajr包)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.3.12.RELEASE</version>
    <scope>compile</scope>
</dependency>

在resources中定义两个文件:

  • logback-base.xml

    定义全局公共部分,包括系统日志appender、全局日志系统变量等等

  • logback-spring.xml

    作为项目默认日志输出,可以让一些没有特殊定制化需求的项目,无需引入logback-spring.xml文件

工程目录如下:

在这里插入图片描述

xml文件

因为我这里需要打印skywalking的traceId,需要引用apm-toolkit-logback-1.x的包

并且,我在logback中使用了<if> 标签,必须引用janino和commons-compiler,该功能才可以实现,如果不需要<if>标签功能,可以不引用这两个包

整体pom如下

 <dependency>
     <groupId>org.codehaus.janino</groupId>
     <artifactId>janino</artifactId>
     <version>3.0.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.codehaus.janino/commons-compiler -->
<dependency>
    <groupId>org.codehaus.janino</groupId>
    <artifactId>commons-compiler</artifactId>
    <version>3.0.8</version>
</dependency>
<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-logback-1.x</artifactId>
    <version>${skywalking.logback.version}</version>
</dependency>
logback-base.xml
<included>
    <conversionRule conversionWord="SW_CTX"
                    converterClass="org.apache.skywalking.apm.toolkit.log.logback.v1.x.LogbackSkyWalkingContextPatternConverter" />
    <conversionRule conversionWord="TID"
                    converterClass="org.apache.skywalking.apm.toolkit.log.logback.v1.x.LogbackPatternConverter" />
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>

    <property name="CONSOLE_LOG_PATTERN"
              value="%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %boldMagenta([%SW_CTX])  %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
    <springProperty scope="context" name="springApplicationName" source="spring.application.name"
                    defaultValue="unknown" />
    <springProperty scope="context" name="appenv" source="spring.profiles.active"
                    defaultValue="test" />
    <property name="logApp" value="${springApplicationName}-${appenv}"/>
    <property name="logAppSys" value="${logApp}-sys"/>
    <property name="logAppBiz" value="${logApp}-biz"/>

    <if condition='property("appenv").equals("prod")'>
        <then>
            <property name="systemEnv" value="standend" />
        </then>
        <else>
            <property name="systemEnv" value="dev"/>
        </else>
    </if>
    <!--统一系统日志输出格式-->
    <property name="sysLogParttern" value='{"timestamp": "%d{yyyy-MM-dd HH:mm:ss.SSS}","fb_collect_app":"${logAppSys}","system_env":"${systemEnv}","traceId": "[%TID]","traceCtx":"[%SW_CTX]","level": "%level","service": "${springApplicationName}", "thread": "%thread", "class": "%logger{50}", "msg": "%msg", "exception":"%exception{10}" }%n'/>
    <!--统一埋点日志输出格式-->
    <!--注意看,我这里的埋点日志是msg字段,我需要在埋点日志多增加一些额外的字段,比如时间,系统环境,trace ID等等,埋点日志只需要埋相关的业务字段-->
    <property name="bizLogParttern" value='{"business_time": "%d{yyyy-MM-dd HH:mm:ss.SSS}","fb_collect_app":"${logAppBiz}","system_env":"${systemEnv}","traceId": "[%TID]","traceCtx":"[%SW_CTX]","msg": %msg }%n'/>


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

    <!-- 系统文件输出 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>/tmp/logs/sys/${springApplicationName}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志文件路径 -->
            <fileNamePattern>/tmp/logs/sys/${springApplicationName}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 保留的历史日志文件数量 -->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件的最大大小 -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>${sysLogParttern}</pattern>
        </encoder>
    </appender>
    <!--开启logback异步记录日志-->  
    <appender name="sysAsync" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="FILE" />
    </appender>

    <!-- 使用gRpc将日志发送到skywalking服务端 -->
    <appender name="grpc-skywalking" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
                <Pattern>${sysLogParttern}</Pattern>
            </layout>
        </encoder>
    </appender>

    <!-- 日志级别 -->
    <root level="info">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="sysAsync"/>
        <appender-ref ref="grpc-skywalking"/>
    </root>
</included>

上述功能,如果不需要使用skywalking相关功能点,需要修改这几个功能:

  • 去掉<conversionRule> 标签 SW_CTX、TID;

    <conversionRule conversionWord="SW_CTX"
                    converterClass="org.apache.skywalking.apm.toolkit.log.logback.v1.x.LogbackSkyWalkingContextPatternConverter" />
    <conversionRule conversionWord="TID"
                    converterClass="org.apache.skywalking.apm.toolkit.log.logback.v1.x.LogbackPatternConverter" />
    
  • 去掉CONSOLE_LOG_PATTERN中的 %boldMagenta([%SW_CTX])

  • 去掉 sysLogPartternbizLogParttern中的 “traceId”: “[%TID]”,“traceCtx”:"[%SW_CTX]"即可

  • 去掉如下配置:

        <!-- 使用gRpc将日志发送到skywalking服务端 -->
        <appender name="grpc-skywalking" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
            <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
                <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
                    <Pattern>${sysLogParttern}</Pattern>
                </layout>
            </encoder>
        </appender>
    
logback-spring.xml

该文件其实是非必须,如果你想项目不需要集成xml文件就实现日志输出功能,那么该文件就可以考虑放到公共starter中

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="logback-base.xml"/>
</configuration>

项目使用

默认功能

如果没有埋点日志,只需要实现系统埋点日志功能,那么直接引入pom文件即可;

<dependency>
    <groupId>com.commons.starter</groupId>
    <artifactId>commons-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>
埋点日志需求

如果业务需要额外的日志输出,按如下步骤实现:

  • 项目新建logback-spring.xml文件,并引入logback-base.xml文件
  • xml文件新增业务appender;
  • 日志输出定义;

示例如下:

logbackj-spring.xml

<configuration>
    <!-- 这个是必须,一定要注意!!! -->
    <include resource="logback-base.xml"/>

    <!-- 埋点输出 -->
    <appender name="bizlogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>/tmp/logs/biz/${springApplicationName}-biz.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志文件路径 -->
            <fileNamePattern>/tmp/logs/biz/${springApplicationName}.%d{yyyy-MM-dd}.%i-biz.log</fileNamePattern>
            <!-- 保留的历史日志文件数量 -->
            <maxHistory>7</maxHistory>
            <!-- 每个日志文件的最大大小 -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>${bizLogParttern}</pattern>
        </encoder>
    </appender>

    <!-- 添加信息 -->
    <logger name="bizlog" additivity="false" level="INFO">
        <appender-ref ref="bizlogAppender"/>
    </logger>

</configuration>

Java如何使用

在Java类使用的时候,如下:

注意:LoggerFactory.getLogger(“bizlog”)中的bizlog来自于你在logback.xml文件中定义的<logger>

class test{
    //bizlog来自于你在logback.xml文件中定义的<logger>
    private static final Logger custom = LoggerFactory.getLogger("bizlog");
    public void aa(){
        // 后面是你自己跟业务约定的json体
        custom.info("{\"timestamp\":\"2024-06-28T12:00:00Z\",\"loglevel\":\"INFO444\",\"logs\":\"User logged in\"}");
    }
}

总结

上面主要讲的是一个公共starter解决多个项目的公共配置,这么做主要是为了统一的日志格式,日志公共处理,这么做可以为后续的日志采集,日志统计分析做铺垫,比如项目集成filebeat、logstash的话,对于日志清洗,筛选,大大简化了很多复杂的东西。

主要还是提供一个思路,大家可以参考,不一定完全按照这个来实现

拓展点

logback中的logger和root区别

文章来源:logback中的logger和root_logback logger

logger和root logger都是日志记录器(logger)的实例,用于控制日志的输出级别。它们之间的区别在于它们的作用范围和默认配置。

logger是应用程序中的具体组件或类的日志记录器。每个logger都可以单独配置,以控制特定组件或类的日志输出级别。通过logger,我们可以对不同的组件或类设置不同的日志级别,从而灵活地控制日志的输出。

root logger是logger的顶级父级别。它是logger层次结构的根节点,用于控制整个应用程序的日志输出级别。如果没有为特定的logger配置日志级别,那么它将继承root logger的日志级别。因此,root logger的日志级别可以被视为默认的全局日志级别。

示例

<!-- 系统模块日志级别控制  -->
<logger name="com.demo" level="info" />
<!-- Spring日志级别控制  -->
<logger name="org.springframework" level="warn" />

<root level="info">
	<appender-ref ref="console" />
</root>

上面的配置代码是一个典型的日志配置文件,用于控制日志输出的级别。在这个配置中,有两个地方设置了日志级别:logger 元素和 root 元素。

  • logger 元素:logger 元素用于指定特定包或类的日志级别。在上面的配置中,com.demo 包的日志级别被设置为 info,org.springframework 包的日志级别被设置为 warn。这意味着在这两个包中的日志输出将受到相应级别的限制。更具体地说,info 级别将输出 info、warn 和 error 级别的日志,而 warn 级别将输出 warn 和 error 级别的日志。

  • root 元素:root 元素用于设置默认的日志级别,适用于所有未被特定 logger 元素覆盖的包或类。在上面的配置中,root 元素的日志级别被设置为 info。这意味着除了被特定 logger 元素设置为其他级别的包或类外,所有其他包或类的日志输出将受到 info 级别的限制。

总结起来,logger 元素用于设置特定包或类的日志级别,而 root 元素用于设置默认的日志级别。如果特定包或类的日志级别被设置为某个级别,那么该级别及其以上级别的日志将被输出。如果未被特定设置的包或类将受到默认的日志级别限制。在上面的配置中,com.demo 包的日志级别为 info,org.springframework 包的日志级别为 warn,而其他包或类的日志级别将受到默认的 info 级别限制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值