上一篇介绍了springboot整合logback的一些项目中用到的经验,本片文章继续介绍在项目中实际用到的工程经验

1、设想一下有这样一个场景:我想把我所有service层的日志单独打印到service.log中,那应该怎么做?

有人会说了可以配置一个service的appender,然后在每个service类中获取Logger实例进行打印

这样做当然可以,但是每个service中都获取一下Logger实例不繁琐吗?既然繁琐那有没有其他方式呢?接下来直接进行配置实践一下

首先配置日志文件路径和名字,然后配置appender

springboot整合logback进行日志管理(下篇)_日志文件

springboot整合logback进行日志管理(下篇)_logback_02

兄弟们看到了吗?直接配置service的扫描路径,这样所有service中的日志都会打印到service.log中

有一点就是我们不再是在root中添加,而是使用了子logger(因为不是所有的都需要打印到service.log中),子logger继承了root;

该标签有一个additivity属性,若是additivity设为true,则子logger不止会在自己的appender里输出,还会在root的logger的appender里输出;若是additivity设为false,则子logger只会在自己的appender里输出,不会在root的logger的appender里输出。

下面测试一下:我在service类中加一行打印

springboot整合logback进行日志管理(下篇)_spring boot_03

然后通过接口调用的时候看一下是否有service.log

springboot整合logback进行日志管理(下篇)_文件名_04

springboot整合logback进行日志管理(下篇)_logback_05

可以看到是没有问题的

2、将一些特定场景的日志单独保存到一个日志文件中

比如有以下一个场景,我项目中有一个类是调用的外部服务,我想把调用外部服务的这个类中的日志单独记录到一个out-service.log中,那怎么实现呢?

首先配置日志文件路径和名字:

springboot整合logback进行日志管理(下篇)_spring boot_06

然后配置相关的appender

springboot整合logback进行日志管理(下篇)_spring boot_07

本次我是用获取Logger实例的方式来记录日志,为了方便我就直接在主启动类里面进行测试了

springboot整合logback进行日志管理(下篇)_spring boot_08

springboot整合logback进行日志管理(下篇)_文件名_09

测试成功!!!

3、下面演示项目中常用到的通过切面将日志进行记录

如下所示我有一个切面类:

springboot整合logback进行日志管理(下篇)_后端_10

我这个切面用来记录controller每个方法的入参、出参、方法名、接口耗时等,下面编写切面代码:

package com.example.mybatisplus.config;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Aspect
@Component
public class HttpAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger("http-aspect");

    @Pointcut("execution(* com.example.mybatisplus.controller..*.*(..))")
    public void pointCut() {
    }

    @Around(value = "pointCut()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        // 获取目标参数
        long start = System.currentTimeMillis();
        String serviceUniqueName = proceedingJoinPoint.getSignature().getDeclaringTypeName();
        String methodName = proceedingJoinPoint.getSignature().getName();
        // 参数
        String args = Arrays.toString(proceedingJoinPoint.getArgs());
        boolean result = true;
        String errorMsg = "";
        long end = 0;
        try {
            // 执行目标方法
            Object proceed = proceedingJoinPoint.proceed();
            end = System.currentTimeMillis();
            return proceed;
        } catch (Exception e) {
            result = false;
            errorMsg = e.getMessage();
            throw e;
        } finally {
            LOGGER.info("serviceUniqueName:" + serviceUniqueName + ";methodName:" + methodName + ";result:" + result + ";args:" + args + ";cost:" + (end - start) + ";errorMsg:" + errorMsg);
        }
    }
}

然后配置切面相关的日志配置:

springboot整合logback进行日志管理(下篇)_日志文件_11

springboot整合logback进行日志管理(下篇)_后端_12

然后我启动服务之后调用controller测试一下:

springboot整合logback进行日志管理(下篇)_文件名_13

兄弟们,看到了吧,我调用了controller里面的两个方法,一个成功调用,一个失败调用,都记录到了切面的日志文件中,这样后面如果需要配置http请求告警监控的话直接读取我们的http-aspect.log是不是就可以了

下面再补充一个知识点:

细心的朋友已经发现了我切面打印日志是用的获取Logger实例的方式打印的,原因是我切面类只有一个,所以我只需要在切面类获取一次Logger就行,那么如果不想用这种方式的话使用@Slf4j能不能实现呢?当然可以,下面就说下使用注解方式怎么做:

由于我们是只有切面里面的日志打印到http-aspect.log中,所以有两种方法:

1、配置扫描路径的方式

springboot整合logback进行日志管理(下篇)_spring boot_14

配置完扫描路径就可以直接使用@Slf4j打印了

springboot整合logback进行日志管理(下篇)_后端_15

2、通过在@Slf4j注解上使用topic指定logger-name即可

我的logger name是http-aspect

springboot整合logback进行日志管理(下篇)_日志文件_16

然后使用的时候在注解上通过topic字段指定该logger name

springboot整合logback进行日志管理(下篇)_logback_17

测试一下也是ok的

springboot整合logback进行日志管理(下篇)_后端_18

