优化 yudao-spring-boot-starter-biz-operatelog 的封装,和 yudao-cloud 保持一致
parent
8174916c92
commit
284ee5000a
|
@ -34,6 +34,20 @@
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- RPC 远程调用相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.cloud</groupId>
|
||||||
|
<artifactId>yudao-spring-boot-starter-rpc</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 业务组件 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.cloud</groupId>
|
||||||
|
<artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行操作日志的记录 -->
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 工具类相关 -->
|
<!-- 工具类相关 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.guava</groupId>
|
<groupId>com.google.guava</groupId>
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package cn.iocoder.yudao.framework.operatelog.config;
|
package cn.iocoder.yudao.framework.operatelog.config;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect;
|
import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect;
|
||||||
|
import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService;
|
||||||
|
import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkServiceImpl;
|
||||||
|
import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@ -12,4 +15,9 @@ public class YudaoOperateLogAutoConfiguration {
|
||||||
return new OperateLogAspect();
|
return new OperateLogAspect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public OperateLogFrameworkService operateLogFrameworkService(OperateLogApi operateLogApi) {
|
||||||
|
return new OperateLogFrameworkServiceImpl(operateLogApi);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package cn.iocoder.yudao.framework.operatelog.config;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
|
||||||
|
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志使用到 Feign 的配置项
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@EnableFeignClients(clients = OperateLogApi.class) // 主要是引入相关的 API 服务
|
||||||
|
public class YudaoOperateLogRpcAutoConfiguration {
|
||||||
|
|
||||||
|
}
|
|
@ -9,9 +9,8 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO;
|
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
|
import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
|
||||||
|
import cn.iocoder.yudao.framework.operatelog.core.service.OperateLog;
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService;
|
import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService;
|
||||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
@ -57,13 +56,13 @@ public class OperateLogAspect {
|
||||||
/**
|
/**
|
||||||
* 用于记录操作内容的上下文
|
* 用于记录操作内容的上下文
|
||||||
*
|
*
|
||||||
* @see OperateLogCreateReqDTO#getContent()
|
* @see OperateLog#getContent()
|
||||||
*/
|
*/
|
||||||
private static final ThreadLocal<String> CONTENT = new ThreadLocal<>();
|
private static final ThreadLocal<String> CONTENT = new ThreadLocal<>();
|
||||||
/**
|
/**
|
||||||
* 用于记录拓展字段的上下文
|
* 用于记录拓展字段的上下文
|
||||||
*
|
*
|
||||||
* @see OperateLogCreateReqDTO#getExts()
|
* @see OperateLog#getExts()
|
||||||
*/
|
*/
|
||||||
private static final ThreadLocal<Map<String, Object>> EXTS = new ThreadLocal<>();
|
private static final ThreadLocal<Map<String, Object>> EXTS = new ThreadLocal<>();
|
||||||
|
|
||||||
|
@ -73,16 +72,20 @@ public class OperateLogAspect {
|
||||||
@Around("@annotation(apiOperation)")
|
@Around("@annotation(apiOperation)")
|
||||||
public Object around(ProceedingJoinPoint joinPoint, ApiOperation apiOperation) throws Throwable {
|
public Object around(ProceedingJoinPoint joinPoint, ApiOperation apiOperation) throws Throwable {
|
||||||
// 可能也添加了 @ApiOperation 注解
|
// 可能也添加了 @ApiOperation 注解
|
||||||
OperateLog operateLog = getMethodAnnotation(joinPoint, OperateLog.class);
|
cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog = getMethodAnnotation(joinPoint,
|
||||||
|
cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog.class);
|
||||||
return around0(joinPoint, operateLog, apiOperation);
|
return around0(joinPoint, operateLog, apiOperation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Around("!@annotation(io.swagger.annotations.ApiOperation) && @annotation(operateLog)") // 兼容处理,只添加 @OperateLog 注解的情况
|
@Around("!@annotation(io.swagger.annotations.ApiOperation) && @annotation(operateLog)") // 兼容处理,只添加 @OperateLog 注解的情况
|
||||||
public Object around(ProceedingJoinPoint joinPoint, OperateLog operateLog) throws Throwable {
|
public Object around(ProceedingJoinPoint joinPoint,
|
||||||
|
cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog) throws Throwable {
|
||||||
return around0(joinPoint, operateLog, null);
|
return around0(joinPoint, operateLog, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object around0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) throws Throwable {
|
private Object around0(ProceedingJoinPoint joinPoint,
|
||||||
|
cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog,
|
||||||
|
ApiOperation apiOperation) throws Throwable {
|
||||||
// 目前,只有管理员,才记录操作日志!所以非管理员,直接调用,不进行记录
|
// 目前,只有管理员,才记录操作日志!所以非管理员,直接调用,不进行记录
|
||||||
Integer userType = WebFrameworkUtils.getLoginUserType();
|
Integer userType = WebFrameworkUtils.getLoginUserType();
|
||||||
if (!Objects.equals(userType, UserTypeEnum.ADMIN.getValue())) {
|
if (!Objects.equals(userType, UserTypeEnum.ADMIN.getValue())) {
|
||||||
|
@ -121,7 +124,9 @@ public class OperateLogAspect {
|
||||||
EXTS.remove();
|
EXTS.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void log(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation,
|
private void log(ProceedingJoinPoint joinPoint,
|
||||||
|
cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog,
|
||||||
|
ApiOperation apiOperation,
|
||||||
Date startTime, Object result, Throwable exception) {
|
Date startTime, Object result, Throwable exception) {
|
||||||
try {
|
try {
|
||||||
// 判断不记录的情况
|
// 判断不记录的情况
|
||||||
|
@ -136,113 +141,119 @@ public class OperateLogAspect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void log0(ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation,
|
private void log0(ProceedingJoinPoint joinPoint,
|
||||||
|
cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog,
|
||||||
|
ApiOperation apiOperation,
|
||||||
Date startTime, Object result, Throwable exception) {
|
Date startTime, Object result, Throwable exception) {
|
||||||
OperateLogCreateReqDTO operateLogDTO = new OperateLogCreateReqDTO();
|
OperateLog operateLogObj = new OperateLog();
|
||||||
// 补全通用字段
|
// 补全通用字段
|
||||||
operateLogDTO.setTraceId(TracerUtils.getTraceId());
|
operateLogObj.setTraceId(TracerUtils.getTraceId());
|
||||||
operateLogDTO.setStartTime(startTime);
|
operateLogObj.setStartTime(startTime);
|
||||||
// 补充用户信息
|
// 补充用户信息
|
||||||
fillUserFields(operateLogDTO);
|
fillUserFields(operateLogObj);
|
||||||
// 补全模块信息
|
// 补全模块信息
|
||||||
fillModuleFields(operateLogDTO, joinPoint, operateLog, apiOperation);
|
fillModuleFields(operateLogObj, joinPoint, operateLog, apiOperation);
|
||||||
// 补全请求信息
|
// 补全请求信息
|
||||||
fillRequestFields(operateLogDTO);
|
fillRequestFields(operateLogObj);
|
||||||
// 补全方法信息
|
// 补全方法信息
|
||||||
fillMethodFields(operateLogDTO, joinPoint, operateLog, startTime, result, exception);
|
fillMethodFields(operateLogObj, joinPoint, operateLog, startTime, result, exception);
|
||||||
|
|
||||||
// 异步记录日志
|
// 异步记录日志
|
||||||
operateLogFrameworkService.createOperateLogAsync(operateLogDTO);
|
operateLogFrameworkService.createOperateLog(operateLogObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fillUserFields(OperateLogCreateReqDTO operateLogDTO) {
|
private static void fillUserFields(OperateLog operateLogObj) {
|
||||||
operateLogDTO.setUserId(WebFrameworkUtils.getLoginUserId());
|
operateLogObj.setUserId(WebFrameworkUtils.getLoginUserId());
|
||||||
operateLogDTO.setUserType(WebFrameworkUtils.getLoginUserType());
|
operateLogObj.setUserType(WebFrameworkUtils.getLoginUserType());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fillModuleFields(OperateLogCreateReqDTO operateLogDTO,
|
private static void fillModuleFields(OperateLog operateLogObj,
|
||||||
ProceedingJoinPoint joinPoint, OperateLog operateLog, ApiOperation apiOperation) {
|
ProceedingJoinPoint joinPoint,
|
||||||
|
cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog,
|
||||||
|
ApiOperation apiOperation) {
|
||||||
// module 属性
|
// module 属性
|
||||||
if (operateLog != null) {
|
if (operateLog != null) {
|
||||||
operateLogDTO.setModule(operateLog.module());
|
operateLogObj.setModule(operateLog.module());
|
||||||
}
|
}
|
||||||
if (StrUtil.isEmpty(operateLogDTO.getModule())) {
|
if (StrUtil.isEmpty(operateLogObj.getModule())) {
|
||||||
Api api = getClassAnnotation(joinPoint, Api.class);
|
Api api = getClassAnnotation(joinPoint, Api.class);
|
||||||
if (api != null) {
|
if (api != null) {
|
||||||
// 优先读取 @API 的 name 属性
|
// 优先读取 @API 的 name 属性
|
||||||
if (StrUtil.isNotEmpty(api.value())) {
|
if (StrUtil.isNotEmpty(api.value())) {
|
||||||
operateLogDTO.setModule(api.value());
|
operateLogObj.setModule(api.value());
|
||||||
}
|
}
|
||||||
// 没有的话,读取 @API 的 tags 属性
|
// 没有的话,读取 @API 的 tags 属性
|
||||||
if (StrUtil.isEmpty(operateLogDTO.getModule()) && ArrayUtil.isNotEmpty(api.tags())) {
|
if (StrUtil.isEmpty(operateLogObj.getModule()) && ArrayUtil.isNotEmpty(api.tags())) {
|
||||||
operateLogDTO.setModule(api.tags()[0]);
|
operateLogObj.setModule(api.tags()[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// name 属性
|
// name 属性
|
||||||
if (operateLog != null) {
|
if (operateLog != null) {
|
||||||
operateLogDTO.setName(operateLog.name());
|
operateLogObj.setName(operateLog.name());
|
||||||
}
|
}
|
||||||
if (StrUtil.isEmpty(operateLogDTO.getName()) && apiOperation != null) {
|
if (StrUtil.isEmpty(operateLogObj.getName()) && apiOperation != null) {
|
||||||
operateLogDTO.setName(apiOperation.value());
|
operateLogObj.setName(apiOperation.value());
|
||||||
}
|
}
|
||||||
// type 属性
|
// type 属性
|
||||||
if (operateLog != null && ArrayUtil.isNotEmpty(operateLog.type())) {
|
if (operateLog != null && ArrayUtil.isNotEmpty(operateLog.type())) {
|
||||||
operateLogDTO.setType(operateLog.type()[0].getType());
|
operateLogObj.setType(operateLog.type()[0].getType());
|
||||||
}
|
}
|
||||||
if (operateLogDTO.getType() == null) {
|
if (operateLogObj.getType() == null) {
|
||||||
RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint));
|
RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint));
|
||||||
OperateTypeEnum operateLogType = convertOperateLogType(requestMethod);
|
OperateTypeEnum operateLogType = convertOperateLogType(requestMethod);
|
||||||
operateLogDTO.setType(operateLogType != null ? operateLogType.getType() : null);
|
operateLogObj.setType(operateLogType != null ? operateLogType.getType() : null);
|
||||||
}
|
}
|
||||||
// content 和 exts 属性
|
// content 和 exts 属性
|
||||||
operateLogDTO.setContent(CONTENT.get());
|
operateLogObj.setContent(CONTENT.get());
|
||||||
operateLogDTO.setExts(EXTS.get());
|
operateLogObj.setExts(EXTS.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fillRequestFields(OperateLogCreateReqDTO operateLogDTO) {
|
private static void fillRequestFields(OperateLog operateLogObj) {
|
||||||
// 获得 Request 对象
|
// 获得 Request 对象
|
||||||
HttpServletRequest request = ServletUtils.getRequest();
|
HttpServletRequest request = ServletUtils.getRequest();
|
||||||
if (request == null) {
|
if (request == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 补全请求信息
|
// 补全请求信息
|
||||||
operateLogDTO.setRequestMethod(request.getMethod());
|
operateLogObj.setRequestMethod(request.getMethod());
|
||||||
operateLogDTO.setRequestUrl(request.getRequestURI());
|
operateLogObj.setRequestUrl(request.getRequestURI());
|
||||||
operateLogDTO.setUserIp(ServletUtil.getClientIP(request));
|
operateLogObj.setUserIp(ServletUtil.getClientIP(request));
|
||||||
operateLogDTO.setUserAgent(ServletUtils.getUserAgent(request));
|
operateLogObj.setUserAgent(ServletUtils.getUserAgent(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fillMethodFields(OperateLogCreateReqDTO operateLogDTO,
|
private static void fillMethodFields(OperateLog operateLogObj,
|
||||||
ProceedingJoinPoint joinPoint, OperateLog operateLog,
|
ProceedingJoinPoint joinPoint,
|
||||||
|
cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog,
|
||||||
Date startTime, Object result, Throwable exception) {
|
Date startTime, Object result, Throwable exception) {
|
||||||
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
|
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
|
||||||
operateLogDTO.setJavaMethod(methodSignature.toString());
|
operateLogObj.setJavaMethod(methodSignature.toString());
|
||||||
if (operateLog == null || operateLog.logArgs()) {
|
if (operateLog == null || operateLog.logArgs()) {
|
||||||
operateLogDTO.setJavaMethodArgs(obtainMethodArgs(joinPoint));
|
operateLogObj.setJavaMethodArgs(obtainMethodArgs(joinPoint));
|
||||||
}
|
}
|
||||||
if (operateLog == null || operateLog.logResultData()) {
|
if (operateLog == null || operateLog.logResultData()) {
|
||||||
operateLogDTO.setResultData(obtainResultData(result));
|
operateLogObj.setResultData(obtainResultData(result));
|
||||||
}
|
}
|
||||||
operateLogDTO.setDuration((int) (System.currentTimeMillis() - startTime.getTime()));
|
operateLogObj.setDuration((int) (System.currentTimeMillis() - startTime.getTime()));
|
||||||
// (正常)处理 resultCode 和 resultMsg 字段
|
// (正常)处理 resultCode 和 resultMsg 字段
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
if (result instanceof CommonResult) {
|
if (result instanceof CommonResult) {
|
||||||
CommonResult<?> commonResult = (CommonResult<?>) result;
|
CommonResult<?> commonResult = (CommonResult<?>) result;
|
||||||
operateLogDTO.setResultCode(commonResult.getCode());
|
operateLogObj.setResultCode(commonResult.getCode());
|
||||||
operateLogDTO.setResultMsg(commonResult.getMsg());
|
operateLogObj.setResultMsg(commonResult.getMsg());
|
||||||
} else {
|
} else {
|
||||||
operateLogDTO.setResultCode(SUCCESS.getCode());
|
operateLogObj.setResultCode(SUCCESS.getCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// (异常)处理 resultCode 和 resultMsg 字段
|
// (异常)处理 resultCode 和 resultMsg 字段
|
||||||
if (exception != null) {
|
if (exception != null) {
|
||||||
operateLogDTO.setResultCode(INTERNAL_SERVER_ERROR.getCode());
|
operateLogObj.setResultCode(INTERNAL_SERVER_ERROR.getCode());
|
||||||
operateLogDTO.setResultMsg(ExceptionUtil.getRootCauseMessage(exception));
|
operateLogObj.setResultMsg(ExceptionUtil.getRootCauseMessage(exception));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isLogEnable(ProceedingJoinPoint joinPoint, OperateLog operateLog) {
|
private static boolean isLogEnable(ProceedingJoinPoint joinPoint,
|
||||||
|
cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog operateLog) {
|
||||||
// 有 @OperateLog 注解的情况下
|
// 有 @OperateLog 注解的情况下
|
||||||
if (operateLog != null) {
|
if (operateLog != null) {
|
||||||
return operateLog.enable();
|
return operateLog.enable();
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
package cn.iocoder.yudao.framework.operatelog.core.service;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OperateLog {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 链路追踪编号
|
||||||
|
*/
|
||||||
|
private String traceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户编号
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
/**
|
||||||
|
* 用户类型
|
||||||
|
*/
|
||||||
|
private Integer userType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作模块
|
||||||
|
*/
|
||||||
|
private String module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作名
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作分类
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作明细
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拓展字段
|
||||||
|
*/
|
||||||
|
private Map<String, Object> exts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求方法名
|
||||||
|
*/
|
||||||
|
private String requestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求地址
|
||||||
|
*/
|
||||||
|
private String requestUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户 IP
|
||||||
|
*/
|
||||||
|
private String userIp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 浏览器 UserAgent
|
||||||
|
*/
|
||||||
|
private String userAgent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java 方法名
|
||||||
|
*/
|
||||||
|
private String javaMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java 方法的参数
|
||||||
|
*/
|
||||||
|
private String javaMethodArgs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始时间
|
||||||
|
*/
|
||||||
|
private Date startTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行时长,单位:毫秒
|
||||||
|
*/
|
||||||
|
private Integer duration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结果码
|
||||||
|
*/
|
||||||
|
private Integer resultCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结果提示
|
||||||
|
*/
|
||||||
|
private String resultMsg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结果数据
|
||||||
|
*/
|
||||||
|
private String resultData;
|
||||||
|
|
||||||
|
}
|
|
@ -1,17 +1,17 @@
|
||||||
package cn.iocoder.yudao.framework.operatelog.core.service;
|
package cn.iocoder.yudao.framework.operatelog.core.service;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO;
|
/**
|
||||||
|
* 操作日志 Framework Service 接口
|
||||||
import java.util.concurrent.Future;
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
public interface OperateLogFrameworkService {
|
public interface OperateLogFrameworkService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异步记录操作日志
|
* 异步记录操作日志
|
||||||
*
|
*
|
||||||
* @param reqVO 操作日志请求
|
* @param operateLog 操作日志请求
|
||||||
* @return true: 记录成功,false: 记录失败
|
|
||||||
*/
|
*/
|
||||||
Future<Boolean> createOperateLogAsync(OperateLogCreateReqDTO reqVO);
|
void createOperateLog(OperateLog operateLog);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package cn.iocoder.yudao.framework.operatelog.core.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志 Framework Service 实现类
|
||||||
|
*
|
||||||
|
* 基于 {@link OperateLogApi} 远程服务,记录操作日志
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class OperateLogFrameworkServiceImpl implements OperateLogFrameworkService {
|
||||||
|
|
||||||
|
private final OperateLogApi operateLogApi;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Async
|
||||||
|
public void createOperateLog(OperateLog operateLog) {
|
||||||
|
OperateLogCreateReqDTO reqDTO = BeanUtil.copyProperties(operateLog, OperateLogCreateReqDTO.class);
|
||||||
|
CommonResult<Boolean> result = operateLogApi.createOperateLog(reqDTO);
|
||||||
|
result.checkError();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,2 +1,3 @@
|
||||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
|
cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogRpcAutoConfiguration,\
|
||||||
cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogAutoConfiguration
|
cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogAutoConfiguration
|
||||||
|
|
|
@ -19,7 +19,7 @@ Authorization: Bearer {{token}}
|
||||||
}
|
}
|
||||||
|
|
||||||
### 请求 /infra/file-config/update 接口 => 成功
|
### 请求 /infra/file-config/update 接口 => 成功
|
||||||
PUT {{baseUrl}}/infra/file-config/update
|
PUT {{infaBaseUrl}}/infra/file-config/update
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
tenant-id: {{adminTenentId}}
|
tenant-id: {{adminTenentId}}
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
|
|
|
@ -1,27 +1,14 @@
|
||||||
package cn.iocoder.yudao.module.infra.framework;
|
package cn.iocoder.yudao.module.infra.framework;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO;
|
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService;
|
|
||||||
import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
|
import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Future;
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class TmpConfiguration {
|
public class TmpConfiguration {
|
||||||
|
|
||||||
@Bean
|
|
||||||
public OperateLogFrameworkService operateLogFrameworkService() {
|
|
||||||
return new OperateLogFrameworkService() {
|
|
||||||
@Override
|
|
||||||
public Future<Boolean> createOperateLogAsync(OperateLogCreateReqDTO reqVO) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public TenantFrameworkService tenantFrameworkService() {
|
public TenantFrameworkService tenantFrameworkService() {
|
||||||
return new TenantFrameworkService() {
|
return new TenantFrameworkService() {
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package cn.iocoder.yudao.module.system.api.logger;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||||
|
import cn.iocoder.yudao.module.system.enums.ApiConstants;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
||||||
|
@Api(tags = "RPC 服务 - 操作日志")
|
||||||
|
public interface OperateLogApi {
|
||||||
|
|
||||||
|
String PREFIX = ApiConstants.PREFIX + "/operate-log";
|
||||||
|
|
||||||
|
@PostMapping(PREFIX + "/create")
|
||||||
|
@ApiOperation("创建操作日志")
|
||||||
|
CommonResult<Boolean> createOperateLog(@Valid @RequestBody OperateLogCreateReqDTO createReqDTO);
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package cn.iocoder.yudao.framework.operatelog.core.dto;
|
package cn.iocoder.yudao.module.system.api.logger.dto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
@ -8,14 +9,11 @@ import javax.validation.constraints.NotNull;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
@ApiModel("操作日志创建 Request DTO")
|
||||||
* 操作日志创建 Request DTO
|
|
||||||
*/
|
|
||||||
@Data
|
@Data
|
||||||
public class OperateLogCreateReqDTO {
|
public class OperateLogCreateReqDTO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab")
|
@ApiModelProperty(value = "链路追踪编号", required = true, example = "89aca178-a370-411c-ae02-3f0d672be4ab")
|
||||||
@NotEmpty(message = "链路追踪编号不能为空")
|
|
||||||
private String traceId;
|
private String traceId;
|
||||||
|
|
||||||
@ApiModelProperty(value = "用户编号", required = true, example = "1024")
|
@ApiModelProperty(value = "用户编号", required = true, example = "1024")
|
|
@ -0,0 +1,29 @@
|
||||||
|
package cn.iocoder.yudao.module.system.api.logger;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||||
|
import cn.iocoder.yudao.module.system.service.logger.OperateLogService;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboService;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
import static cn.iocoder.yudao.module.system.enums.ApiConstants.VERSION;
|
||||||
|
|
||||||
|
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||||
|
@DubboService(version = VERSION) // 提供 Dubbo RPC 接口,给 Dubbo Consumer 调用
|
||||||
|
@Validated
|
||||||
|
public class OperateLogApiImpl implements OperateLogApi {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OperateLogService operateLogService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> createOperateLog(OperateLogCreateReqDTO createReqDTO) {
|
||||||
|
operateLogService.createOperateLog(createReqDTO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,11 +1,12 @@
|
||||||
### 请求 /system/sms-template/send-sms 接口 => 成功
|
### 请求 /system/sms-template/send-sms 接口 => 成功
|
||||||
POST {{baseUrl}}/system/sms-template/send-sms
|
POST {{systemBaseUrl}}/system/sms-template/send-sms
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
tenant-id: {{adminTenentId}}
|
tenant-id: {{adminTenentId}}
|
||||||
|
|
||||||
{
|
{
|
||||||
"code": "test_01",
|
"templateCode": "test_01",
|
||||||
|
"mobile": "156016913900",
|
||||||
"params": {
|
"params": {
|
||||||
"key01": "value01",
|
"key01": "value01",
|
||||||
"key02": "value02"
|
"key02": "value02"
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package cn.iocoder.yudao.module.system.convert.logger;
|
package cn.iocoder.yudao.module.system.convert.logger;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||||
|
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExcelVO;
|
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExcelVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO;
|
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO;
|
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,29 @@
|
||||||
package cn.iocoder.yudao.module.system.service.logger;
|
package cn.iocoder.yudao.module.system.service.logger;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.operatelog.core.service.OperateLog;
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService;
|
import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService;
|
||||||
|
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 操作日志 Service 接口
|
* 操作日志 Service 接口
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
public interface OperateLogService extends OperateLogFrameworkService {
|
public interface OperateLogService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录操作日志
|
||||||
|
*
|
||||||
|
* @param createReqDTO 操作日志请求
|
||||||
|
*/
|
||||||
|
void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得操作日志分页列表
|
* 获得操作日志分页列表
|
||||||
|
|
|
@ -4,7 +4,8 @@ import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO;
|
import cn.iocoder.yudao.framework.operatelog.core.service.OperateLog;
|
||||||
|
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
|
||||||
import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert;
|
import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert;
|
||||||
|
@ -40,19 +41,11 @@ public class OperateLogServiceImpl implements OperateLogService {
|
||||||
private AdminUserService userService;
|
private AdminUserService userService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Async
|
public void createOperateLog(OperateLogCreateReqDTO createReqDTO) {
|
||||||
public Future<Boolean> createOperateLogAsync(OperateLogCreateReqDTO reqVO) {
|
OperateLogDO logDO = OperateLogConvert.INSTANCE.convert(createReqDTO);
|
||||||
boolean success = false;
|
logDO.setJavaMethodArgs(StrUtils.maxLength(logDO.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH));
|
||||||
try {
|
logDO.setResultData(StrUtils.maxLength(logDO.getResultData(), RESULT_MAX_LENGTH));
|
||||||
OperateLogDO logDO = OperateLogConvert.INSTANCE.convert(reqVO);
|
operateLogMapper.insert(logDO);
|
||||||
logDO.setJavaMethodArgs(StrUtils.maxLength(logDO.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH));
|
|
||||||
logDO.setResultData(StrUtils.maxLength(logDO.getResultData(), RESULT_MAX_LENGTH));
|
|
||||||
success = operateLogMapper.insert(logDO) == 1;
|
|
||||||
} catch (Throwable throwable) {
|
|
||||||
// 仅仅打印日志,不对外抛出。原因是,还是要保留现场数据。
|
|
||||||
log.error("[createOperateLogAsync][记录操作日志异常,日志为 ({})]", reqVO, throwable);
|
|
||||||
}
|
|
||||||
return new AsyncResult<>(success);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,9 +7,10 @@ import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstant
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.dto.OperateLogCreateReqDTO;
|
import cn.iocoder.yudao.framework.operatelog.core.service.OperateLog;
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
|
import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
|
||||||
import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
|
import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
|
||||||
|
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
|
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
|
||||||
|
@ -49,7 +50,7 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest {
|
||||||
private AdminUserService userService;
|
private AdminUserService userService;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateOperateLogAsync() throws InterruptedException, ExecutionException {
|
public void testCreateOperateLogAsync() {
|
||||||
String traceId = TracerUtils.getTraceId();
|
String traceId = TracerUtils.getTraceId();
|
||||||
OperateLogCreateReqDTO reqVO = RandomUtils.randomPojo(OperateLogCreateReqDTO.class, o -> {
|
OperateLogCreateReqDTO reqVO = RandomUtils.randomPojo(OperateLogCreateReqDTO.class, o -> {
|
||||||
o.setTraceId(traceId);
|
o.setTraceId(traceId);
|
||||||
|
@ -59,8 +60,7 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest {
|
||||||
});
|
});
|
||||||
|
|
||||||
// 执行service方法
|
// 执行service方法
|
||||||
Future<Boolean> future = operateLogServiceImpl.createOperateLogAsync(reqVO);
|
operateLogServiceImpl.createOperateLog(reqVO);
|
||||||
future.get();
|
|
||||||
// 断言插入是否正确
|
// 断言插入是否正确
|
||||||
OperateLogDO sysOperateLogDO = operateLogMapper.selectOne("trace_id", traceId);
|
OperateLogDO sysOperateLogDO = operateLogMapper.selectOne("trace_id", traceId);
|
||||||
assertPojoEquals(reqVO, sysOperateLogDO);
|
assertPojoEquals(reqVO, sysOperateLogDO);
|
||||||
|
|
Loading…
Reference in New Issue