refactor: 优化系统日志收集方式

This commit is contained in:
fit2-zhao 2023-06-13 19:35:24 +08:00 committed by fit2-zhao
parent 103cb3e999
commit 2d7bbc53f9
4 changed files with 100 additions and 47 deletions

View File

@ -21,11 +21,11 @@ public @interface RequestLog {
String module() default OperationLogModule.UNKNOWN_MODULE; String module() default OperationLogModule.UNKNOWN_MODULE;
/** /**
* 项目 * 项目系统模块没有项目id默认系统
* *
* @return * @return
*/ */
String projectId() default "default"; String projectId() default "system";
/** /**
* 操作类型 * 操作类型
@ -61,11 +61,11 @@ public @interface RequestLog {
boolean isBatch() default false; boolean isBatch() default false;
/** /**
* 操作前触发内容 * 是否在业务代码执行前记录内容
* *
* @return * @return
*/ */
String event() default ""; boolean isBefore() default false;
/** /**
* 传入执行类 * 传入执行类

View File

@ -57,6 +57,11 @@ public class OperationLogAspect {
private OperationLogService operationLogService; private OperationLogService operationLogService;
private ThreadLocal<List<OperationLog>> beforeValue = new ThreadLocal<>(); private ThreadLocal<List<OperationLog>> beforeValue = new ThreadLocal<>();
private ThreadLocal<String> treadLocalDetails = new ThreadLocal<>();
private ThreadLocal<String> treadLocalSourceId = new ThreadLocal<>();
private ThreadLocal<String> localUser = new ThreadLocal<>(); private ThreadLocal<String> localUser = new ThreadLocal<>();
private final String[] methodNames = new String[]{"delete", "update", "add"}; private final String[] methodNames = new String[]{"delete", "update", "add"};
@ -76,13 +81,14 @@ public class OperationLogAspect {
//获取切入点所在的方法 //获取切入点所在的方法
Method method = signature.getMethod(); Method method = signature.getMethod();
RequestLog msLog = method.getAnnotation(RequestLog.class); RequestLog msLog = method.getAnnotation(RequestLog.class);
if (msLog != null && StringUtils.isNotEmpty(msLog.event())) { if (msLog != null && msLog.isBefore()) {
//获取参数对象数组 //获取参数对象数组
Object[] args = joinPoint.getArgs(); Object[] args = joinPoint.getArgs();
//获取方法参数名 //获取方法参数名
String[] params = discoverer.getParameterNames(method); String[] params = discoverer.getParameterNames(method);
//将参数纳入Spring管理 //将参数纳入Spring管理
EvaluationContext context = new StandardEvaluationContext(); EvaluationContext context = new StandardEvaluationContext();
for (int len = 0; len < params.length; len++) { for (int len = 0; len < params.length; len++) {
context.setVariable(params[len], args[len]); context.setVariable(params[len], args[len]);
} }
@ -95,11 +101,13 @@ public class OperationLogAspect {
context.setVariable("msClass", applicationContext.getBean(clazz)); context.setVariable("msClass", applicationContext.getBean(clazz));
isNext = true; isNext = true;
} }
if (isNext) { if (!isNext) {
Expression expression = parser.parseExpression(msLog.event()); return;
List<OperationLog> beforeContent = expression.getValue(context, List.class);
beforeValue.set(beforeContent);
} }
// 初始化details内容
initDetails(msLog, context);
// 初始化资源id
initResourceId(msLog, context);
} }
} catch (Exception e) { } catch (Exception e) {
LogUtils.error("操作日志写入异常:" + joinPoint.getSignature()); LogUtils.error("操作日志写入异常:" + joinPoint.getSignature());
@ -111,6 +119,65 @@ public class OperationLogAspect {
.anyMatch(input -> input.contains(keyword)); .anyMatch(input -> input.contains(keyword));
} }
private void initDetails(RequestLog msLog, EvaluationContext context) {
try {
// 批量内容处理
if (StringUtils.isNotBlank(msLog.details()) && msLog.details().startsWith("#msClass")) {
if (msLog.isBatch()) {
Expression expression = parser.parseExpression(msLog.details());
List<OperationLog> beforeContent = expression.getValue(context, List.class);
beforeValue.set(beforeContent);
} else {
Expression detailsEx = parser.parseExpression(msLog.details());
String details = detailsEx.getValue(context, String.class);
this.treadLocalDetails.set(details);
}
} else if (StringUtils.isNotBlank(msLog.details()) && msLog.details().startsWith("#")) {
Expression titleExp = parser.parseExpression(msLog.details());
String details = titleExp.getValue(context, String.class);
this.treadLocalDetails.set(details);
} else {
this.treadLocalDetails.set(msLog.details());
}
} catch (Exception e) {
LogUtils.error("未获取到details内容", e);
this.treadLocalDetails.set(msLog.details());
}
}
private void initResourceId(RequestLog msLog, EvaluationContext context) {
try {
// 批量内容处理
if (StringUtils.isNotBlank(msLog.sourceId()) && msLog.sourceId().startsWith("#msClass")) {
Expression detailsEx = parser.parseExpression(msLog.sourceId());
String sourceId = detailsEx.getValue(context, String.class);
treadLocalSourceId.set(sourceId);
} else if (StringUtils.isNotBlank(msLog.sourceId()) && msLog.sourceId().startsWith("#")) {
Expression titleExp = parser.parseExpression(msLog.sourceId());
String sourceId = titleExp.getValue(context, String.class);
treadLocalSourceId.set(sourceId);
} else {
treadLocalSourceId.set(msLog.sourceId());
}
} catch (Exception e) {
LogUtils.error("未获取到资源id", e);
treadLocalSourceId.set(msLog.sourceId());
}
}
private String getProjectId(RequestLog msLog, EvaluationContext context) {
try {
if (StringUtils.isNotBlank(msLog.projectId()) && msLog.projectId().startsWith("#")) {
Expression titleExp = parser.parseExpression(msLog.projectId());
return titleExp.getValue(context, String.class);
} else {
return msLog.projectId();
}
} catch (Exception e) {
return msLog.projectId();
}
}
private void add(OperationLog operationLog, RequestLog msLog, JoinPoint joinPoint, Object result) { private void add(OperationLog operationLog, RequestLog msLog, JoinPoint joinPoint, Object result) {
//从切面织入点处通过反射机制获取织入点处的方法 //从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); MethodSignature signature = (MethodSignature) joinPoint.getSignature();
@ -143,38 +210,23 @@ public class OperationLogAspect {
return; return;
} }
// 项目ID表达式 // 项目ID表达式
try { operationLog.setProjectId(getProjectId(msLog, context));
Expression titleExp = parser.parseExpression(msLog.projectId());
String project = titleExp.getValue(context, String.class); if (!msLog.isBefore()) {
operationLog.setProjectId(project); // 初始化资源id
} catch (Exception e) { initResourceId(msLog, context);
operationLog.setProjectId(msLog.projectId()); // 初始化内容详情
} initDetails(msLog, context);
// 标题
if (StringUtils.isNotEmpty(msLog.details())) {
String details = msLog.details();
try {
Expression titleExp = parser.parseExpression(details);
details = titleExp.getValue(context, String.class);
operationLog.setDetails(details);
} catch (Exception e) {
operationLog.setDetails(details);
}
}
// 资源ID
if (StringUtils.isNotEmpty(msLog.sourceId())) {
try {
String sourceId = msLog.sourceId();
Expression titleExp = parser.parseExpression(sourceId);
sourceId = titleExp.getValue(context, String.class);
operationLog.setSourceId(sourceId);
} catch (Exception e) {
operationLog.setSourceId(msLog.sourceId());
}
} }
// 内容详情
operationLog.setDetails(treadLocalDetails.get());
// 资源id
operationLog.setSourceId(treadLocalSourceId.get());
if (StringUtils.isBlank(operationLog.getCreateUser())) { if (StringUtils.isBlank(operationLog.getCreateUser())) {
operationLog.setCreateUser(localUser.get()); operationLog.setCreateUser(localUser.get());
} }
// 从返回内容中获取资源id
if (StringUtils.isEmpty(operationLog.getSourceId()) && !msLog.isBatch()) { if (StringUtils.isEmpty(operationLog.getSourceId()) && !msLog.isBatch()) {
operationLog.setSourceId(getId(result)); operationLog.setSourceId(getId(result));
} }
@ -217,11 +269,8 @@ public class OperationLogAspect {
operationLog.setMethod(StringUtils.join(className, ".", method.getName())); operationLog.setMethod(StringUtils.join(className, ".", method.getName()));
operationLog.setCreateTime(System.currentTimeMillis()); operationLog.setCreateTime(System.currentTimeMillis());
operationLog.setCreateUser(SessionUtils.getUserId()); operationLog.setCreateUser(SessionUtils.getUserId());
HttpServletRequest request = ((ServletRequestAttributes) HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
RequestContextHolder.getRequestAttributes()).getRequest(); operationLog.setPath(request.getServletPath());
String path = request.getServletPath();
operationLog.setPath(path);
// 获取操作 // 获取操作
RequestLog msLog = method.getAnnotation(RequestLog.class); RequestLog msLog = method.getAnnotation(RequestLog.class);
if (msLog != null) { if (msLog != null) {
@ -236,6 +285,7 @@ public class OperationLogAspect {
} finally { } finally {
localUser.remove(); localUser.remove();
beforeValue.remove(); beforeValue.remove();
treadLocalDetails.remove();
} }
} }

View File

@ -30,8 +30,8 @@ public class OperationLogService {
log.setCreateUser("admin"); log.setCreateUser("admin");
} }
// 限制长度 // 限制长度
if (StringUtils.isNotBlank(log.getDetails()) && log.getDetails().length() > 1000) { if (StringUtils.isNotBlank(log.getDetails()) && log.getDetails().length() > 500) {
log.setDetails(log.getDetails().substring(0, 1000)); log.setDetails(log.getDetails().substring(0, 499));
} }
operationLogMapper.insert(log); operationLogMapper.insert(log);
} }
@ -44,6 +44,10 @@ public class OperationLogService {
OperationLogMapper logMapper = sqlSession.getMapper(OperationLogMapper.class); OperationLogMapper logMapper = sqlSession.getMapper(OperationLogMapper.class);
if (CollectionUtils.isNotEmpty(logs)) { if (CollectionUtils.isNotEmpty(logs)) {
logs.forEach(item -> { logs.forEach(item -> {
// 限制长度
if (StringUtils.isNotBlank(item.getDetails()) && item.getDetails().length() > 500) {
item.setDetails(item.getDetails().substring(0, 499));
}
logMapper.insert(item); logMapper.insert(item);
}); });
} }

View File

@ -32,8 +32,7 @@ public class ApiDefinitionController {
@PostMapping(value = "/add", consumes = MediaType.APPLICATION_JSON_VALUE) @PostMapping(value = "/add", consumes = MediaType.APPLICATION_JSON_VALUE)
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_ADD_API) @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_ADD_API)
@RequestLog(type = OperationLogType.ADD, module = OperationLogModule.API_DEFINITION, @RequestLog(type = OperationLogType.ADD, module = OperationLogModule.API_DEFINITION, projectId = "#request.projectId", details = "#request.name")
sourceId = "#request.id", projectId = "#request.projectId", details = "#request.name")
public ApiDefinitionDTO add(@Validated({Created.class}) @RequestBody ApiDefinitionDTO request, public ApiDefinitionDTO add(@Validated({Created.class}) @RequestBody ApiDefinitionDTO request,
@RequestParam(value = "files") List<MultipartFile> bodyFiles) { @RequestParam(value = "files") List<MultipartFile> bodyFiles) {
return apiDefinitionService.create(request, bodyFiles); return apiDefinitionService.create(request, bodyFiles);
@ -41,7 +40,7 @@ public class ApiDefinitionController {
@PostMapping(value = "/batch-del") @PostMapping(value = "/batch-del")
@RequiresPermissions(PermissionConstants.PROJECT_API_REPORT_READ_DELETE) @RequiresPermissions(PermissionConstants.PROJECT_API_REPORT_READ_DELETE)
@RequestLog(isBatch = true, event = "#msClass.getLogs(#ids)", msClass = ApiDefinitionService.class) @RequestLog(isBatch = true, isBefore = true, details = "#msClass.getLogs(#ids)", msClass = ApiDefinitionService.class)
public void batchDelete(@RequestBody List<String> ids) { public void batchDelete(@RequestBody List<String> ids) {
apiDefinitionService.batchDelete(ids); apiDefinitionService.batchDelete(ids);
} }