Browse Source

1.增加日志、异常处理aop;2.增加mdc日志链路追踪

test
wangxianzhang 3 years ago
parent
commit
e339ef64e9
  1. 206
      src/main/java/com/epmet/jmreport/aop/RequestLogAspect.java
  2. 71
      src/main/java/com/epmet/jmreport/constants/JmReportConstants.java
  3. 23
      src/main/java/com/epmet/jmreport/constants/ThreadLocalConstant.java
  4. 57
      src/main/java/com/epmet/jmreport/utils/ExceptionUtils.java

206
src/main/java/com/epmet/jmreport/aop/RequestLogAspect.java

@ -1,40 +1,166 @@
//package com.epmet.jmreport.aop; package com.epmet.jmreport.aop;
//
//import com.epmet.commons.tools.aspect.BaseRequestLogAspect; import com.alibaba.fastjson.JSON;
//import org.aspectj.lang.ProceedingJoinPoint; import com.epmet.jmreport.constants.JmReportConstants;
//import org.aspectj.lang.annotation.Around; import com.epmet.jmreport.constants.ThreadLocalConstant;
//import org.aspectj.lang.annotation.Aspect; import com.epmet.jmreport.utils.ExceptionUtils;
//import org.springframework.core.annotation.Order; import lombok.extern.slf4j.Slf4j;
//import org.springframework.stereotype.Component; import org.aspectj.lang.ProceedingJoinPoint;
//import org.springframework.web.context.request.RequestAttributes; import org.aspectj.lang.annotation.Around;
//import org.springframework.web.context.request.RequestContextHolder; import org.aspectj.lang.annotation.Aspect;
//import org.springframework.web.context.request.ServletRequestAttributes; import org.jeecg.modules.jmreport.common.vo.Result;
// import org.slf4j.MDC;
//import javax.servlet.http.HttpServletRequest; import org.springframework.core.annotation.Order;
// import org.springframework.stereotype.Component;
///** import org.springframework.web.context.request.RequestAttributes;
// * 日志/异常处理切面实现,调用父类方法完成日志记录和异常处理。 import org.springframework.web.context.request.RequestContextHolder;
// */ import org.springframework.web.context.request.ServletRequestAttributes;
//@Aspect import org.springframework.web.multipart.MultipartFile;
//@Component
//@Order(0) import javax.servlet.ServletRequest;
//public class RequestLogAspect { import javax.servlet.ServletResponse;
// import javax.servlet.http.HttpServletRequest;
// @Override import java.time.Duration;
// @Around(value = "execution(* com...*Controller*.*(..)) ") import java.time.LocalDateTime;
// public Object proceed(ProceedingJoinPoint point) throws Throwable { import java.util.Arrays;
// return super.proceed(point, getRequest()); import java.util.Enumeration;
// } import java.util.HashMap;
// import java.util.Map;
// /**
// * 获取Request对象 /**
// * * 日志/异常处理切面实现调用父类方法完成日志记录和异常处理
// * @return */
// */ @Aspect
// private HttpServletRequest getRequest() { @Component
// RequestAttributes ra = RequestContextHolder.getRequestAttributes(); @Order(0)
// ServletRequestAttributes sra = (ServletRequestAttributes) ra; @Slf4j
// return sra.getRequest(); public class RequestLogAspect {
// }
// @Around(value = "execution(* org.jeecg..*.*(..)) " +
//} "&& (@annotation(org.springframework.web.bind.annotation.RequestMapping)) " +
"|| @annotation(org.springframework.web.bind.annotation.GetMapping)" +
"|| @annotation(org.springframework.web.bind.annotation.PostMapping)")
public Object proceed(ProceedingJoinPoint point) throws Throwable {
HttpServletRequest request = getRequest();
String requestURI = request.getRequestURI();
String method = request.getMethod();
// 获取事务流水号
String transactionSerial = request.getHeader(JmReportConstants.TRANSACTION_SERIAL_KEY);
Map<String, String> requestHeaders = getRequestHeaders(request);
// 设置traceId,日志链路追踪
MDC.put(JmReportConstants.TRANSACTION_SERIAL_KEY, transactionSerial);
Object result;
LocalDateTime startTime = LocalDateTime.now();
try {
Object[] args = point.getArgs();
ThreadLocalConstant.requestParam.set(Arrays.toString(point.getArgs()));
log.info(">>>>>>>>请求信息>>>>>>>>:事务流水号:{},url:{} ,method:{},请求参数:{},请求头:{}",
transactionSerial, requestURI, method, objectsToString(args), requestHeaders);
result = point.proceed();
resultInfoLog(transactionSerial, getExecPeriod(startTime), result);
} catch (Throwable e) {
result = Result.FAIL("请求失败", null);
String exceptionMsg = ExceptionUtils.getThrowableErrorStackTrace(e);
resultErrorLog(transactionSerial, getExecPeriod(startTime), result, e.getMessage(), exceptionMsg);
}
return result;
}
/**
* 获取Request对象
*
* @return
*/
private HttpServletRequest getRequest() {
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
return sra.getRequest();
}
/**
* @Description 获取请求头信息
* @return
* @author wxz
* @date 2021.03.31 13:59
*/
private Map<String, String> getRequestHeaders(HttpServletRequest request) {
Enumeration<String> headerNames = request.getHeaderNames();
HashMap<String, String> headerMap = new HashMap<>();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
headerMap.put(headerName, headerValue);
}
return headerMap;
}
/**
* 将请求对象转换为String
* @param args
* @return
*/
private String objectsToString(Object[] args) {
if (args == null) {
return null;
} else {
StringBuilder builder = new StringBuilder("[");
for (Object object : args) {
if (object != null
&& !(object instanceof ServletRequest)
&& !(object instanceof ServletResponse)
&& !(object instanceof MultipartFile)
) {
try {
// 尝试作为json解析
String objectString = JSON.toJSONString(object);
builder.append(objectString);
} catch (Exception e) {
builder.append(object.toString());
}
builder.append(",");
}
}
builder.append("]");
return builder.toString();
}
}
/**
* info日志
* @param transactionSerial
* @param execTimeMillis
* @param result
*/
private void resultInfoLog(String transactionSerial, Long execTimeMillis, Object result) {
log.info("<<<<<<<<正常响应<<<<<<<<:事务流水号:{}, 执行时长:{}ms, 响应数据:{}",
transactionSerial, execTimeMillis, result == null ? result : result.toString());
}
/**
* 计算执行周期
* @param startTime
* @return
*/
private Long getExecPeriod(LocalDateTime startTime) {
LocalDateTime endTime = LocalDateTime.now();
return Duration.between(startTime, endTime).toMillis();
}
/**
* 异常错误级别日志
* @param transactionSerial
* @param execTimeMillis
* @param result
* @param exceptionMsg
* @param exceptionDetail
*/
private void resultErrorLog(String transactionSerial, Long execTimeMillis, Object result, String exceptionMsg, String exceptionDetail) {
log.error("<<<<<<<<异常响应<<<<<<<<:事务流水号:{}, 执行时长:{}ms, 响应数据:{}, 异常信息:{}, 堆栈信息:{}",
transactionSerial, execTimeMillis, result == null ? result : result.toString(), exceptionMsg, exceptionDetail);
}
}

