一、日志收集便于投产和调试对接 快速定位问题
自定义注解Class
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
@Documented
public @interface WebLog {
String description() default "";
}
切面日志收集Class
import com.yunbeast.common.enums.NumberEnum;
import com.yunbeast.common.util.JsonUtil;
import com.yunbeast.common.util.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.slf4j.MDC;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Aspect
@Service
public class WebLogAspect {
private final static String INVOKE_NO = "invokeNo";
private static final String LINE_SEPARATOR = System.lineSeparator();
@Pointcut("@annotation(com.zhu.common.log.WebLog)")
public void webLog() {
}
@Around("webLog()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
try {
// 设置invokeNo
MDC.put(INVOKE_NO, UUIDUtil.generateUUID());
long now = System.currentTimeMillis();
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
// 打印请求相关参数
log.info("========================================== Start ==========================================");
// 打印请求 URL
// log.info("URL : {}", request.getRequestURL().toString());
// 打印描述信息
log.info("Description : {}", getAspectLogDescription(proceedingJoinPoint));
// 打印请求的 IP
//if (attributes != null) {
// HttpServletRequest request = attributes.getRequest();
log.info("IP : {}", request.getRemoteAddr());
// 打印调用 controller 的全路径以及执行方法
log.info("Class Method : {}.{}", proceedingJoinPoint.getSignature().getDeclaringTypeName(),
proceedingJoinPoint.getSignature().getName());
// 打印请求入参
try {
if (proceedingJoinPoint.getArgs() != null
&& proceedingJoinPoint.getArgs().length > NumberEnum.ZERO.getValue()) {
Map param = getParam(proceedingJoinPoint);
log.info("Request Data : {}", JsonUtil.format(param));
}
} catch (Exception e) {
e.printStackTrace();
log.error("Exception ={}", e.getMessage());
}
// }
Object object = proceedingJoinPoint.proceed();
// 打印响应结果
log.info("Response Data : {}", JsonUtil.format(object));
// 接口耗时
log.info("Time-Consuming : {} ms", System.currentTimeMillis() - now);
// 接口结束后换行,方便分割查看
log.info("=========================================== End ==========================================={}",
LINE_SEPARATOR);
return object;
} finally {
MDC.clear();
}
}
public String getAspectLogDescription(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class> targetClass = joinPoint.getTarget().getClass();
Method[] methods = targetClass.getMethods();
StringBuilder description = new StringBuilder();
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class>[] classes = method.getParameterTypes();
if (classes.length == arguments.length) {
description.append(method.getAnnotation(com.zhu.common.log.WebLog.class).description());
break;
}
}
}
return description.toString();
}
public Map getParam(ProceedingJoinPoint proceedingJoinPoint) {
Map map = new HashMap<>(16);
Object[] values = proceedingJoinPoint.getArgs();
String[] names = ((CodeSignature) proceedingJoinPoint.getSignature()).getParameterNames();
for (int i = 0; i < names.length; i++) {
map.put(names[i], values[i]);
}
return map;
}
}
部分Utils
public class UUIDUtil {
public static String generateUUID() {
return UUID.randomUUID().toString().replace("-", "");
}
}
package com.yunbeast.common.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.PropertyNamingStrategy;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.ValueFilter;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Objects;
public class JsonUtil {
public static String format(Object object) {
if (object != null) {
return JSON.toJSONString(object);
}
return null;
}
public static T parse(String text, Class clazz) {
if (org.apache.commons.lang3.StringUtils.isNotEmpty(text)) {
return JSON.parseObject(text, clazz);
}
return null;
}
public static List parseArray(String text, Class clazz) {
if (StringUtils.isNotEmpty(text)) {
return JSON.parseArray(text, clazz);
}
return null;
}
//过滤器 所有的null和"“串都会被转换成”"值输出到字符串中
private static final ValueFilter VALUE_FILTER = (o, s, o1) -> o1 == null ? "" : o1;
public static JSONObject creatGrpcJson(Object obj){
if (Objects.nonNull(obj)){
SerializeConfig config = new SerializeConfig();
config.propertyNamingStrategy = PropertyNamingStrategy.SnakeCase;
String json = JSON.toJSONString(obj, config, VALUE_FILTER);
return JSONObject.parseObject(json);
}
return null;
}
public static JSONObject parseObject(String text ){
if (StringUtils.isNotEmpty(text)){
return JSONObject.parseObject(text);
}
return null;}
}
这里因为我log文件配置的 本地开发不要这个输出到控制台
so 程序里面info 日志并没有打印
这里需要大家去了解一下 关于MDC 的日志增强
传送门 :使用MDC增强日志记录



