首先是目录结构

logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds" debug="false">
<!-- <!–引用公共日志–>-->
<include resource="logback/logback-base.xml"/>
<!-- <!– 开发环境配置 –>-->
<springProfile name="dev">
<!-- 引用开发环境日志配置 -->
<include resource="logback/logback-dev.xml"/>
</springProfile>
<!-- <!– 生产环境配置 –>-->
<springProfile name="prod">
<!-- 引用生产环境日志配置 -->
<include resource="logback/logback-prod.xml"/>
</springProfile>
</configuration>
logback-base.xml
<included>
<!-- 最大文件大小-->
<springProperty name="LOGGER_FILE_MAX_SIZE" scope="context" source="logback.filesize" defaultValue="5MB"/>
<!-- 文件最大保存时间-->
<springProperty name="LOGGER_FILE_MAX_DAY" scope="context" source="logback.filemaxday" defaultValue="2"/>
<!-- 日志保留地址-->
<property name="LOGGER_FILE_PATH" value="logs"/>
<!--日志编码-->
<property name="CHARSET" value="utf-8"/>
<!-- 最大保留文件容量 -->
<property name="TOTAL_SIZE_CAP" value="1GB" />
<!-- 日志输出格式-->
<property name="LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} %level ${PID} [%thread] %logger %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wex}"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
</included>
logback-dev.xml
<included>
<property name="DEV_LOGGER_LEVEL" value="DEBUG"/>
<!-- 控制台彩色日志格式 -->
<property name="CONSOLE-LOG-PATTERN"
value="%red(%date{yyyy-MM-dd HH:mm:ss}) %highlight(%-5level) %red([%thread]) %boldMagenta(%logger{50}) %cyan(%msg%n)"/>
<appender name="stdoutAppender" class="ch.qos.logback.core.ConsoleAppender">
<withJansi>true</withJansi>
<encoder>
<pattern>${CONSOLE-LOG-PATTERN}</pattern>
<charset>${CHARSET}</charset>
</encoder>
</appender>
<appender name="console-async-appender" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<appender-ref ref="stdoutAppender"/>
</appender>
<root level="${DEV_LOGGER_LEVEL}" additivity="false">
<appender-ref ref="console-async-appender"/>
</root>
</included>
logback-prod.xml
<included>
<property name="PROD_LOGGER_LEVEL" value="INFO"/>
<appender name="data-appender-error" class="ch.qos.logback.classic.sift.SiftingAppender">
<discriminator>
<key>jobName</key>
<defaultValue>system</defaultValue>
</discriminator>
<sift>
<appender name="${jobName}-error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
<charset>${CHARSET}</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOGGER_FILE_PATH}/${jobName}.%d{yyyy-MM-dd}.%i.error</fileNamePattern>
<maxHistory>${LOGGER_FILE_MAX_DAY}</maxHistory>
<maxFileSize>${LOGGER_FILE_MAX_SIZE}</maxFileSize>
<totalSizeCap>${TOTAL_SIZE_CAP}</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
</appender>
</sift>
</appender>
<appender name="data-appender-info" class="ch.qos.logback.classic.sift.SiftingAppender">
<discriminator>
<key>jobName</key>
<defaultValue>system</defaultValue>
</discriminator>
<sift>
<appender name="${jobName}-info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
<charset>${CHARSET}</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOGGER_FILE_PATH}/${jobName}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxHistory>${LOGGER_FILE_MAX_DAY}</maxHistory>
<maxFileSize>${LOGGER_FILE_MAX_SIZE}</maxFileSize>
<totalSizeCap>${TOTAL_SIZE_CAP}</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!--过滤 Error-->
<level>ERROR</level>
<!--匹配到就禁止-->
<onMatch>DENY</onMatch>
<!--没有匹配到就允许-->
<onMismatch>ACCEPT</onMismatch>
</filter>
</appender>
</sift>
</appender>
<appender name="file_async" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<appender-ref ref="data-appender-info"/>
</appender>
<appender name="error_file_async" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<appender-ref ref="data-appender-error"/>
</appender>
<logger name="根路径" level="error" additivity="false">
<appender-ref ref="error_file_async"/>
</logger>
<logger name="根路径" level="${PROD_LOGGER_LEVEL}" additivity="false">
<appender-ref ref="file_async"/>
</logger>
<root level="${PROD_LOGGER_LEVEL}">
<appender-ref ref="file_async"/>
<appender-ref ref="error_file_async"/>
</root>
</included>
最后是注解的实现,技术是logback的Mdc,只要任务在同一个线程内就可以实现日志区分
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MdcLogger {
/**
* logger MDC对应的value值
* @return
*/
String value();
}
Aop的实现
@Aspect
@Component
public class MdcLoggerAspect {
private static Logger logger = LoggerFactory.getLogger(MdcLoggerAspect.class);
/**
* 切入点
*/
@Pointcut("@annotation(com.lz.bigdata.synchronizer.biz.dy.domain.annotation.MdcLogger)")
public void mdcLoggerCutPoint() {
logger.info("MDC切入点");
}
@Before("mdcLoggerCutPoint()")
public void mdcLoggerBefore(JoinPoint joinPoint) {
MdcLogger mdcLoggerAnnotation = ((MethodSignature) joinPoint.getSignature()).getMethod().getDeclaredAnnotation(MdcLogger.class);
String value = mdcLoggerAnnotation.value();
// String methodName = joinPoint.getTarget().getClass().getSimpleName() + "." + joinPoint.getSignature().getName();
MDC.put(配置文件定义的名称(此文章是jobName), value);
}
@After("mdcLoggerCutPoint()")
public void mdcLoggerAfter() {
MDC.clear();
}
}
版权声明:本文为weixin_43836438原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。