修改@OperationLogDetail注解

This commit is contained in:
付庆吉
2021-12-29 09:49:56 +08:00
parent 414a3a0c22
commit 4ab7ac08fc
20 changed files with 391 additions and 270 deletions

View File

@ -6,13 +6,13 @@
<parent>
<groupId>com.chinaunicom.ebtp</groupId>
<artifactId>mall-ebtp-cloud-parent</artifactId>
<version>2.0.0-SNAPSHOT</version>
<version>2.0.1-SNAPSHOT</version>
<relativePath>../mall-ebtp-cloud-parent</relativePath>
</parent>
<groupId>com.chinaunicom.mall.ebtp</groupId>
<artifactId>uboot-common</artifactId>
<version>2.0.0-SNAPSHOT</version>
<version>2.0.1-SNAPSHOT</version>
<name>uboot-common</name>
<dependencies>
@ -175,11 +175,11 @@
</dependency>
<!-- mongodb-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- &lt;!&ndash; mongodb&ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-mongodb</artifactId>-->
<!-- </dependency>-->
</dependencies>

View File

@ -0,0 +1,71 @@
package com.chinaunicom.mall.ebtp.common.config;
import com.chinaunicom.mall.ebtp.common.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/**
* 异步线程池配置
*
* @author f
* @date 2021-11-12
*/
@Configuration
@EnableAsync
@EnableConfigurationProperties(AsyncProperties.class)
@Slf4j
public class AsyncConfig implements AsyncConfigurer {
@Autowired
private AsyncProperties asyncProperties;
/**
* 配置异步线程池
* <p>
* 拒绝异常处理 - 在调用线程中执行当线程池中线程都已被占用且queue已满则拒绝继续提交task
* 默认为ThreakPoolExecutor.AbortPolicy抛出异常到上层应用 - 导致异步死掉,无法再处理新任务,
* 此处实现照搬ThreadPoolExecutor.CallerRunsPolicy且添加日志记录
* CallerRunsPolicy不在新线程中执行任务而是用调用者所在的线程来执行
*/
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(asyncProperties.getCoreSize());
executor.setMaxPoolSize(asyncProperties.getMaxSize());
executor.setQueueCapacity(asyncProperties.getQueueCapacity());
executor.setKeepAliveSeconds(asyncProperties.getKeepAlive());
executor.setThreadNamePrefix(asyncProperties.getThreadNamePrefix());
// new ThreadPoolExecutor.CallerRunsPolicy();
executor.setRejectedExecutionHandler((r, e) -> {
log.error("Async thread pool over load - caller run - queue size{}", e.getQueue().size());
if (!e.isShutdown()) {
r.run();
}
});
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}
/**
* 异步线程池 - 全局异常处理
*
* @return
*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (ex, method, params) -> {
log.info("Async method{} has uncaught exceptionparams: {}", method, JsonUtils.objectToJson(params), ex);
};
}
}

View File

@ -0,0 +1,39 @@
package com.chinaunicom.mall.ebtp.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 异步线程池属性
*
* @author f
* @date 2021-11-12
*/
@ConfigurationProperties(prefix = "async.thead.pool")
@Data
public class AsyncProperties {
/**
* 核心线程池大小
*/
private Integer coreSize;
/**
* 最大线程池大小
*/
private Integer maxSize;
/**
* 线程池队列容量默认Integer.MAX_VALUE
*/
private Integer queueCapacity;
/**
* 线程池空闲时间
*/
private Integer keepAlive;
/**
* 线程池名称前缀
*/
private String threadNamePrefix;
}

View File

@ -26,4 +26,14 @@ public interface CommonConstants {
* 候审
*/
Integer ROOM_TYPE_2 = 2;
/**
* seata transactionId
*/
String TRANSACTION_ID = "PtxId";
/**
* seata spanId
*/
String P_SPAN_ID = "PspanId";
}

View File

