一,创建注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface StrategyOperateLog {
}
二、创建AOP类,关联注解
@Aspect
@Component
public class LoggingAspect {
private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);
@Before("@annotation(org.ethh.common.annotation.StrategyOperateLog)")
public void logExecutionTime(JoinPoint joinPoint) {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = methodSignature.getParameterNames();
Object[] parameterValues = joinPoint.getArgs();
StringBuilder params = new StringBuilder();
for (int i = 0; i < parameterNames.length; i++) {
params.append(parameterNames[i]).append(": ").append(parameterValues[i]).append(", ");
}
logger.info("Executing method: {} with parameters: {}", joinPoint.getSignature().toShortString(), params.toString());
}
@AfterReturning(pointcut = "@annotation(org.ethh.common.annotation.StrategyOperateLog)", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
logger.info("Method execution completed: {}", joinPoint.getSignature().toShortString());
logger.info("Returned value: {}", result);
}
@AfterThrowing(pointcut = "@annotation(org.ethh.common.annotation.StrategyOperateLog)", throwing = "exception")
public void logAfterThrowing(JoinPoint joinPoint, Throwable exception) {
logger.error("Exception in method: {}", joinPoint.getSignature().toShortString());
logger.error("Exception message: {}", exception.getMessage());
}
}
之后在需要记录日志的方法上增加注解即可
@StrategyOperateLog
public ApiResponse<String> test() {
xxx
}
三、日志配置
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<configuration>
<property name="LOG_HOME" value="${log.home:-./logs}"/>
<property name="LOG_APP_NAME" value="${log.app-name:-core}"/>
<property name="MAX_SINGLE_LOG_FILE_SIZE" value="${log.max-single-log-file-size:-100MB}"/>
<property name="MAX_LOG_FILE_HISTORY" value="${log.max-log-file-history:-180}"/>
<property name="LOG_FILE_TOTAL_CAPACITY" value="${log.log-file-total-capacity:-10GB}"/>
<property name="ASYNC_DISCARDING_THRESHOLD" value="${log.async.discarding-threshold:-0}"/>
<property name="ASYNC_LOG_QUEUE_SIZE" value="${log.async.queue-size:-512}"/>
<property name="LOG_PATTERN" value="%red(%d{yyyy-MM-dd HH:mm:ss.SSS}) %highlight([%X{traceId}]) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger) - %cyan(%msg%n)"/>
<property name="LOG_PATTERN_FILE" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] [%thread] %-5level %logger - %msg%n"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="ASYNC_STDOUT" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>${ASYNC_DISCARDING_THRESHOLD}</discardingThreshold>
<queueSize>${ASYNC_LOG_QUEUE_SIZE}</queueSize>
<includeCallerData>false</includeCallerData>
<appender-ref ref="STDOUT"/>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/${LOG_APP_NAME}.log</file>
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/${LOG_APP_NAME}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
<maxFileSize>${MAX_SINGLE_LOG_FILE_SIZE}</maxFileSize>
<maxHistory>${MAX_LOG_FILE_HISTORY}</maxHistory>
<totalSizeCap>${LOG_FILE_TOTAL_CAPACITY}</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${LOG_PATTERN_FILE}</pattern>
</encoder>
</appender>
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>${ASYNC_DISCARDING_THRESHOLD}</discardingThreshold>
<queueSize>${ASYNC_LOG_QUEUE_SIZE}</queueSize>
<includeCallerData>true</includeCallerData>
<appender-ref ref="FILE"/>
</appender>
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>${LOG_HOME}/${LOG_APP_NAME}-error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/${LOG_APP_NAME}.%d{yyyy-MM-dd}-error.%i.log.zip</fileNamePattern>
<maxFileSize>${MAX_SINGLE_LOG_FILE_SIZE}</maxFileSize>
<maxHistory>${MAX_LOG_FILE_HISTORY}</maxHistory>
<totalSizeCap>${LOG_FILE_TOTAL_CAPACITY}</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${LOG_PATTERN_FILE}</pattern>
</encoder>
</appender>
<appender name="ASYNC_ERROR_FILE" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>${ASYNC_DISCARDING_THRESHOLD}</discardingThreshold>
<queueSize>${ASYNC_LOG_QUEUE_SIZE}</queueSize>
<includeCallerData>false</includeCallerData>
<appender-ref ref="ERROR_FILE"/>
</appender>
<root level="INFO">
<appender-ref ref="ASYNC_STDOUT"/>
<appender-ref ref="ASYNC_FILE"/>
<appender-ref ref="ASYNC_ERROR_FILE"/>
</root>
</configuration>