feat: 完成日志

This commit is contained in:
wangyu 2021-01-14 14:47:15 +08:00
parent 0ab915a03e
commit 056c32e11a
5 changed files with 193 additions and 65 deletions

View File

@ -1,6 +1,8 @@
package com.flyfish.framework.logging.advice;
import com.flyfish.framework.logging.service.LogContext;
import com.flyfish.framework.logging.service.LogManager;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@ -14,10 +16,10 @@ import javax.annotation.Resource;
* @author wangyu
*/
@Aspect
@RequiredArgsConstructor
public class LogAdvice {
@Resource
private LogManager logManager;
private final LogManager logManager;
/**
* 切入注解
@ -36,17 +38,20 @@ public class LogAdvice {
*/
@Around("pointCut()")
public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
Throwable e = null;
Object result = null;
// 构建上下文
LogContext context = LogContext.of(joinPoint);
try {
result = joinPoint.proceed(args);
Object result = joinPoint.proceed(joinPoint.getArgs());
context.setResult(result);
return result;
} catch (Throwable throwable) {
e = throwable;
context.setError(throwable);
throw throwable;
} finally {
logManager.tryLog(joinPoint, result, e);
if (context.isValid()) {
context.end();
logManager.tryLog(context);
}
}
}
}

View File

@ -1,6 +1,7 @@
package com.flyfish.framework.logging.config;
import com.flyfish.framework.logging.advice.LogAdvice;
import com.flyfish.framework.logging.service.LogManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@ -20,8 +21,8 @@ public class LoggingConfig {
* @return 结果
*/
@Bean
public LogAdvice logAdvice() {
return new LogAdvice();
public LogAdvice logAdvice(LogManager manager) {
return new LogAdvice(manager);
}
/**
@ -33,4 +34,14 @@ public class LoggingConfig {
public LoggingTextRegistry loggingTextRegistry(List<LoggingTextModifier> modifiers) {
return new LoggingTextRegistry(modifiers);
}
/**
* 日志管理器线程池
*
* @return 结果
*/
@Bean
public LogManager logManager() {
return new LogManager();
}
}

View File

@ -40,7 +40,10 @@ public class Log extends Domain {
private Long period;
// 操作时间
private Date createTime;
private Date startTime;
// 完成时间
private Date endTime;
// 操作人
private String operator;

View File

@ -0,0 +1,128 @@
package com.flyfish.framework.logging.service;
import com.flyfish.framework.annotations.Operation;
import com.flyfish.framework.beans.meta.RestBean;
import com.flyfish.framework.context.UserContext;
import com.flyfish.framework.domain.base.Domain;
import com.flyfish.framework.logging.domain.DomainDescriptions;
import com.flyfish.framework.utils.ReflectionUtils;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.util.CastUtils;
import java.util.Optional;
/**
* 日志上下文线程协作好帮手
*
* @author wangyu
*/
@Data
@Slf4j
public class LogContext {
private static final LogContext UN_SUPPORT = new LogContext();
private long startTime;
private long endTime;
@Setter(AccessLevel.NONE)
private Throwable error;
@Setter(AccessLevel.NONE)
private Object result;
private Object[] args;
private String module;
private String business;
private String signature;
private String user;
private boolean valid = false;
public static LogContext unSupport() {
return UN_SUPPORT;
}
/**
* 通过切入点创建
*
* @param joinPoint 切入点
* @return 结果
*/
public static LogContext of(ProceedingJoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
if (signature instanceof MethodSignature) {
MethodSignature methodSignature = (MethodSignature) signature;
Operation operation = AnnotationUtils.findAnnotation(methodSignature.getMethod(), Operation.class);
if (null != operation) {
LogContext context = new LogContext();
context.startTime = System.currentTimeMillis();
context.module = determineModule(operation, joinPoint.getTarget().getClass());
context.business = operation.value();
context.signature = joinPoint.getSignature().getName();
context.args = joinPoint.getArgs();
context.valid = true;
log.info("监测到支持的切点:{}, {}", context.module, operation.value());
return context;
}
}
return UN_SUPPORT;
}
/**
* 确定模块
*
* @param operation 模块
* @return 结果
*/
private static String determineModule(Operation operation, Class<?> targetClass) {
String module = operation.module();
if (StringUtils.isBlank(module)) {
return ReflectionUtils.getGenericType(targetClass)
.flatMap(clazz -> {
DomainDescriptions description = DomainDescriptions.getByClass(CastUtils.cast(clazz));
if (null != description) {
return Optional.of(description.getName());
}
return Optional.ofNullable(AnnotationUtils.findAnnotation(clazz, RestBean.class))
.map(RestBean::name);
})
.orElse("未知模块");
}
return module;
}
public void setResult(Object result) {
if (valid) {
this.result = result;
}
}
public void setError(Throwable error) {
if (valid) {
this.error = error;
}
}
public boolean isSuccess() {
return null == error;
}
public void end() {
this.user = UserContext.sharedContext().map(UserContext::currentUser).map(Domain::getName).orElse("未知");
this.endTime = System.currentTimeMillis();
}
}

View File

@ -1,81 +1,55 @@
package com.flyfish.framework.logging.service;
import com.alibaba.fastjson.JSON;
import com.flyfish.framework.annotations.Operation;
import com.flyfish.framework.beans.meta.RestBean;
import com.flyfish.framework.context.UserContext;
import com.flyfish.framework.domain.base.Domain;
import com.flyfish.framework.logging.domain.DomainDescriptions;
import com.flyfish.framework.logging.domain.Log;
import com.flyfish.framework.utils.ReflectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.util.CastUtils;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.DisposableBean;
import javax.annotation.Resource;
import java.util.Date;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 日志管理器
*
* @author wangyu
*/
@Service
@Slf4j
public class LogManager {
public class LogManager implements DisposableBean {
// 固定线程池
private final ExecutorService executorService = Executors.newFixedThreadPool(20);
@Resource
private LogService logService;
/**
* 尝试记录日志
*
* @param joinPoint 接入点
* @param e 异常
* @param context 上下文
*/
public void tryLog(ProceedingJoinPoint joinPoint, Object result, Throwable e) {
Signature signature = joinPoint.getSignature();
if (signature instanceof MethodSignature) {
MethodSignature methodSignature = (MethodSignature) signature;
Operation operation = AnnotationUtils.findAnnotation(methodSignature.getMethod(), Operation.class);
if (null != operation) {
String module = operation.module();
Class<?> targetClass = joinPoint.getTarget().getClass();
if (StringUtils.isBlank(module)) {
module = ReflectionUtils.getGenericType(targetClass)
.flatMap(clazz -> {
DomainDescriptions description = DomainDescriptions.getByClass(CastUtils.cast(clazz));
if (null != description) {
return Optional.of(description.getName());
}
return Optional.ofNullable(AnnotationUtils.findAnnotation(clazz, RestBean.class))
.map(RestBean::name);
})
.orElse("未知模块");
}
log.info("监测到支持的切点:{}, {}", module, operation.value());
// 构建日志
Log log = new Log();
log.setSuccess(null == e);
log.setBody(bodyString(joinPoint.getArgs()));
log.setModule(module);
log.setBusiness(operation.value());
log.setError(Optional.ofNullable(e).map(JSON::toJSONString).orElse(null));
log.setResponse(Optional.ofNullable(result).map(JSON::toJSONString).orElse(null));
log.setOperator(UserContext.sharedContext().map(UserContext::currentUser).map(Domain::getName).orElse("未知"));
log.setSignature(joinPoint.getSignature().getName());
// 先不拼接
log.setUri(null);
// 写入日志
logService.create(log);
}
}
public void tryLog(LogContext context) {
executorService.execute(() -> {
// 构建日志
Log log = new Log();
log.setSuccess(context.isSuccess());
log.setBody(bodyString(context.getArgs()));
log.setModule(context.getModule());
log.setBusiness(context.getBusiness());
log.setError(Optional.ofNullable(context.getError()).map(JSON::toJSONString).orElse(null));
log.setResponse(Optional.ofNullable(context.getResult()).map(JSON::toJSONString).orElse(null));
log.setOperator(context.getUser());
log.setSignature(context.getSignature());
log.setPeriod(context.getEndTime() - context.getStartTime());
log.setStartTime(new Date(context.getStartTime()));
log.setEndTime(new Date(context.getEndTime()));
// 先不拼接
log.setUri(null);
// 写入日志
logService.create(log);
});
}
private String bodyString(Object[] args) {
@ -87,4 +61,11 @@ public class LogManager {
}
return JSON.toJSONString(args);
}
@Override
public void destroy() {
if (!executorService.isShutdown()) {
executorService.shutdownNow();
}
}
}