springboot集成logback

发布时间 2023-06-02 16:27:34作者: 噗噗噗i丶

配置:

Springboot框架已经整合了logback依赖,因此不再需要加入依赖。
关于日志系统的配置文件,官方推荐我们使用logback-spring.xml 而不是 logback.xml
因此我们在resources(classpath路径)下创建一个名为logback-spring.xml的配置文件。

 代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <conversionRule conversionWord="serverIp" converterClass="com.lmes.contract.config.LogIpConfig" />
    <property name="logback.logdir" value="@profileLogdir@" defaultValue="./logs" />
    <property name="SystemCode" value="L115" />
    <springProperty scope="context" name="applicationName" source="spring.application.name" defaultValue="lmes-app" />
    <springProperty scope="context" name="serverPort" source="server.port" defaultValue="8080" />
    <contextName>${applicationName}</contextName>

    <!--输出到控制台 ConsoleAppender -->
    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n</pattern>
            </pattern>
        </layout>
    </appender>

    <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--如果只是想要 Info 级别的日志,只是过滤 info 还是会输出 Error 日志,因为 Error 的级别高, 所以我们使用下面的策略,可以避免输出 Error 的日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ALL</level>
        </filter>
        <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则 如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天的日志改名为今天的日期。即,<File> 的日志都是当天的。 -->
        <File>${logback.logdir}/${applicationName}/logs/info.${applicationName}.log</File>
        <!--滚动策略,按照大小和时间滚动 SizeAndTimeBasedRollingPolicy -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间 -->
            <FileNamePattern>${logback.logdir}/${applicationName}/logs/info.${applicationName}.log.%d{yyyy-MM-dd}.%i</FileNamePattern>
            <maxFileSize>1GB</maxFileSize>
        </rollingPolicy>
        <!--日志输出编码格式化 -->
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d|%level|${serverPort}|%class|%method|${SystemCode}|%serverIp|%X{traceId}|${applicationName}|1|%msg  %replace(%ex{full}){"[\r\n]+", "###"} %nopex|$|$|%n</pattern>
        </encoder>
    </appender>


    <appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--如果只是想要 Error 级别的日志,那么需要过滤一下,默认是 info 级别的,ThresholdFilter -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>Error</level>
        </filter>
        <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则 如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天的日志改名为今天的日期。即,<File> 的日志都是当天的。 -->
        <File>${logback.logdir}/${applicationName}/logs/error.${applicationName}.log</File>
        <!--滚动策略,按照大小和时间滚动 SizeAndTimeBasedRollingPolicy -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间 -->
            <FileNamePattern>${logback.logdir}/${applicationName}/logs/error.${applicationName}.log.%d{yyyy-MM-dd}.%i</FileNamePattern>
            <maxFileSize>100MB</maxFileSize>
        </rollingPolicy>
        <!--日志输出编码格式化 -->
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d|%level|${serverPort}|%class|%method|${SystemCode}|%serverIp|%X{traceId}|${applicationName}|1|%msg|$|$|%n</pattern>
        </encoder>
    </appender>

    
    <appender name="fileWarnLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--如果只是想要 DEBUG 级别的日志,那么需要过滤一下,默认是 info 级别的,ThresholdFilter -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!--过滤 DEBUG -->
            <level>WARN</level>
            <!--匹配到就允许 -->
            <onMatch>ACCEPT</onMatch>
            <!--没有匹配到就禁止-->
            <onMismatch>DENY</onMismatch>
        </filter>
        <!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则 如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天的日志改名为今天的日期。即,<File> 的日志都是当天的。 -->
        <File>${logback.logdir}/${applicationName}/logs/warn.${applicationName}.log</File>
        <!--滚动策略,按照大小和时间滚动 SizeAndTimeBasedRollingPolicy -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间 -->
            <FileNamePattern>${logback.logdir}/${applicationName}/logs/warn.${applicationName}.log.%d{yyyy-MM-dd}.%i</FileNamePattern>
            <maxFileSize>20MB</maxFileSize>
        </rollingPolicy>
        <!--日志输出编码格式化 -->
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d|%level|${serverPort}|%class|%method|${SystemCode}|%serverIp|%X{traceId}|${applicationName}|1|%msg|$|$|%n</pattern>
        </encoder>
    </appender>

    <!--指定最基础的日志输出级别 -->
    <root level="INFO">
        <!--appender将会添加到这个loger -->
        <appender-ref ref="fileInfoLog" />
        <appender-ref ref="fileWarnLog" />
        <appender-ref ref="fileErrorLog" />
        <appender-ref ref="consoleLog" />
    </root>

</configuration>

然后nacos配置文件中指定日志系统使用的配置文件,如下图所示:

 使用:

使用的方法有两种

  • 在类头上使用@slf4j注解
  • 手动创建Logger对象

看到16行和19行,就分别是我们上面说到的两种方式,40和41行就是关于日志输出的使用。

常用Appender

AsyncAppender
AsyncAppender并不处理日志,只是将日志缓冲到一个BlockingQueue里面去,并在内部创建一个工作线程从队列头部获取日志,之后将获取的日志循环记录到附加的其他appender上去,从而达到不阻塞主线程的效果。因此AsynAppender仅仅充当事件转发器,必须引用另一个appender来做事。

默认情况下,AsyncAppender会在队列满80%的情况下删除TRACE、DEBUG和INFO级别的事件。这种策略以事件损失为代价,对性能有惊人的有利影响。

由于使用了BlockingQueue来缓存日志,因此就会出现队列满的情况,默认情况下,AsyncAppender会在队列满80%的情况下删除TRACE、DEBUG和INFO级别的事件。这种策略以事件损失为代价,对性能有惊人的有利影响。

 

queueSize:blockingQueue长度决定了队列能放多少信息,在默认的配置下,如果blockingQueue放满了,后续想要输出日志的线程会被阻塞,直到Worker线程处理掉队列中的信息为止。根据实际情况适当调整队列长度,可以防止线程被阻塞。

discardingThreshold:为了提高性能,默认情况下,当事件添加到事件队列时,不会提取与事件关联的调用者数据。默认情况下,只复制像线程名和MDC这样的“廉价”数据。您可以通过将inclecallerdata属性设置为true来引导这个appender包含调用者数据。

maxFlushTime:根据队列深度和被引用的appender的延迟,AsyncAppender可能会花费不可接受的时间来完全刷新队列。当LoggerContext停止时,AsyncAppender stop方法将等待工作线程完成此超时。使用maxFlushTime指定以毫秒为单位的最大队列刷新超时。无法在此窗口内处理的事件将被丢弃。该值的语义与Thread.join(long)相同。

neverBlock:如果为false(默认值),代表在队列放满的情况下是否卡住线程,不会丢失消息。当队列满了时,会阻塞业务线程,此时异步处理会变成同步等待;只有队列有可用容量时,业务线程才从阻塞状态恢复。如果配置neverBlock=true,当队列满了之后,后面阻塞的线程想要输出的消息就直接被丢弃,从而线程不会阻塞。

详解见:(17条消息) logback教程logback快速入门超实用详细教程收藏这一篇就够了(万字长文)_「已注销」的博客-CSDN博客