@ -1,7 +1,8 @@
package com.chinaunicom.mall.ebtp.common.log;
import com.chinaunicom.mall.ebtp.common.log.enums.OperationType;
import com.chinaunicom.mall.ebtp.common.log.enums.EbtpLogBusinessModule;
import com.chinaunicom.mall.ebtp.common.log.enums.EbtpLogType;
import java.lang.annotation.*;
@ -21,22 +22,18 @@ public @interface OperationLogDetail {
/**
* 方法执行模块名称
* 所属模块
*/
String operationModel() default "";
EbtpLogBusinessModule businessModule();
/**
* 操作类型(enum):主要是select,insert,update,delete
*/
EbtpLogType operationType();
/**
* 方法描述,可使用占位符获取参数:{{tel}}
*/
String detail() default "";
/**
* 操作类型(enum):主要是select,insert,update,delete
*/
OperationType operationType() default OperationType.UNKNOWN;
/**
* 日志等级:自己定义
*/
int level() default 2;
}

View File

@ -1,5 +1,6 @@
package com.chinaunicom.mall.ebtp.common.log.aop;
import cn.hutool.core.exceptions.ExceptionUtil;
import com.chinaunicom.mall.ebtp.common.log.OperationLogDetail;
import com.chinaunicom.mall.ebtp.common.log.entity.OperationLog;
import com.chinaunicom.mall.ebtp.common.log.service.OperationLogService;
@ -13,6 +14,8 @@ import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@ -31,6 +34,8 @@ import java.util.Map;
@Component
public class LogAspect {
private final static String CONTENT = "{\"args\":%s,\"returnVal\":%s}";
@Autowired
private OperationLogService operationLogService;
@ -44,22 +49,17 @@ public class LogAspect {
*/
@Around("operationLog()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object res = null;
long time = System.currentTimeMillis();
Object res = joinPoint.proceed();
try {
res = joinPoint.proceed();
time = System.currentTimeMillis() - time;
return res;
} finally {
try {
//方法执行完成后增加日志
addOperationLog(joinPoint, res, time);
} catch (Exception e) {
e.printStackTrace();
log.error("LogAspect 操作失败:" + e.getMessage());
}
//方法执行完成后增加日志
addOperationLog(joinPoint, res, time, true);
} catch (Exception e) {
e.printStackTrace();
log.error("LogAspect 操作失败:" + e.getMessage());
}
return res;
}
/**
@ -69,23 +69,26 @@ public class LogAspect {
* @param res 方法参数
* @param time 执行时间
*/
private void addOperationLog(JoinPoint joinPoint, Object res, long time) {
private void addOperationLog(JoinPoint joinPoint, Object res, long time, boolean result) {
ObjectMapper mapper = new ObjectMapper();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
OperationLog operationLog = new OperationLog();
try {
operationLog.setRunTime(time);
operationLog.setReturnValue(mapper.writeValueAsString(res));
operationLog.setArgs(mapper.writeValueAsString(joinPoint.getArgs()));
operationLog.setMethod(signature.getDeclaringTypeName() + "." + signature.getName());
operationLog.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(time)));
operationLog.setRunTime(System.currentTimeMillis() - time);
operationLog.setContent(String.format(CONTENT, mapper.writeValueAsString(joinPoint.getArgs()), mapper.writeValueAsString(res)));
operationLog.setResult(result);
operationLog.setPackageName(signature.getDeclaringTypeName());
operationLog.setMethod(signature.getName());
OperationLogDetail annotation = signature.getMethod().getAnnotation(OperationLogDetail.class);
if (annotation != null) {
operationLog.setLevel(annotation.level());
operationLog.setLevel("aop");
operationLog.setDescribe(getDetail(((MethodSignature) joinPoint.getSignature()).getParameterNames(), joinPoint.getArgs(), annotation));
operationLog.setOperationType(annotation.operationType().getValue());
operationLog.setOperationModel(annotation.operationModel());
operationLog.setBusinessModule(annotation.businessModule().getValue());
}
operationLogService.addOperationLog(operationLog);
} catch (JsonProcessingException e) {
@ -126,15 +129,22 @@ public class LogAspect {
@Before("operationLog()")
public void doBeforeAdvice(JoinPoint joinPoint) {
}
/**
* 后置异常通知
*/
@AfterThrowing("operationLog()")
public void throwss(JoinPoint jp) {
@AfterThrowing(pointcut = "operationLog()", throwing = "ex")
public void throwss(JoinPoint jp, Exception ex) {
//方法执行完成后增加日志
addOperationLog(jp, ExceptionUtil.stacktraceToString(ex, 500), System.currentTimeMillis(), false);
}
/**
* 后置异常通知
*/
@After("operationLog()")
public void After(JoinPoint jp) {
}
}

View File

@ -1,18 +0,0 @@
package com.chinaunicom.mall.ebtp.common.log.dao;
import com.chinaunicom.mall.ebtp.common.log.entity.OperationLog;
/**
* 保存日志
*
* @author f
*/
public interface OperationLogDao {
/**
* 保存日志
*
* @param operationLog
*/
void save(OperationLog operationLog);
}

View File

@ -1,31 +0,0 @@
package com.chinaunicom.mall.ebtp.common.log.dao.impl;
import com.chinaunicom.mall.ebtp.common.log.dao.OperationLogDao;
import com.chinaunicom.mall.ebtp.common.log.entity.OperationLog;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
/**
* 保存日志
*
* @author f
*/
@Repository
public class OperationLogDaoImpl implements OperationLogDao {
@Resource
private MongoTemplate mongoTemplate;
/**
* 保存日志
*
* @param operationLog
*/
@Override
public void save(OperationLog operationLog) {
mongoTemplate.save(operationLog);
}
}

View File

@ -1,8 +1,9 @@
package com.chinaunicom.mall.ebtp.common.log.entity;
import com.chinaunicom.mall.ebtp.common.base.entity.BaseCacheUser;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
@ -14,8 +15,8 @@ import java.io.Serializable;
* @author daixc
* @date 2020-09-07
*/
@Document(collection = "ebtp_log")
@Data
@Accessors(chain = true)
public class OperationLog implements Serializable {
/**
@ -29,81 +30,73 @@ public class OperationLog implements Serializable {
*/
private String transactionId;
/**
* 内容
*/
private String content;
/**
* 内容
*/
private boolean result;
/**
* 创建时间
*/
private String createTime;
/**
* 日志等级
* 操作人token
*/
private Integer level;
/**
* 服务名
*/
private String serviceName;
/**
* 被操作的模块
*/
private String operationModel;
/**
* 方法名
*/
private String method;
/**
* 参数
*/
private String args;
/**
* 操作人id
*/
private String userId;
private String token;
/**
* 操作人
*/
private String userName;
/**
* 日志描述
*/
private String describe;
private BaseCacheUser user;
/**
* 操作类型
*/
private String operationType;
/**
* 服务名
*/
private String serviceName;
/**
* 业务所属模块
*/
private String businessModule;
/**
* 包名
*/
private String packageName;
/**
* 方法名
*/
private String method;
/**
* url
*/
private String url;
/**
* 日志描述
*/
private String describe;
/**
* 方法运行时间
*/
private Long runTime;
/**
* 方法返回值
* 日志等级
*/
private String returnValue;
@Override
public String toString() {
return "OperationLog{" +
"id='" + id + '\'' +
", createTime=" + createTime +
", level=" + level +
", operationModel='" + operationModel + '\'' +
", method='" + method + '\'' +
", args='" + args + '\'' +
", userId='" + userId + '\'' +
", userName='" + userName + '\'' +
", describe='" + describe + '\'' +
", operationType='" + operationType + '\'' +
", runTime=" + runTime +
", returnValue='" + returnValue + '\'' +
'}';
}
private String level;
}

View File

@ -0,0 +1,53 @@
package com.chinaunicom.mall.ebtp.common.log.enums;
/**
* <p>
* 日志级别枚举类
*
* </p>
*
* @author daixc
* @date 2020-09-07
*/
public enum EbtpLogBusinessModule {
/**
* 系统日志
*/
SYSTEM("system"),
/**
* 应用程序日志
*/
APPLICATION("application"),
/**
* 拦截器日志
*/
AOP("aop"),
/**
* 业务日志
*/
BUSINESS("business"),
/**
* 垃圾收集器日志
*/
GC("gc"),
/**
* 其他
*/
OTHER("other");
private final String value;
public String getValue() {
return value;
}
EbtpLogBusinessModule(String s) {
this.value = s;
}
}

View File

@ -9,7 +9,7 @@ package com.chinaunicom.mall.ebtp.common.log.enums;
* @author daixc
* @date 2020-09-07
*/
public enum OperationType {
public enum EbtpLogType {
/**
* 操作类型
@ -30,7 +30,7 @@ public enum OperationType {
this.value = value;
}
OperationType(String s) {
EbtpLogType(String s) {
this.value = s;
}
}

View File

@ -0,0 +1,30 @@
package com.chinaunicom.mall.ebtp.common.log.producer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
/**
* @author Administrator
*/
@Component
@Slf4j
public class OperationLogKafkaProducer {
/**
* log topic
*/
public static final String TOPIC = "jl_ebtp_log";
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
public void send(String message) {
kafkaTemplate.send(TOPIC, message)
.addCallback(success -> {
},
failure -> log.info(TOPIC + " - 生产者 发送消息失败:" + failure.getMessage()));
}
}

View File

@ -2,7 +2,8 @@ package com.chinaunicom.mall.ebtp.common.log.service;
import com.chinaunicom.mall.ebtp.common.log.entity.OperationLog;
import com.chinaunicom.mall.ebtp.common.log.enums.OperationType;
import com.chinaunicom.mall.ebtp.common.log.enums.EbtpLogBusinessModule;
import com.chinaunicom.mall.ebtp.common.log.enums.EbtpLogType;
/**
* 日志持久化
@ -17,43 +18,29 @@ public interface OperationLogService {
*
* @param operationLog
*/
void addOperationLog(OperationLog operationLog);
public void addOperationLog(OperationLog operationLog);
/**
* 保存日志
*
* @param message 日志内容
* @param result 执行结果
* @param businessModule 所属模块
* @param type 类型
* @param detail 描述
*/
public void addOperationLog(String message, boolean result, EbtpLogBusinessModule businessModule, EbtpLogType type, String detail);
/**
* 保存日志
*
* @param args
* @param returnValue
* @param operationModel
* @param describe
* @param operationType
* @param message 日志内容
* @param result 执行结果
* @param businessModule 所属模块
* @param type 类型
*/
void addOperationLog(String args, String returnValue, String operationModel, String describe, OperationType operationType);
public void addOperationLog(String message, boolean result, EbtpLogBusinessModule businessModule, EbtpLogType type);
/**
* 保存日志
*
* @param args
* @param returnValue
* @param operationModel
* @param operationType
*/
void addOperationLog(String args, String returnValue, String operationModel, OperationType operationType);
/**
* 保存日志
*
* @param args
* @param returnValue
* @param operationType
*/
void addOperationLog(String args, String returnValue, OperationType operationType);
/**
* 保存日志
*
* @param args
* @param returnValue
*/
void addOperationLog(String args, String returnValue);
}
}

View File

@ -3,17 +3,24 @@ package com.chinaunicom.mall.ebtp.common.log.service.impl;
import cn.hutool.core.date.DateUtil;
import com.chinaunicom.mall.ebtp.common.base.entity.BaseCacheUser;
import com.chinaunicom.mall.ebtp.common.base.service.IBaseCacheUserService;
import com.chinaunicom.mall.ebtp.common.log.dao.OperationLogDao;
import com.chinaunicom.mall.ebtp.common.constant.CommonConstants;
import com.chinaunicom.mall.ebtp.common.log.entity.OperationLog;
import com.chinaunicom.mall.ebtp.common.log.enums.OperationType;
import com.chinaunicom.mall.ebtp.common.log.enums.EbtpLogBusinessModule;
import com.chinaunicom.mall.ebtp.common.log.enums.EbtpLogType;
import com.chinaunicom.mall.ebtp.common.log.producer.OperationLogKafkaProducer;
import com.chinaunicom.mall.ebtp.common.log.service.OperationLogService;
import com.chinaunicom.mall.ebtp.common.util.HttpContextUtils;
import com.chinaunicom.mall.ebtp.common.util.JsonUtils;
import com.chinaunicom.mall.ebtp.common.util.PropertyUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.AUTHORIZATION_HEADER;
/**
* 日志持久化
@ -22,9 +29,6 @@ import org.springframework.stereotype.Service;
*/
@Service
public class OperationLogServiceImpl implements OperationLogService {
private static final String TRANSACTION_ID = "PtxId";
private static final String P_SPAN_ID = "PspanId";
@Autowired
private IBaseCacheUserService cacheUserService;
@ -33,18 +37,18 @@ public class OperationLogServiceImpl implements OperationLogService {
private String serviceName;
@Autowired
private OperationLogDao dao;
private OperationLogKafkaProducer kafkaProducer;
@Override
@Async
public void addOperationLog(OperationLog operationLog) {
if (operationLog.getMethod() == null) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
for (int i = 1; i < stackTrace.length; i++) {
StackTraceElement element = stackTrace[i];
if (!element.getClassName().equals(OperationLogServiceImpl.class.getName())) {
operationLog.setMethod(element.getClassName() + "." + element.getMethodName());
operationLog.setPackageName(element.getClassName());
operationLog.setMethod(element.getMethodName());
break;
}
}
@ -52,84 +56,53 @@ public class OperationLogServiceImpl implements OperationLogService {
if (operationLog.getMethod() == null) {
StackTraceElement element = Thread.currentThread().getStackTrace()[1];
operationLog.setMethod(element.getClassName() + "." + element.getMethodName());
operationLog.setPackageName(element.getClassName());
operationLog.setMethod(element.getMethodName());
}
operationLog.setId(PropertyUtils.getSnowflakeId());
operationLog.setTransactionId(MDC.get(TRANSACTION_ID));
operationLog.setServiceName(serviceName);
operationLog.setCreateTime(DateUtil.now());
dao.save(operationLog);
}
/**
* 保存
*
* @param args
* @param returnValue
* @param operationModel
* @param describe
* @param operationType
*/
@Override
public void addOperationLog(String args, String returnValue, String operationModel, String describe, OperationType operationType) {
OperationLog operationLog = new OperationLog();
operationLog.setArgs(args);
operationLog.setReturnValue(returnValue);
BaseCacheUser user = cacheUserService.getCacheUser();
if (null != user) {
operationLog.setUserId(user.getUserId());
operationLog.setUserName(user.getFullName());
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
// 提取token头信息 ;
operationLog.setToken(request.getHeader(AUTHORIZATION_HEADER))
.setUser(user)
.setUrl(request.getMethod() + "." + request.getRequestURI());
}
operationLog.setLevel(3);
operationLog.setOperationModel(operationModel);
operationLog.setDescribe(describe);
operationLog.setOperationType(operationType.getValue());
operationLog.setId(PropertyUtils.getSnowflakeId())
.setTransactionId(MDC.get(CommonConstants.TRANSACTION_ID))
.setServiceName(serviceName);
kafkaProducer.send(JsonUtils.objectToJson(operationLog));
}
this.addOperationLog(operationLog);
/**
* 保存日志
*
* @param message 日志内容
* @param businessModule 所属模块
* @param type 类型
* @param detail 描述
*/
@Override
public void addOperationLog(String message, boolean result, EbtpLogBusinessModule businessModule, EbtpLogType type, String detail) {
this.addOperationLog(new OperationLog()
.setCreateTime(DateUtil.now())
.setContent(message)
.setLevel("business")
.setDescribe(detail)
.setOperationType(type.getValue()));
}
/**
* 保存日志
*
* @param args
* @param returnValue
* @param operationModel
* @param operationType
* @param message 日志内容
* @param businessModule 所属模块
* @param type 类型
*/
@Override
public void addOperationLog(String args, String returnValue, String operationModel, OperationType operationType) {
addOperationLog(args, returnValue, operationModel, "", operationType);
public void addOperationLog(String message, boolean result, EbtpLogBusinessModule businessModule, EbtpLogType type) {
addOperationLog(message, result, businessModule, type, null);
}
/**
* 保存日志
*
* @param args
* @param returnValue
* @param operationType
*/
@Override
public void addOperationLog(String args, String returnValue, OperationType operationType) {
addOperationLog(args, returnValue, "", operationType);
}
/**
* 保存日志
*
* @param args
* @param returnValue
*/
@Override
public void addOperationLog(String args, String returnValue) {
addOperationLog(args, returnValue, OperationType.UNKNOWN);
}
}

View File

@ -0,0 +1,7 @@
#spring.task.execution.pool <20>̳߳<DFB3><CCB3><EFBFBD><EFBFBD><EFBFBD>
async.thead.pool.coreSize=200
async.thead.pool.maxSize=1000
async.thead.pool.queueCapaciry=100
async.thead.pool.keepALive=1000
async.thead.pool.threadNamePrefix=ebtp-thread