操作日志处理

编写切面,可以加到公共模块里面,也可以放到网关层



/**
 * @author
 * @title: OpreateLogAop
 * @projectName commerce
 * @description: TODO
 * @date 2021/11/2919:06
 */
@Aspect
@Component
public class OpreateLogAspect {
    private final static Logger LOGGER = LoggerFactory.getLogger(RequestLogAspect.class);

    @Pointcut("execution(* com.scm..*.controller..*(..))")
    public void requestServer() {
    }

    @Around("requestServer()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        OperateLogDTO log = new OperateLogDTO();
        long beginTime = System.currentTimeMillis();
        Object result = pjp.proceed();
        try {
            ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

            if (Objects.nonNull(sra)) {
                HttpServletRequest request = sra.getRequest();

                // 日志标题
                log.setOperationInfo(getControllerMethodInfo(pjp).get("description").toString());
                //获取客户端操作系统
                String osInfo = getOsInfo(request);
                log.setOsInfo(osInfo);
                //IP地址
                log.setClientIp(request.getRemoteAddr());
                //日志请求url
                log.setRequestUrl(request.getRequestURI());
                //请求方式
                log.setRequestType(request.getMethod());
                //请求参数
                log.setRequestParam(JacksonUtils.writeValueAsString(getRequestParamsByProceedingJoinPoint(pjp)));
                //请求用户
//                log.setOperationUserCode(UserUtils.getEmployeeCode());
                log.setResponseData(result == null ? "" : JacksonUtils.writeValueAsString(result));
                //创建时间
                log.setCreateTime(new Date());
                long endTime = System.currentTimeMillis();
                //请求耗时
                long logElapsedTime = endTime - beginTime;
                log.setCostTime((int) logElapsedTime);
                ServerInfo serverInfo = getServerInfo();
                log.setServerIp(serverInfo.getIp());
                log.setServerInfo(serverInfo.getHostName());
                LOGGER.info("行为日志记录---->" + JacksonUtils.writeValueAsString(log));
                OpreateLog.getInstance().offerQueue(log);
            }

        } catch (Exception e) {
            LOGGER.error("AOP后置通知异常", e);
        }

        return result;
    }

