package com.xzx.gc.filter;
|
|
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.exceptions.ExceptionUtil;
|
import cn.hutool.core.lang.Dict;
|
import cn.hutool.core.text.StrBuilder;
|
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.URLUtil;
|
import cn.hutool.extra.emoji.EmojiUtil;
|
import cn.hutool.extra.servlet.ServletUtil;
|
import com.xzx.gc.common.constant.CommonEnum;
|
import com.xzx.gc.common.constant.MqConstants;
|
import com.xzx.gc.common.dto.log.*;
|
import com.xzx.gc.common.exception.BusinessException;
|
import com.xzx.gc.common.exception.PlatformException;
|
import com.xzx.gc.common.exception.RestException;
|
import com.xzx.gc.common.utils.*;
|
import com.xzx.gc.entity.CoreUser;
|
import com.xzx.gc.interceptor.SqlInterceptor;
|
import com.xzx.gc.model.MiException;
|
import com.xzx.gc.util.SessionUtil;
|
import io.swagger.annotations.Api;
|
import io.swagger.annotations.ApiOperation;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.ibatis.mapping.SqlCommandType;
|
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.ProceedingJoinPoint;
|
import org.aspectj.lang.Signature;
|
import org.aspectj.lang.annotation.*;
|
import org.aspectj.lang.reflect.MethodSignature;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
|
import javax.servlet.http.HttpServletRequest;
|
import java.lang.reflect.Method;
|
import java.util.List;
|
import java.util.stream.Collectors;
|
|
|
/**
|
* 日志切面
|
*/
|
@Aspect
|
@Component
|
@Slf4j
|
public class LogFilter {
|
|
|
public static final String AROUND_PARAM="aroundParam";
|
|
//错误异常打印行数
|
public static final int ERR_LINE=50000;
|
@Autowired
|
private BusinessUtil businessUtil;
|
|
@Autowired
|
private SpringUtil springUtil;
|
|
@Autowired
|
private MqUtil mqUtil;
|
|
/** 以 controller 包下定义的所有请求为切入点 */
|
@Pointcut("execution(public * com.xzx.gc.*.controller..*.*(..))")
|
public void webLog() {}
|
|
/**
|
* 在切点之前织入
|
* @param joinPoint
|
* @throws Throwable
|
*/
|
@Before("webLog()")
|
public void doBefore(JoinPoint joinPoint) throws Throwable {
|
|
}
|
|
/**
|
* 在切点之后织入
|
* @throws Throwable
|
*/
|
@After("webLog()")
|
public void doAfter() throws Throwable {
|
}
|
|
/**
|
* 环绕
|
* @param joinPoint
|
* @return
|
* @throws Throwable
|
*/
|
@Around("webLog()")
|
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
|
HttpServletRequest request = springUtil.getCurrentRequest();
|
Dict dict = get(joinPoint,request);
|
request.setAttribute(AROUND_PARAM,dict);
|
// 开始打印请求日志
|
String userId = request.getHeader("userId");
|
if(StringUtils.isNotBlank(userId)){
|
String ip = IpUtils.getIpAddr(request);
|
businessUtil.saveLoginInfoToRedis(ip,userId);
|
}
|
Object result = joinPoint.proceed();
|
String resultJson = businessUtil.prettyOut(result);
|
|
//返回结果处理
|
List<SqlDto> sqlList = (List<SqlDto>) request.getAttribute(SqlInterceptor.SQL_PARAM);
|
// 执行耗时
|
Long startTime = dict.getLong("startTime");
|
long l = System.currentTimeMillis() - startTime;
|
|
|
IntefaceAdminLog intefaceAdminLog = (IntefaceAdminLog) dict.get("inteface");
|
intefaceAdminLog.setRunTime(Convert.toStr(l));
|
intefaceAdminLog.setLogLevel(CommonEnum.调试级别.getValue());
|
intefaceAdminLog.setOutParameter(EmojiUtil.removeAllEmojis(resultJson));
|
|
if(CollUtil.isNotEmpty(sqlList)){
|
String sql=sqlList.stream().map(x->x.getSql()).collect(Collectors.joining(";"));
|
intefaceAdminLog.setSqlParameter(sql);
|
}
|
|
//不是后台请求才发送info日志队列
|
|
|
// if(SpringUtil.isTest()||SpringUtil.isCheck()||SpringUtil.isDev()){
|
// mqUtil.send(MqConstants.INTEFACE_ADMIN_LOG_QUEUE, intefaceAdminLog);
|
// }else {
|
// if (!dict.getBool("isAdmin")) {
|
// mqUtil.send(MqConstants.INTEFACE_ADMIN_LOG_QUEUE, intefaceAdminLog);
|
//// OperationAppLog operationAppLog = (OperationAppLog) dict.get("operation");
|
//// mqUtil.send(MqConstants.OPERATION_APP_LOG_QUEUE, operationAppLog);
|
// }
|
// }
|
mqUtil.send(MqConstants.INTEFACE_ADMIN_LOG_QUEUE, intefaceAdminLog);
|
out(dict,sqlList,resultJson,l+"",CommonEnum.调试级别.getValue());
|
clear(request);
|
return result;
|
}
|
|
|
/**
|
*
|
* afterThrowable:(统一异常处理). <br/>
|
*
|
* @author fenglanglang
|
* @param e
|
*/
|
@AfterThrowing(pointcut="webLog()",throwing="e")
|
public void afterThrowable(Throwable e) {
|
HttpServletRequest request = springUtil.getCurrentRequest();
|
if (request != null) {
|
List<SqlDto> sqlList = (List<SqlDto>) request.getAttribute(SqlInterceptor.SQL_PARAM);
|
Dict dict = (Dict) request.getAttribute(AROUND_PARAM);
|
String l = null;
|
if (dict != null) {
|
Long startTime = dict.getLong("startTime");
|
l = Convert.toStr(System.currentTimeMillis() - startTime);
|
IntefaceAdminLog intefaceAdminLog = (IntefaceAdminLog) dict.get("inteface");
|
intefaceAdminLog.setRunTime(Convert.toStr(l));
|
String errMsg=null;
|
String logLevel=CommonEnum.调试级别.getValue();
|
if(e instanceof BusinessException){
|
errMsg=((BusinessException) e).getDebugMsg();
|
intefaceAdminLog.setLogLevel(CommonEnum.调试级别.getValue());
|
intefaceAdminLog.setOutParameter(errMsg);
|
}else if(e instanceof RestException){
|
errMsg=((RestException) e).getMsg();
|
intefaceAdminLog.setLogLevel(CommonEnum.调试级别.getValue());
|
intefaceAdminLog.setOutParameter(errMsg);
|
}else if(e instanceof MiException){
|
errMsg= e.getMessage();
|
intefaceAdminLog.setLogLevel(CommonEnum.调试级别.getValue());
|
intefaceAdminLog.setOutParameter(errMsg);
|
}else {
|
if(SpringUtil.isDevOrTestOrCheck()){
|
errMsg = ExceptionUtil.stacktraceToString(e, ERR_LINE);
|
}else{
|
errMsg = ExceptionUtil.stacktraceToOneLineString(e, ERR_LINE);
|
}
|
intefaceAdminLog.setErrMessage(errMsg);
|
intefaceAdminLog.setLogLevel(CommonEnum.错误级别.getValue());
|
logLevel=CommonEnum.错误级别.getValue();
|
}
|
if (CollUtil.isNotEmpty(sqlList)) {
|
String sql = sqlList.stream().map(x -> x.getSql()).collect(Collectors.joining(";"));
|
intefaceAdminLog.setSqlParameter(sql);
|
}
|
mqUtil.send(MqConstants.INTEFACE_ADMIN_LOG_QUEUE, intefaceAdminLog);
|
// if(!dict.getBool("isAdmin")){
|
// OperationAppLog operationAppLog = (OperationAppLog) dict.get("operation");
|
// mqUtil.send(MqConstants.OPERATION_APP_LOG_QUEUE, operationAppLog);
|
// }
|
out(dict, sqlList, errMsg, l, logLevel);
|
}
|
clear(request);
|
}
|
}
|
|
|
/**
|
* 组装
|
* @param joinPoint
|
* @return
|
* @throws NoSuchMethodException
|
*/
|
private Dict get(JoinPoint joinPoint,HttpServletRequest request) throws NoSuchMethodException {
|
long startTime=System.currentTimeMillis();
|
Dict dict=Dict.create();
|
// 开始打印请求日志
|
String clientType = request.getHeader("clientType");
|
clientType=businessUtil.getClientTypeName(clientType);
|
|
//接口描述
|
String desc="";
|
//接口所在模块
|
String module="";
|
Signature signature = joinPoint.getSignature();
|
String methodName = signature.getName();
|
//类
|
Class declaringType = signature.getDeclaringType();
|
String className = declaringType.getName();
|
Class[] parameterTypes = ((MethodSignature)signature).getMethod().getParameterTypes();
|
//方法
|
Method method = declaringType.getMethod(signature.getName(),parameterTypes);
|
|
if (method.isAnnotationPresent(ApiOperation.class)) {
|
ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
|
desc=apiOperation.value();
|
}
|
|
// if (declaringType.isAnnotationPresent(Api.class)) {
|
// Api api = (Api) declaringType.getAnnotation(Api.class);
|
// String[] tags = api.tags();
|
// if(ArrayUtil.isNotEmpty(tags)){
|
// module=tags[0];
|
// }else {
|
// module=desc;
|
// }
|
// }
|
|
String inParam = businessUtil.prettyInParam(joinPoint.getArgs());
|
String codePath=className+"."+methodName;
|
|
boolean isAdmin = businessUtil.isAdmin(request.getRequestURI());
|
|
String userId;
|
if(isAdmin){
|
CoreUser user= (CoreUser) request.getSession().getAttribute(SessionUtil.ACCESS_CURRENT_USER);
|
userId=user!=null?user.getId().toString():"匿名";
|
}else {
|
userId = request.getHeader("userId");
|
userId = StrUtil.isBlank(userId) ? "匿名" : userId;
|
}
|
|
String platName= isAdmin ?"后台接口":"前台接口";
|
|
|
ConsoleDto in = in(request, desc, codePath, clientType,platName,inParam);
|
dict.put("console",in);
|
|
|
IntefaceAdminLog intefaceAdminLog =new IntefaceAdminLog();
|
intefaceAdminLog.setMethodPath(request.getRequestURI());
|
intefaceAdminLog.setMethodDesc(desc);
|
intefaceAdminLog.setMethodName(className+"."+methodName);
|
intefaceAdminLog.setIntoParameter(EmojiUtil.removeAllEmojis(inParam));
|
intefaceAdminLog.setImplementType(isAdmin ?"2":"1");
|
intefaceAdminLog.setUserId(userId);
|
|
dict.put("inteface", intefaceAdminLog);
|
|
|
// if(!isAdmin) {
|
// OperationAppLog operationAppLog = new OperationAppLog();
|
// operationAppLog.setOpreateName(userId);
|
// if ("WEB".equals(clientType)) {
|
// operationAppLog.setAppPrograme("1");
|
// } else {
|
// operationAppLog.setAppPrograme("2");
|
// }
|
// operationAppLog.setMethodName(module);
|
// operationAppLog.setOperateAction(null);
|
// dict.put("operation",operationAppLog);
|
// }
|
|
|
dict.put("startTime",startTime);
|
|
dict.put("isAdmin",isAdmin);
|
return dict;
|
}
|
|
/**
|
* 清除
|
* @param request
|
*/
|
private void clear(HttpServletRequest request){
|
request.removeAttribute(AROUND_PARAM);
|
request.removeAttribute(SqlInterceptor.SQL_PARAM);
|
}
|
|
/**
|
* 请求
|
* @param request
|
* @param desc
|
* @param codePath
|
* @param inParam
|
* @return
|
*/
|
private ConsoleDto in(HttpServletRequest request,String desc,String codePath,String clientType, String platName,String inParam){
|
ConsoleDto consoleDto=new ConsoleDto();
|
|
consoleDto.setTitle(businessUtil.checkProject(request.getRequestURI()));
|
List<ConsoleContentDto> list=CollUtil.newArrayList();
|
ConsoleContentDto consoleContentDto=new ConsoleContentDto();
|
consoleContentDto.setName("请求地址");
|
consoleContentDto.setValue(URLUtil.normalize(request.getRequestURL().toString()));
|
list.add(consoleContentDto);
|
|
consoleContentDto=new ConsoleContentDto();
|
consoleContentDto.setName("请求描述");
|
consoleContentDto.setValue(desc);
|
list.add(consoleContentDto);
|
|
// consoleContentDto=new ConsoleContentDto();
|
// consoleContentDto.setName("请求方法");
|
// consoleContentDto.setValue(request.getMethod());
|
// list.add(consoleContentDto);
|
|
consoleContentDto=new ConsoleContentDto();
|
consoleContentDto.setName("请求接口");
|
consoleContentDto.setValue(codePath);
|
list.add(consoleContentDto);
|
|
consoleContentDto=new ConsoleContentDto();
|
consoleContentDto.setName("请求I P ");
|
consoleContentDto.setValue(IpUtils.getIpAddr(request));
|
list.add(consoleContentDto);
|
|
consoleContentDto=new ConsoleContentDto();
|
consoleContentDto.setName("请求平台");
|
consoleContentDto.setValue(platName);
|
list.add(consoleContentDto);
|
|
consoleContentDto=new ConsoleContentDto();
|
consoleContentDto.setName("请求来源");
|
consoleContentDto.setValue(clientType);
|
list.add(consoleContentDto);
|
|
|
consoleContentDto=new ConsoleContentDto();
|
consoleContentDto.setName("请求头部");
|
consoleContentDto.setValue(businessUtil.prettyHeader(ServletUtil.getHeaderMap(request)));
|
list.add(consoleContentDto);
|
|
consoleContentDto=new ConsoleContentDto();
|
consoleContentDto.setName("请求入参");
|
consoleContentDto.setValue(inParam);
|
list.add(consoleContentDto);
|
|
consoleDto.setList(list);
|
|
return consoleDto;
|
}
|
|
/**
|
* 输出
|
* @param dict
|
* @param sqlList
|
* @param resultJson
|
* @param l
|
*/
|
private void out(Dict dict, List<SqlDto> sqlList,String resultJson,String l,String type){
|
ConsoleDto consoleDto= (ConsoleDto) dict.get("console");
|
consoleDto.setHeader("您有新的请求");
|
consoleDto.setEmjio("fish");
|
List<ConsoleContentDto> list = consoleDto.getList();
|
|
if(StrUtil.isNotBlank(resultJson)) {
|
ConsoleContentDto consoleContentDto = new ConsoleContentDto();
|
if(CommonEnum.调试级别.getValue().equals(type)) {
|
consoleContentDto.setName("响应出参");
|
}else if(CommonEnum.错误级别.getValue().equals(type)){
|
consoleContentDto.setName("异常信息");
|
}
|
consoleContentDto.setValue(resultJson);
|
list.add(consoleContentDto);
|
}
|
|
if(CollUtil.isNotEmpty(sqlList)) {
|
// String sql=sqlList.stream().map(x->x.getSql()).collect(Collectors.joining(";\n "));
|
// long effectNum=sqlList.stream().mapToLong(x->Convert.toLong(x.getEffectNum())).sum();
|
StrBuilder strBuilder = StrBuilder.create();
|
for (int i = 0; i < sqlList.size(); i++) {
|
SqlDto sqlDto = sqlList.get(i);
|
strBuilder.append(sqlDto.getSql());
|
strBuilder.append(";\n ");
|
if(SqlCommandType.SELECT.name().equals(sqlDto.getSqlType())){
|
strBuilder.append("【返回结果数:"+sqlDto.getEffectNum()+"】");
|
}else {
|
strBuilder.append("【影响的行数:"+sqlDto.getEffectNum()+"】");
|
}
|
|
if(i!=sqlList.size()-1) {
|
strBuilder.append("\n ");
|
}
|
}
|
long costTime=sqlList.stream().mapToLong(x->Convert.toLong(x.getCostTime())).sum();
|
ConsoleContentDto consoleContentDto = new ConsoleContentDto();
|
consoleContentDto.setName("执行SQL ");
|
consoleContentDto.setValue(strBuilder.toString());
|
list.add(consoleContentDto);
|
|
consoleContentDto=new ConsoleContentDto();
|
consoleContentDto.setName("SQL耗时 ");
|
consoleContentDto.setValue(costTime+"毫秒");
|
list.add(consoleContentDto);
|
|
// consoleContentDto=new ConsoleContentDto();
|
// consoleContentDto.setName("影响行数");
|
// consoleContentDto.setValue(effectNum+"");
|
// list.add(consoleContentDto);
|
}
|
|
|
if(StrUtil.isNotBlank(l)) {
|
ConsoleContentDto consoleContentDto = new ConsoleContentDto();
|
consoleContentDto.setName("请求耗时");
|
consoleContentDto.setValue(l + "毫秒");
|
list.add(consoleContentDto);
|
}
|
|
ConsoleContentDto consoleContentDtoType = new ConsoleContentDto();
|
consoleContentDtoType.setName("请求状态");
|
if(CommonEnum.调试级别.getValue().equals(type)) {
|
consoleContentDtoType.setValue("大吉大利今晚吃鸡!");
|
}else if(CommonEnum.错误级别.getValue().equals(type)){
|
consoleContentDtoType.setValue("又失败了我太难了!");
|
}
|
list.add(consoleContentDtoType);
|
|
String console = businessUtil.console(consoleDto);
|
log.debug(console);
|
|
}
|
|
|
|
}
|
|