From 058341eff6071d8f5127273a6bbc9d3bcbceec0b Mon Sep 17 00:00:00 2001 From: zhendongyang Date: Tue, 28 May 2024 21:07:13 +0800 Subject: [PATCH] feat: manual operation log --- log-record-core/pom.xml | 38 ++++----- .../logRecord/aop/SystemLogAspect.java | 63 +-------------- .../logRecord/bean/LogRequest.java | 64 +++++++++++++++ .../handler/OperationLogHandler.java | 77 +++++++++++++++++++ .../logRecord/util/OperationLogUtil.java | 62 +++++++++++++++ .../logRecord/util/SpringContextUtil.java | 20 +++++ log-record-starter/pom.xml | 4 +- .../springboot/test/OperationLogUtilTest.java | 68 ++++++++++++++++ .../service/OperationLogNormalService.java | 5 ++ 9 files changed, 320 insertions(+), 81 deletions(-) create mode 100644 log-record-core/src/main/java/cn/monitor4all/logRecord/bean/LogRequest.java create mode 100644 log-record-core/src/main/java/cn/monitor4all/logRecord/handler/OperationLogHandler.java create mode 100644 log-record-core/src/main/java/cn/monitor4all/logRecord/util/OperationLogUtil.java create mode 100644 log-record-core/src/main/java/cn/monitor4all/logRecord/util/SpringContextUtil.java create mode 100644 log-record-starter/src/test/java/cn/monitor4all/logRecord/springboot/test/OperationLogUtilTest.java diff --git a/log-record-core/pom.xml b/log-record-core/pom.xml index 4852428..86de4a1 100644 --- a/log-record-core/pom.xml +++ b/log-record-core/pom.xml @@ -10,7 +10,7 @@ cn.monitor4all log-record-core - 1.6.3 + 1.7.0-SNAPSHOT 8 @@ -166,24 +166,24 @@ - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/log-record-core/src/main/java/cn/monitor4all/logRecord/aop/SystemLogAspect.java b/log-record-core/src/main/java/cn/monitor4all/logRecord/aop/SystemLogAspect.java index 08cdc4c..bc1cbe8 100644 --- a/log-record-core/src/main/java/cn/monitor4all/logRecord/aop/SystemLogAspect.java +++ b/log-record-core/src/main/java/cn/monitor4all/logRecord/aop/SystemLogAspect.java @@ -2,13 +2,10 @@ import cn.monitor4all.logRecord.annotation.OperationLog; import cn.monitor4all.logRecord.bean.LogDTO; -import cn.monitor4all.logRecord.configuration.LogRecordProperties; import cn.monitor4all.logRecord.context.LogRecordContext; import cn.monitor4all.logRecord.function.CustomFunctionRegistrar; -import cn.monitor4all.logRecord.service.DataPipelineService; -import cn.monitor4all.logRecord.service.IOperationLogGetService; +import cn.monitor4all.logRecord.handler.OperationLogHandler; import cn.monitor4all.logRecord.service.IOperatorIdGetService; -import cn.monitor4all.logRecord.service.LogRecordErrorHandlerService; import cn.monitor4all.logRecord.thread.LogRecordThreadPool; import cn.monitor4all.logRecord.util.JsonUtil; import com.alibaba.ttl.TtlRunnable; @@ -43,23 +40,14 @@ public class SystemLogAspect { @Autowired - private LogRecordProperties logRecordProperties; + private OperationLogHandler operationLogHandler; @Autowired(required = false) private LogRecordThreadPool logRecordThreadPool; - @Autowired(required = false) - private DataPipelineService dataPipelineService; - - @Autowired(required = false) - private IOperationLogGetService iOperationLogGetService; - @Autowired(required = false) private IOperatorIdGetService iOperatorIdGetService; - @Autowired(required = false) - private LogRecordErrorHandlerService logRecordErrorHandlerService; - private final SpelExpressionParser parser = new SpelExpressionParser(); private final DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer(); @@ -168,7 +156,7 @@ public Object doAround(ProceedingJoinPoint pjp) throws Throwable { try { // 提交日志至主线程或线程池 Long finalExecutionTime = executionTime; - Consumer createLogFunction = logDTO -> createLog(logDTO, finalExecutionTime); + Consumer createLogFunction = logDTO -> operationLogHandler.createLog(logDTO, finalExecutionTime); if (logRecordThreadPool != null) { logDTOList.forEach(logDTO -> { Runnable task = () -> createLogFunction.accept(logDTO); @@ -321,49 +309,4 @@ private Method getMethod(JoinPoint joinPoint) { } return method; } - - private void createLog(LogDTO logDTO, Long finalExecutionTime) { - int maxRetryTimes = logRecordProperties.getRetry().getRetryTimes(); - - // 发送日志本地监听 - boolean iOperationLogGetResult = false; - if (iOperationLogGetService != null) { - for (int retryTimes = 0; retryTimes <= maxRetryTimes; retryTimes++) { - try { - logDTO.setExecutionTime(finalExecutionTime); - iOperationLogGetResult = iOperationLogGetService.createLog(logDTO); - if (iOperationLogGetResult) { - break; - } - } catch (Throwable throwable) { - log.error("OperationLogAspect send logDTO error", throwable); - } - } - } - - if (!iOperationLogGetResult && iOperationLogGetService != null && logRecordErrorHandlerService != null) { - logRecordErrorHandlerService.operationLogGetErrorHandler(); - } - - // 发送消息管道 - boolean dataPipelineServiceResult = false; - if (dataPipelineService != null) { - for (int retryTimes = 0; retryTimes <= maxRetryTimes; retryTimes++) { - try { - logDTO.setExecutionTime(finalExecutionTime); - dataPipelineServiceResult = dataPipelineService.createLog(logDTO); - if (dataPipelineServiceResult) { - break; - } - } catch (Throwable throwable) { - log.error("OperationLogAspect send logDTO error", throwable); - } - } - } - - if (!dataPipelineServiceResult && dataPipelineService != null && logRecordErrorHandlerService != null) { - logRecordErrorHandlerService.dataPipelineErrorHandler(); - } - - } } diff --git a/log-record-core/src/main/java/cn/monitor4all/logRecord/bean/LogRequest.java b/log-record-core/src/main/java/cn/monitor4all/logRecord/bean/LogRequest.java new file mode 100644 index 0000000..16b0fd2 --- /dev/null +++ b/log-record-core/src/main/java/cn/monitor4all/logRecord/bean/LogRequest.java @@ -0,0 +1,64 @@ +package cn.monitor4all.logRecord.bean; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + +/** + * 日志请求实体 + * 用于非注解手动记录日志 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class LogRequest { + + /** + * 业务ID + */ + private String bizId; + /** + * 业务类型 + */ + private String bizType; + /** + * 方法异常信息 + */ + private String exception; + /** + * 日志操作时间 + */ + private Date operateDate; + /** + * 方法是否成功 + */ + private Boolean success; + /** + * 日志内容 + */ + private String msg; + /** + * 日志标签 + */ + private String tag; + /** + * 方法结果 + */ + private String returnStr; + /** + * 方法执行时间(单位:毫秒) + */ + private Long executionTime; + /** + * 额外信息 + */ + private String extra; + /** + * 操作人ID + */ + private String operatorId; +} diff --git a/log-record-core/src/main/java/cn/monitor4all/logRecord/handler/OperationLogHandler.java b/log-record-core/src/main/java/cn/monitor4all/logRecord/handler/OperationLogHandler.java new file mode 100644 index 0000000..1da55eb --- /dev/null +++ b/log-record-core/src/main/java/cn/monitor4all/logRecord/handler/OperationLogHandler.java @@ -0,0 +1,77 @@ +package cn.monitor4all.logRecord.handler; + + +import cn.monitor4all.logRecord.bean.LogDTO; +import cn.monitor4all.logRecord.configuration.LogRecordProperties; +import cn.monitor4all.logRecord.service.DataPipelineService; +import cn.monitor4all.logRecord.service.IOperationLogGetService; +import cn.monitor4all.logRecord.service.LogRecordErrorHandlerService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class OperationLogHandler { + + @Autowired + private LogRecordProperties logRecordProperties; + + @Autowired(required = false) + private DataPipelineService dataPipelineService; + + @Autowired(required = false) + private IOperationLogGetService iOperationLogGetService; + + @Autowired(required = false) + private LogRecordErrorHandlerService logRecordErrorHandlerService; + + public void createLog(LogDTO logDTO, Long finalExecutionTime) { + + // 重试次数 + int maxRetryTimes = logRecordProperties.getRetry().getRetryTimes(); + + // 发送本地日志 + boolean iOperationLogGetResult = false; + if (iOperationLogGetService != null) { + for (int retryTimes = 0; retryTimes <= maxRetryTimes; retryTimes++) { + try { + logDTO.setExecutionTime(finalExecutionTime); + iOperationLogGetResult = iOperationLogGetService.createLog(logDTO); + if (iOperationLogGetResult) { + break; + } + } catch (Throwable throwable) { + log.error("OperationLogAspect send logDTO error", throwable); + } + } + } + + // 发送本地日志失败错误处理 + if (!iOperationLogGetResult && iOperationLogGetService != null && logRecordErrorHandlerService != null) { + logRecordErrorHandlerService.operationLogGetErrorHandler(); + } + + // 发送消息管道 + boolean dataPipelineServiceResult = false; + if (dataPipelineService != null) { + for (int retryTimes = 0; retryTimes <= maxRetryTimes; retryTimes++) { + try { + logDTO.setExecutionTime(finalExecutionTime); + dataPipelineServiceResult = dataPipelineService.createLog(logDTO); + if (dataPipelineServiceResult) { + break; + } + } catch (Throwable throwable) { + log.error("OperationLogAspect send logDTO error", throwable); + } + } + } + + // 发送消息管道失败错误处理 + if (!dataPipelineServiceResult && dataPipelineService != null && logRecordErrorHandlerService != null) { + logRecordErrorHandlerService.dataPipelineErrorHandler(); + } + + } +} diff --git a/log-record-core/src/main/java/cn/monitor4all/logRecord/util/OperationLogUtil.java b/log-record-core/src/main/java/cn/monitor4all/logRecord/util/OperationLogUtil.java new file mode 100644 index 0000000..a1b9acf --- /dev/null +++ b/log-record-core/src/main/java/cn/monitor4all/logRecord/util/OperationLogUtil.java @@ -0,0 +1,62 @@ +package cn.monitor4all.logRecord.util; + + +import cn.monitor4all.logRecord.bean.LogDTO; +import cn.monitor4all.logRecord.bean.LogRequest; +import cn.monitor4all.logRecord.context.LogRecordContext; +import cn.monitor4all.logRecord.handler.OperationLogHandler; +import cn.monitor4all.logRecord.thread.LogRecordThreadPool; +import com.alibaba.ttl.TtlRunnable; +import lombok.extern.slf4j.Slf4j; + +import java.util.function.Consumer; + +/** + * 操作日志工具 + */ +@Slf4j +public class OperationLogUtil { + + private static final OperationLogHandler operationLogHandler = SpringContextUtil.getBean(OperationLogHandler.class); + private static final LogRecordThreadPool logRecordThreadPool = SpringContextUtil.getBean(LogRecordThreadPool.class); + + /** + * 生成LogDTO并交由框架统一处理 + */ + public static void log(LogRequest logRequest) { + + try { + LogDTO logDTO = generateLogDTO(logRequest); + Consumer createLogFunction = log -> operationLogHandler.createLog(log, logRequest.getExecutionTime()); + if (logRecordThreadPool != null) { + Runnable task = () -> createLogFunction.accept(logDTO); + Runnable ttlRunnable = TtlRunnable.get(task); + logRecordThreadPool.getLogRecordPoolExecutor().execute(ttlRunnable); + } else { + operationLogHandler.createLog(logDTO, logRequest.getExecutionTime()); + } + // 清除Context:每次方法执行一次 + LogRecordContext.clearContext(); + } catch (Throwable throwableFinal) { + log.error("OperationLogAspect send logDTO error", throwableFinal); + } + } + + private static LogDTO generateLogDTO(LogRequest logRequest) { + LogDTO logDTO = new LogDTO(); + logDTO.setBizId(logRequest.getBizId()); + logDTO.setBizType(logRequest.getBizType()); + logDTO.setException(logRequest.getException()); + logDTO.setOperateDate(logRequest.getOperateDate()); + logDTO.setSuccess(logRequest.getSuccess()); + logDTO.setMsg(logRequest.getMsg()); + logDTO.setTag(logRequest.getTag()); + logDTO.setReturnStr(logRequest.getReturnStr()); + logDTO.setExecutionTime(logRequest.getExecutionTime()); + logDTO.setExtra(logRequest.getExtra()); + logDTO.setOperatorId(logRequest.getOperatorId()); + return logDTO; + } + + +} diff --git a/log-record-core/src/main/java/cn/monitor4all/logRecord/util/SpringContextUtil.java b/log-record-core/src/main/java/cn/monitor4all/logRecord/util/SpringContextUtil.java new file mode 100644 index 0000000..f3be739 --- /dev/null +++ b/log-record-core/src/main/java/cn/monitor4all/logRecord/util/SpringContextUtil.java @@ -0,0 +1,20 @@ +package cn.monitor4all.logRecord.util; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class SpringContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + SpringContextUtil.applicationContext = applicationContext; + } + + public static T getBean(Class clazz) { + return applicationContext.getBean(clazz); + } +} diff --git a/log-record-starter/pom.xml b/log-record-starter/pom.xml index 28b9e43..f87d232 100644 --- a/log-record-starter/pom.xml +++ b/log-record-starter/pom.xml @@ -10,7 +10,7 @@ cn.monitor4all log-record-starter - 1.6.3 + 1.7.0-SNAPSHOT 8 @@ -35,7 +35,7 @@ cn.monitor4all log-record-core - 1.6.3 + 1.7.0-SNAPSHOT diff --git a/log-record-starter/src/test/java/cn/monitor4all/logRecord/springboot/test/OperationLogUtilTest.java b/log-record-starter/src/test/java/cn/monitor4all/logRecord/springboot/test/OperationLogUtilTest.java new file mode 100644 index 0000000..5003981 --- /dev/null +++ b/log-record-starter/src/test/java/cn/monitor4all/logRecord/springboot/test/OperationLogUtilTest.java @@ -0,0 +1,68 @@ +package cn.monitor4all.logRecord.springboot.test; + + +import cn.monitor4all.logRecord.bean.LogDTO; +import cn.monitor4all.logRecord.bean.LogRequest; +import cn.monitor4all.logRecord.springboot.LogRecordAutoConfiguration; +import cn.monitor4all.logRecord.springboot.test.service.OperatorIdGetService; +import cn.monitor4all.logRecord.springboot.test.service.TestService; +import cn.monitor4all.logRecord.springboot.test.utils.TestHelper; +import cn.monitor4all.logRecord.util.OperationLogUtil; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.context.annotation.PropertySource; +import org.springframework.test.context.ContextConfiguration; + +import java.util.Date; + +/** + * 单元测试:自定义线程池 + */ +@Slf4j +@SpringBootTest +@ContextConfiguration(classes = { + LogRecordAutoConfiguration.class, + OperatorIdGetService.class, + TestService.class,}) +@PropertySource("classpath:testNormal.properties") +@EnableAspectJAutoProxy(proxyTargetClass = true) +public class OperationLogUtilTest { + + @Test + public void testBuildLogRequest() { + TestHelper.addLock("testBuildLogRequest"); + Date date = new Date(); + LogRequest logRequest = LogRequest.builder() + .bizId("testBizId") + .bizType("testBuildLogRequest") + .exception("testException") + .operateDate(date) + .success(true) + .msg("testMsg") + .tag("testTag") + .returnStr("testReturnStr") + .executionTime(0L) + .extra("testExtra") + .operatorId("testOperatorId") + .build(); + OperationLogUtil.log(logRequest); + TestHelper.await("testBuildLogRequest"); + LogDTO logDTO = TestHelper.getLogDTO("testBuildLogRequest"); + + Assertions.assertEquals("testBizId", logDTO.getBizId()); + Assertions.assertEquals("testBuildLogRequest", logDTO.getBizType()); + Assertions.assertEquals("testException", logDTO.getException()); + Assertions.assertEquals(date, logDTO.getOperateDate()); + Assertions.assertEquals(true, logDTO.getSuccess()); + Assertions.assertEquals("testMsg", logDTO.getMsg()); + Assertions.assertEquals("testTag", logDTO.getTag()); + Assertions.assertEquals("testReturnStr", logDTO.getReturnStr()); + Assertions.assertEquals(0L, logDTO.getExecutionTime()); + Assertions.assertEquals("testExtra", logDTO.getExtra()); + Assertions.assertEquals("testOperatorId", logDTO.getOperatorId()); + } + +} diff --git a/log-record-starter/src/test/java/cn/monitor4all/logRecord/springboot/test/service/OperationLogNormalService.java b/log-record-starter/src/test/java/cn/monitor4all/logRecord/springboot/test/service/OperationLogNormalService.java index 5bf330c..349bd93 100644 --- a/log-record-starter/src/test/java/cn/monitor4all/logRecord/springboot/test/service/OperationLogNormalService.java +++ b/log-record-starter/src/test/java/cn/monitor4all/logRecord/springboot/test/service/OperationLogNormalService.java @@ -225,6 +225,11 @@ public boolean createLog(LogDTO logDTO) { TestHelper.releaseLock("testLogRecordContextTransmittableThreadLocal"); } + if ("testBuildLogRequest".equals(logDTO.getBizType())) { + TestHelper.putLogDTO("testBuildLogRequest", logDTO); + TestHelper.releaseLock("testBuildLogRequest"); + } + return true; } }