71
src/main/java/com/epmet/jmreport/constants/JmReportConstants.java

@ -0,0 +1,71 @@
package com.epmet.jmreport.constants;
/**
* 公用参数常量
*/
public interface JmReportConstants {
/**
* app类型-居民端端
*/
String APP_RESI = "resi";
/**
* app类型-政府端
*/
String APP_GOV = "gov";
/**
* app类型-运营端
*/
String APP_OPER = "oper";
/**
* 基层治理平台端
*/
String APP_IC = "ic";
/**
* PC端:web
*/
String CLIENT_WEB = "web";
/**
* 微信小程序:wxmp
*/
String CLIENT_WXMP = "wxmp";
/**
* 客户来源App
* */
String APP = "app";
/**
* 用户Id
* */
String USER_ID = "userId";
/**
* 客户端
* */
String CLIENT = "client";
/**
* 客户ID
*/
String CUSTOMER_ID = "customerId";
/**
* 事务流水号每次请求串起来的多个服务拥有相同的流水号,便于日志追踪
*/
String TRANSACTION_SERIAL_KEY = "Transaction-Serial";
/**
* app类型-工作端
*/
String APP_WORK = "work";
/**
* 来源类型-话题topic
*/
String TOPIC = "topic";
/**
* 来源类型-议题issue
*/
String ISSUE = "issue";
}

23
src/main/java/com/epmet/jmreport/constants/ThreadLocalConstant.java

@ -0,0 +1,23 @@
package com.epmet.jmreport.constants;
/**
* ThreadLocal常亮
*/
public class ThreadLocalConstant {
/**
* 存储所需操作权限的 ThreadLocal
*/
public static final ThreadLocal<String> requirePermissionTl = new ThreadLocal<>();
/**
* 用于向DataFilterInterceptor传递权限过滤的sql片段(需要在Controller相关的AOP中进行清理防止变量残留)
*/
public static final ThreadLocal<String> sqlFilter = new ThreadLocal();
/**
* 用于本次的获取请求参数
*/
public static final ThreadLocal<String> requestParam = new ThreadLocal();
}

57
src/main/java/com/epmet/jmreport/utils/ExceptionUtils.java

@ -0,0 +1,57 @@
/**
* Copyright (c) 2018 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有侵权必究
*/
package com.epmet.jmreport.utils;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* Exception工具类
*
* @author Mark sunlightcs@gmail.com
*/
public class ExceptionUtils {
/**
* 获取异常信息
* @param ex 异常
* @return 返回异常信息
*/
public static String getErrorStackTrace(Exception ex){
return getThrowableErrorStackTrace(ex);
}
public static String getThrowableErrorStackTrace(Throwable ex) {
StringWriter sw = null;
PrintWriter pw = null;
try {
sw = new StringWriter();
pw = new PrintWriter(sw, true);
ex.printStackTrace(pw);
}finally {
try {
if(pw != null) {
pw.close();
}
} catch (Exception e) {
}
try {
if(sw != null) {
sw.close();
}
} catch (IOException e) {
}
}
return sw.toString();
}
}
Loading…
Cancel
Save