Initial commit

This commit is contained in:
jackyu66git
2026-03-23 11:52:51 +08:00
commit ea8d889fbe
1114 changed files with 92438 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.oneone.cloud</groupId>
<artifactId>oneone-common</artifactId>
<version>${revision}</version>
</parent>
<artifactId>common-log</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.oneone.cloud</groupId>
<artifactId>common-core</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>com.oneone.cloud</groupId>
<artifactId>common-web</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,32 @@
package com.oneone.common.log;
import com.oneone.common.log.aspect.SysLogAspect;
import com.oneone.common.log.handler.DefaultLogHandler;
import com.oneone.common.log.handler.LogHandler;
import com.oneone.upms.api.logger.OperateLogApi;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@EnableAsync
@Configuration
@AllArgsConstructor
@ConditionalOnWebApplication
@ConditionalOnProperty(prefix = "oneone.log" , name = "enabled" , havingValue = "true" , matchIfMissing = true)
public class LogAutoConfiguration {
@Bean
@ConditionalOnMissingBean(LogHandler.class)
public DefaultLogHandler logHandler(OperateLogApi operateLogApi) {
return new DefaultLogHandler(operateLogApi);
}
@Bean
public SysLogAspect sysLogAspect(LogHandler logHandler) {
return new SysLogAspect(logHandler);
}
}
@@ -0,0 +1,18 @@
package com.oneone.common.log.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ISysLog {
/**
* 描述
* @return {String}
*/
String value();
}
@@ -0,0 +1,167 @@
package com.oneone.common.log.aspect;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.oneone.common.base.LocalUser;
import com.oneone.common.log.annotation.ISysLog;
import com.oneone.common.log.event.SysLog;
import com.oneone.common.log.handler.LogHandler;
import com.oneone.common.result.Result;
import com.oneone.common.result.ResultCode;
import com.oneone.common.util.JsonUtils;
import com.oneone.common.util.TracerUtils;
import com.oneone.common.web.util.UserContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Array;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.IntStream;
@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class SysLogAspect {
@Value("${spring.application.name}")
private String applicationName;
private final LogHandler logHandler;
private final ThreadLocal<SysLog> logThreadLocal = new ThreadLocal<>();
@Before("@annotation(iSysLog)")
public void doBefore(JoinPoint joinPoint, ISysLog iSysLog) {
ServletRequestAttributes attributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//get方法不记录日志
if ("GET".equals(request.getMethod())) {
return;
}
SysLog sysLog = new SysLog();
sysLog.setTraceId(TracerUtils.getTraceId());
sysLog.setModule(applicationName);
sysLog.setName(iSysLog.value());
sysLog.setType(0);
sysLog.setRequestMethod(request.getMethod());
sysLog.setRequestUrl(URLUtil.getPath(request.getRequestURI()));
sysLog.setUserIp(ServletUtil.getClientIP(request));
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
sysLog.setJavaMethod(methodSignature.toString());
sysLog.setJavaMethodArgs(obtainMethodArgs(joinPoint));
sysLog.setUserAgent(request.getHeader("user-agent"));
sysLog.setStartTime(LocalDateTime.now());
logThreadLocal.set(sysLog);
}
@AfterReturning(value = "@annotation(iSysLog)" , returning = "result")
public void doAfterReturning(Object result, ISysLog iSysLog) {
try {
// 处理完请求,从线程变量中获取日志数据,并记录到db
SysLog sysLog = logThreadLocal.get();
if (null != sysLog) {
sysLog.setUserId(UserContext.getUserIdIfPresentDefault());
LocalUser localUser = UserContext.getUser();
Integer useType = localUser == null ? 0 : localUser.getUserType();
sysLog.setUserType(useType);
Result result1 = (Result) result;
sysLog.setResultCode(result1.getCode());
sysLog.setResultMsg(result1.getMsg());
sysLog.setResultData(JsonUtils.toJSONString(result1.getData()));
sysLog.setDuration((int) (LocalDateTimeUtil.between(sysLog.getStartTime(), LocalDateTime.now()).toMillis()));
logHandler.save(sysLog);
}
} catch (Exception e) {
log.error("操作请求日志记录失败" , e);
} finally {
// 清除threadlocal
logThreadLocal.remove();
}
}
@AfterThrowing(value = "@annotation(iSysLog)" , throwing = "throwable")
public void doAfterThrowing(ISysLog iSysLog, Throwable throwable) {
try {
// 处理完请求,从线程变量中获取日志数据,并记录到db
SysLog sysLog = logThreadLocal.get();
if (null != sysLog) {
sysLog.setUserId(UserContext.getUserIdIfPresentDefault());
LocalUser localUser = UserContext.getUser();
Integer useType = localUser == null ? 0 : localUser.getUserType();
sysLog.setUserType(useType);
sysLog.setResultCode(ResultCode.SYSTEM_EXECUTION_ERROR.getCode());
sysLog.setResultMsg(JSON.toJSONString(throwable.getMessage()));
sysLog.setDuration((int) (LocalDateTimeUtil.between(sysLog.getStartTime(), LocalDateTime.now()).toMillis()));
logHandler.save(sysLog);
}
} catch (Exception e) {
log.error("操作请求日志记录失败" , e);
} finally {
// 清除threadlocal
logThreadLocal.remove();
}
}
private static String obtainMethodArgs(JoinPoint joinPoint) {
// TODO 提升:参数脱敏和忽略
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String[] argNames = methodSignature.getParameterNames();
Object[] argValues = joinPoint.getArgs();
// 拼接参数
Map<String, Object> args = Maps.newHashMapWithExpectedSize(argValues.length);
for (int i = 0; i < argNames.length; i++) {
String argName = argNames[i];
Object argValue = argValues[i];
// 被忽略时,标记为 ignore 字符串,避免和 null 混在一起
args.put(argName, !isIgnoreArgs(argValue) ? argValue : "[ignore]");
}
return JsonUtils.toJSONString(args);
}
private static boolean isIgnoreArgs(Object object) {
Class<?> clazz = object.getClass();
// 处理数组的情况
if (clazz.isArray()) {
return IntStream.range(0, Array.getLength(object))
.anyMatch(index -> isIgnoreArgs(Array.get(object, index)));
}
// 递归,处理数组、Collection、Map 的情况
if (Collection.class.isAssignableFrom(clazz)) {
return ((Collection<?>) object).stream()
.anyMatch((Predicate<Object>) SysLogAspect::isIgnoreArgs);
}
if (Map.class.isAssignableFrom(clazz)) {
return isIgnoreArgs(((Map<?, ?>) object).values());
}
// obj
return object instanceof MultipartFile
|| object instanceof HttpServletRequest
|| object instanceof HttpServletResponse
|| object instanceof BindingResult;
}
}
@@ -0,0 +1,108 @@
package com.oneone.common.log.event;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Map;
@Data
public class SysLog implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 链路追踪编号
*/
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 LocalDateTime startTime;
/**
* 执行时长,单位:毫秒
*/
private Integer duration;
/**
* 结果码
*/
private String resultCode;
/**
* 结果提示
*/
private String resultMsg;
/**
* 结果数据
*/
private String resultData;
}
@@ -0,0 +1,19 @@
package com.oneone.common.log.handler;
import cn.hutool.core.bean.BeanUtil;
import com.oneone.common.log.event.SysLog;
import com.oneone.upms.api.logger.OperateLogApi;
import com.oneone.upms.api.logger.dto.OperateLogCreateReqDTO;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class DefaultLogHandler implements LogHandler{
private final OperateLogApi operateLogApi;
@Override
public void save(SysLog sysLog) {
OperateLogCreateReqDTO reqDTO = BeanUtil.copyProperties(sysLog, OperateLogCreateReqDTO.class);
operateLogApi.createOperateLog(reqDTO);
}
}
@@ -0,0 +1,13 @@
package com.oneone.common.log.handler;
import com.oneone.common.log.event.SysLog;
/**
* @author mice
* @version 1.0
* @date 2022-12-21 13:58
*/
public interface LogHandler {
void save(SysLog sysLog);
}
@@ -0,0 +1,54 @@
package com.oneone.common.log.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
/**
* @author mice
* @version 1.0
* @desc 事件
* @date 2022-04-20 12:10:02
*/
@Data
@Schema(description = "事件" )
@NoArgsConstructor
@AllArgsConstructor
public class EventParam {
private static final long serialVersionUID = 1L;
/**
* 标题
*/
@Schema(description = "标题" )
@Length(max = 8)
private String title;
/**
* 告警等级
*/
@Schema(description = "告警等级" )
private Integer level;
/**
* 应用
*/
@Schema(description = "应用" )
private String app;
/**
* 通知人id [userId:userName,1:陈浩]
*/
@Schema(description = "通知人id" )
@Length(max = 200)
private String notifyUser;
/**
* 内容
*/
@Schema(description = "内容" )
private String content;
}
@@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.oneone.common.log.LogAutoConfiguration