上一篇介绍了springboot整合logback的一些项目中用到的经验,本片文章继续介绍在项目中实际用到的工程经验
1、设想一下有这样一个场景:我想把我所有service层的日志单独打印到service.log中,那应该怎么做?
有人会说了可以配置一个service的appender,然后在每个service类中获取Logger实例进行打印
这样做当然可以,但是每个service中都获取一下Logger实例不繁琐吗?既然繁琐那有没有其他方式呢?接下来直接进行配置实践一下
首先配置日志文件路径和名字,然后配置appender
兄弟们看到了吗?直接配置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类中加一行打印
然后通过接口调用的时候看一下是否有service.log
可以看到是没有问题的
2、将一些特定场景的日志单独保存到一个日志文件中
比如有以下一个场景,我项目中有一个类是调用的外部服务,我想把调用外部服务的这个类中的日志单独记录到一个out-service.log中,那怎么实现呢?
首先配置日志文件路径和名字:
然后配置相关的appender
本次我是用获取Logger实例的方式来记录日志,为了方便我就直接在主启动类里面进行测试了
测试成功!!!
3、下面演示项目中常用到的通过切面将日志进行记录
如下所示我有一个切面类:
我这个切面用来记录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);
}
}
}
然后配置切面相关的日志配置:
然后我启动服务之后调用controller测试一下:
兄弟们,看到了吧,我调用了controller里面的两个方法,一个成功调用,一个失败调用,都记录到了切面的日志文件中,这样后面如果需要配置http请求告警监控的话直接读取我们的http-aspect.log是不是就可以了
下面再补充一个知识点:
细心的朋友已经发现了我切面打印日志是用的获取Logger实例的方式打印的,原因是我切面类只有一个,所以我只需要在切面类获取一次Logger就行,那么如果不想用这种方式的话使用@Slf4j能不能实现呢?当然可以,下面就说下使用注解方式怎么做:
由于我们是只有切面里面的日志打印到http-aspect.log中,所以有两种方法:
1、配置扫描路径的方式
配置完扫描路径就可以直接使用@Slf4j打印了
2、通过在@Slf4j注解上使用topic指定logger-name即可
我的logger name是http-aspect
然后使用的时候在注解上通过topic字段指定该logger name
测试一下也是ok的
最后附加上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>