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 sqlList = (List) 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:(统一异常处理).
* * @author fenglanglang * @param e */ @AfterThrowing(pointcut="webLog()",throwing="e") public void afterThrowable(Throwable e) { HttpServletRequest request = springUtil.getCurrentRequest(); if (request != null) { List sqlList = (List) 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 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 sqlList,String resultJson,String l,String type){ ConsoleDto consoleDto= (ConsoleDto) dict.get("console"); consoleDto.setHeader("您有新的请求"); consoleDto.setEmjio("fish"); List 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); } }