最后附加上logback-spring.xml相关的配置:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- include引入打印格式配置 -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />

    <!-- 定义应用名称,区分应用 -->
    <property name="APP_NAME" value="myTradeProd"/>
    <!-- 定义日志文件的输出路径 -->
    <property name="LOG_PATH" value="${user.home}/logs/${APP_NAME}"/>
    <!-- 定义日志文件名称和路径 -->
    <property name="LOG_FILE" value="${LOG_PATH}/application.log"/>
    <!-- 定义错误级别日志文件名称和路径 -->
    <property name="ERROR_LOG_FILE" value="${LOG_PATH}/error.log"/>
    <!-- 定义指定目录service日志文件名称和路径 -->
    <property name="SERVICE_LOG_FILE" value="${LOG_PATH}/service.log"/>
    <!-- 配置out-service.log日志文件名称和路径 -->
    <property name="OUT_SERVICE_LOG_FILE" value="${LOG_PATH}/out-service.log"/>
    <!-- 定义指定切面日志文件名称和路径 -->
    <property name="HTTP_ASPECT_LOG_FILE" value="${LOG_PATH}/http-aspect.log"/>

    <!-- 将日志滚动输出到application.log文件中 -->
    <appender name="APPLICATION"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 输出文件目的地 -->
        <file>${LOG_FILE}</file>
        <encoder>
            <!-- 使用默认的输出格式打印 -->
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
        <!-- 设置 RollingPolicy 属性,用于配置文件大小限制,保留天数、文件名格式 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 文件命名格式 -->
            <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 文件保留最大天数 -->
            <maxHistory>7</maxHistory>
            <!-- 文件大小限制 -->
            <maxFileSize>50MB</maxFileSize>
            <!-- 文件总大小 -->
            <totalSizeCap>500MB</totalSizeCap>
        </rollingPolicy>
    </appender>

    <!-- 配置控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 配置日志打印格式 -->
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <!-- 过滤ERROR日志输出到error.log中 -->
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${ERROR_LOG_FILE}</file>
        <encoder>
            <!-- 使用默认的输出格式 -->
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
        <!-- 设置 RollingPolicy 属性,用于配置文件大小限制,保留天数、文件名格式 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 备份文件命名格式 -->
            <fileNamePattern>${LOG_PATH}/error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 文件保留最大天数 -->
            <maxHistory>7</maxHistory>
            <!-- 文件大小限制 -->
            <maxFileSize>50MB</maxFileSize>
            <!-- 文件总大小 -->
            <totalSizeCap>500MB</totalSizeCap>
        </rollingPolicy>
        <!-- 日志过滤器,将ERROR相关日志过滤出来 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
    </appender>

    <!-- 定义指定目录service的appender -->
    <appender name="SERVICE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${SERVICE_LOG_FILE}</file>
        <encoder>
            <!-- 使用默认的输出格式打印 -->
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
        <!-- 设置 RollingPolicy 属性,用于配置文件大小限制,保留天数、文件名格式 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 备份文件命名格式 -->
            <fileNamePattern>${LOG_PATH}/service.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 文件保留最大天数 -->
            <maxHistory>7</maxHistory>
            <!-- 文件大小限制 -->
            <maxFileSize>50MB</maxFileSize>
            <!-- 文件总大小 -->
            <totalSizeCap>500MB</totalSizeCap>
        </rollingPolicy>
    </appender>
    <!-- 配置扫描包路径,路径下所有service中的打印日志保存到service.log -->
    <!--若是additivity设为true,则子Logger不止会在自己的appender里输出,还会在root的logger的appender里输出-->
    <logger name="com.example.mybatisplus.service" level="INFO" additivity="false">
        <appender-ref ref="SERVICE"/>
    </logger>

    <!-- 定义指定目录service的appender -->
    <appender name="OUT-SERVICE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${OUT_SERVICE_LOG_FILE}</file>
        <encoder>
            <!-- 使用默认的输出格式打印 -->
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
        <!-- 设置 RollingPolicy 属性,用于配置文件大小限制,保留天数、文件名格式 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 备份文件命名格式 -->
            <fileNamePattern>${LOG_PATH}/out-service.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 文件保留最大天数 -->
            <maxHistory>7</maxHistory>
            <!-- 文件大小限制 -->
            <maxFileSize>50MB</maxFileSize>
            <!-- 文件总大小 -->
            <totalSizeCap>500MB</totalSizeCap>
        </rollingPolicy>
    </appender>
    <logger name="OUT-SERVICE" level="INFO" additivity="false">
        <appender-ref ref="OUT-SERVICE"/>
    </logger>

    <!-- 定义指定类topic的appender -->
    <appender name="HTTP-ASPECT" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${HTTP_ASPECT_LOG_FILE}</file>
        <encoder>
            <!-- 使用默认的输出格式打印 -->
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
        <!-- 设置 RollingPolicy 属性,用于配置文件大小限制,保留天数、文件名格式 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 文件命名格式 -->
            <fileNamePattern>${LOG_PATH}/http-aspect.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 文件保留最大天数 -->
            <maxHistory>7</maxHistory>
            <!-- 文件大小限制 -->
            <maxFileSize>50MB</maxFileSize>
            <!-- 文件总大小 -->
            <totalSizeCap>500MB</totalSizeCap>
        </rollingPolicy>
    </appender>

    <!-- 追加日志到HTTP-ASPECT的appender中 -->
    <!--若是additivity设为true,则子Logger不止会在自己的appender里输出,还会在root的logger的appender里输出-->
    <logger name="http-aspect" level="INFO" additivity="false">
        <appender-ref ref="HTTP-ASPECT"/>
    </logger>

    <!-- 配置日志级别 -->
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <!-- 加入APPLICATION输出 -->
        <appender-ref ref="APPLICATION"/>
        <!-- 加入ERROR日志输出 -->
        <appender-ref ref="ERROR"/>
    </root>
</configuration>