    @AfterThrowing(pointcut = "requestServer()", throwing = "e")
    public void doAfterThrow(JoinPoint joinPoint, RuntimeException e) {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            RequestLogAspect.RequestErrorInfo requestErrorInfo = new RequestLogAspect.RequestErrorInfo();
            if (!ObjectUtils.isEmpty(attributes) && !ObjectUtils.isEmpty(attributes.getRequest())) {
                HttpServletRequest request = attributes.getRequest();
                requestErrorInfo.setIp(request.getRemoteAddr());
                requestErrorInfo.setUrl(request.getRequestURL().toString());
                requestErrorInfo.setHttpMethod(request.getMethod());
            }
            requestErrorInfo.setClassMethod(String.format("%s.%s", joinPoint.getSignature().getDeclaringTypeName(),
                    joinPoint.getSignature().getName()));
            requestErrorInfo.setRequestParams(getRequestParamsByJoinPoint(joinPoint));
            StackTraceElement[] stackTrace = e.getStackTrace();
            // 转换成json
            JSONObject jsonObject = new JSONObject();
            if (!ObjectUtils.isEmpty(stackTrace)) {
                StackTraceElement stackTraceElement = stackTrace[0];
                jsonObject = JSONUtil.parseObj(JSONUtil.toJsonStr(stackTraceElement));
                // 转换成json
                jsonObject.set("errorContent", e.getMessage());
                jsonObject.set("createTime", DateUtil.date());
                jsonObject.setDateFormat(DatePattern.NORM_DATETIME_PATTERN);
                jsonObject.set("messageId", IdUtil.fastSimpleUUID());
                // 获取IP地址
                jsonObject.set("serverIp", NetUtil.getLocalhostStr());
            }
            requestErrorInfo.setErrorMessage(jsonObject);
            LOGGER.info("Error Request Info      : {}", JSONUtil.toJsonStr(requestErrorInfo));
        } catch (Exception ignored) {

        }
    }

    /**
     * 获取入参
     * @param proceedingJoinPoint 入参
     *
     * @return 返回
     * */
    private Map<String, Object> getRequestParamsByProceedingJoinPoint(ProceedingJoinPoint proceedingJoinPoint) {
        //参数名
        String[] paramNames = ((MethodSignature)proceedingJoinPoint.getSignature()).getParameterNames();
        //参数值
        Object[] paramValues = proceedingJoinPoint.getArgs();

        return buildRequestParam(paramNames, paramValues);
    }

    private Map<String, Object> getRequestParamsByJoinPoint(JoinPoint joinPoint) {
        try {
            //参数名
            String[] paramNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
            //参数值
            Object[] paramValues = joinPoint.getArgs();

            return buildRequestParam(paramNames, paramValues);
        } catch (Exception e) {
            return new HashMap<>();
        }
    }

    /**
     * 得到计算机的ip,名称,操作系统名称,操作系统版本
     *
     * @return ServerInfo
     */
    public static ServerInfo getServerInfo() {
        try {
            ServerInfo serverInfo = new ServerInfo();
            InetAddress addr = InetAddress.getLocalHost();
            serverInfo.setIp(addr.getHostAddress());
            //获取本机ip
            serverInfo.setHostName(addr.getHostName());
            Properties props = System.getProperties();
            serverInfo.setOsName(props.getProperty("os.name"));
            serverInfo.setOsVersion(props.getProperty("os.version"));
            return serverInfo;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ServerInfo();
    }

    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     *
     * @param joinPoint 切点
     * @return 方法描述
     * @throws Exception
     */
    public static Map<String, Object> getControllerMethodInfo(JoinPoint joinPoint) throws Exception {

        Map<String, Object> map = new HashMap<String, Object>(16);
        //获取目标类名
        String targetName = joinPoint.getTarget().getClass().getName();
        //获取方法名
        String methodName = joinPoint.getSignature().getName();
        //获取相关参数
        Object[] arguments = joinPoint.getArgs();
        //生成类对象
        Class targetClass = Class.forName(targetName);
        //获取该类中的方法
        Method[] methods = targetClass.getMethods();



        String description = "description";
        String type = "";
        String operationType = "";
        String serviceName = "";
        for (Method method : methods) {
            if (!method.getName().equals(methodName)) {
                continue;
            }
            Annotation[] annotations = method.getDeclaredAnnotations();
            if (annotations != null) {
                for (Annotation annotation : annotations) {
                    if (annotation instanceof ApiOperation) {
                        ApiOperation methodDesc = (ApiOperation) annotation;
                        String desc = methodDesc.value();
                        map.put(description, desc);
                        System.out.println(desc);
                    }
                }
            }
        }
        return map;
    }

    private String getOsInfo(HttpServletRequest request){
        String  userAgent  =   request.getHeader("User-Agent");
        String os = "";
        if (userAgent.toLowerCase().contains("windows")) {
            os = "Windows";
        } else if(userAgent.toLowerCase().contains("mac")) {
            os = "Mac";
        } else if(userAgent.toLowerCase().contains("x11")) {
            os = "Unix";
        } else if(userAgent.toLowerCase().contains("android")) {
            os = "Android";
        } else if(userAgent.toLowerCase().contains("iphone")) {
            os = "IPhone";
        }else{
            os = "UnKnown, More-Info: "+userAgent;
        }
        return os;
    }

    private Map<String, Object> buildRequestParam(String[] paramNames, Object[] paramValues) {
        try {
            Map<String, Object> requestParams = new HashMap<>(paramNames.length);
            for (int i = 0; i < paramNames.length; i++) {
                Object value = paramValues[i];

                //如果是文件对象
                if (value instanceof MultipartFile) {
                    MultipartFile file = (MultipartFile) value;
                    //获取文件名
                    value = file.getOriginalFilename();
                }

                requestParams.put(paramNames[i], value);
            }

            return requestParams;
        } catch (Exception e) {
            return new HashMap<>(1);
        }
    }

    @Data
    public static class RequestInfo {
        private String ip;
        private String url;
        private String httpMethod;
        private String classMethod;
        private Object requestParams;
        private Object result;
        private Long timeCost;
    }

    @Data
    public static class RequestErrorInfo {
        private String ip;
        private String url;
        private String httpMethod;
        private String classMethod;
        private Object requestParams;
        private JSONObject errorMessage;
    }

    @Data
    public static class ServerInfo {
        private String ip;
        private String hostName;
        private String osName;
        private String osVersion;
    }
}

2、将任务放到阻塞队列中,另外起一个线程处理

package com.scm.common.log;

import com.mountslink.components.util.SpringUtils;
import com.scm.common.aop.OperateLogDTO;
import com.scm.common.feign.base.BaseService;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * ${DESCRIPTION}
 *
 * @author wanghaobin
 * @create 2017-07-01 15:28
 */
@Slf4j
public class OpreateLog extends Thread {
    private static OpreateLog dblog = null;
    private static BlockingQueue<OperateLogDTO> logInfoQueue = new LinkedBlockingQueue<>(10);

    private BaseService baseService;

    public OpreateLog() {
        super("CLogOracleWriterThread");

        this.baseService = SpringUtils.getBean(BaseService.class);
    }

    public static synchronized OpreateLog getInstance() {
        if (dblog == null) {
            dblog = new OpreateLog();
            dblog.start();
        }
        return dblog;
    }

    public void offerQueue(OperateLogDTO logInfo) {
        try {
            logInfoQueue.offer(logInfo);
        } catch (Exception e) {
            log.error("日志写入失败", e);
        }
    }

    @Override
    public void run() {
        // 缓冲队列
        List<OperateLogDTO> bufferedLogList = new ArrayList<>();
        log.error("日志写入开始");
        while (true) {
            try {
                bufferedLogList.add(logInfoQueue.take());
                logInfoQueue.drainTo(bufferedLogList);
                if (bufferedLogList.size() > 0) {
                    // 写入日志
                    for (OperateLogDTO operateLogDTO : bufferedLogList) {
                        
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                // 防止缓冲队列填充数据出现异常时不断刷屏
                try {
                    Thread.sleep(1000);
                } catch (Exception eee) {
                }
            } finally {
                if (bufferedLogList.size() > 0) {
                    try {
                        bufferedLogList.clear();
                    } catch (Exception e) {
                    }
                }
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值