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; package com.flyfish.framework.logging.advice;
import com.flyfish.framework.logging.service.LogContext;
import com.flyfish.framework.logging.service.LogManager; import com.flyfish.framework.logging.service.LogManager;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
@ -14,10 +16,10 @@ import javax.annotation.Resource;
* @author wangyu * @author wangyu
*/ */
@Aspect @Aspect
@RequiredArgsConstructor
public class LogAdvice { public class LogAdvice {
@Resource private final LogManager logManager;
private LogManager logManager;
/** /**
* 切入注解 * 切入注解
@ -36,17 +38,20 @@ public class LogAdvice {
*/ */
@Around("pointCut()") @Around("pointCut()")
public Object process(ProceedingJoinPoint joinPoint) throws Throwable { public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs(); // 构建上下文
Throwable e = null; LogContext context = LogContext.of(joinPoint);
Object result = null;
try { try {
result = joinPoint.proceed(args); Object result = joinPoint.proceed(joinPoint.getArgs());
context.setResult(result);
return result; return result;
} catch (Throwable throwable) { } catch (Throwable throwable) {
e = throwable; context.setError(throwable);
throw throwable; throw throwable;
} finally { } 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; package com.flyfish.framework.logging.config;
import com.flyfish.framework.logging.advice.LogAdvice; 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.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.EnableAspectJAutoProxy;
@ -20,8 +21,8 @@ public class LoggingConfig {
* @return 结果 * @return 结果
*/ */
@Bean @Bean
public LogAdvice logAdvice() { public LogAdvice logAdvice(LogManager manager) {
return new LogAdvice(); return new LogAdvice(manager);
} }
/** /**
@ -33,4 +34,14 @@ public class LoggingConfig {
public LoggingTextRegistry loggingTextRegistry(List<LoggingTextModifier> modifiers) { public LoggingTextRegistry loggingTextRegistry(List<LoggingTextModifier> modifiers) {
return new LoggingTextRegistry(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 Long period;
// 操作时间 // 操作时间
private Date createTime; private Date startTime;
// 完成时间
private Date endTime;
// 操作人 // 操作人
private String operator; 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; package com.flyfish.framework.logging.service;
import com.alibaba.fastjson.JSON; 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.logging.domain.Log;
import com.flyfish.framework.utils.ReflectionUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.DisposableBean;
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 javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Date;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/** /**
* 日志管理器 * 日志管理器
* *
* @author wangyu * @author wangyu
*/ */
@Service
@Slf4j @Slf4j
public class LogManager { public class LogManager implements DisposableBean {
// 固定线程池
private final ExecutorService executorService = Executors.newFixedThreadPool(20);
@Resource @Resource
private LogService logService; private LogService logService;
/** /**
* 尝试记录日志 * 尝试记录日志
* *
* @param joinPoint 接入点 * @param context 上下文
* @param e 异常
*/ */
public void tryLog(ProceedingJoinPoint joinPoint, Object result, Throwable e) { public void tryLog(LogContext context) {
Signature signature = joinPoint.getSignature(); executorService.execute(() -> {
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 log = new Log();
log.setSuccess(null == e); log.setSuccess(context.isSuccess());
log.setBody(bodyString(joinPoint.getArgs())); log.setBody(bodyString(context.getArgs()));
log.setModule(module); log.setModule(context.getModule());
log.setBusiness(operation.value()); log.setBusiness(context.getBusiness());
log.setError(Optional.ofNullable(e).map(JSON::toJSONString).orElse(null)); log.setError(Optional.ofNullable(context.getError()).map(JSON::toJSONString).orElse(null));
log.setResponse(Optional.ofNullable(result).map(JSON::toJSONString).orElse(null)); log.setResponse(Optional.ofNullable(context.getResult()).map(JSON::toJSONString).orElse(null));
log.setOperator(UserContext.sharedContext().map(UserContext::currentUser).map(Domain::getName).orElse("未知")); log.setOperator(context.getUser());
log.setSignature(joinPoint.getSignature().getName()); 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); log.setUri(null);
// 写入日志 // 写入日志
logService.create(log); logService.create(log);
} });
}
} }
private String bodyString(Object[] args) { private String bodyString(Object[] args) {
@ -87,4 +61,11 @@ public class LogManager {
} }
return JSON.toJSONString(args); return JSON.toJSONString(args);
} }
@Override
public void destroy() {
if (!executorService.isShutdown()) {
executorService.shutdownNow();
}
}
} }