使用自定义注解打印logstash日志

269 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第12天,点击查看活动详情

在收集日志时,首先需要打印日志,所以使用AOP将日志打印到控制台。博主的需求是按照操作日志和详细日志分为两种日志,同时正常日志与错误日志也要区分出来。所以有了以下的打印方式。

1.Log注解

因为大多数接口都需要打印日志,所有这里我们判断如果写有这个注解的类不需要打印日志,减少工作量。

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {

    /**
     * 注释
     */
    String operationName() default "";
}

2.切面类LogAspect

这里使用AOP拦截打印日志,判断有注解的接口打印日志,日志以|分隔开。并按照正常访问与异常访问打印不同。并按操作日志与接口调用日志区分开。

打印的日志格式为:|操作人|接口名|操作时间|客户端ip|系统名称|日志类型|接口地址|入参

@Aspect
@Component
public class LogAspect {

    private Logger logger = LoggerFactory.getLogger(LogAspect.class);

    private String succeed = "true";

    /**
     * 在注释@log的方法中进入本类
     */
    @Pointcut("@annotation(com.vanpeng.aspect.log.annotation.Log)")
    public void logPointCut() {
    }

    /**
     * 前置通知 用于拦截操作,在方法返回后执行
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
    public void doAfter(JoinPoint joinPoint, Result jsonResult) {
        handleLog(joinPoint, jsonResult);

    }

    /**
     * 拦截异常操作,有异常时执行
     *
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfter(JoinPoint joinPoint, Exception e) {
        Log controllerLog = getAnnotationLog(joinPoint);
        // 没有注解
        if (controllerLog == null) {
            return;
        }
        // 处理入参
        String args = this.argsArrayToString(joinPoint.getArgs());
        // 获取请求上下文信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        // 获取时间
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 获取用户信息
        String userName = (String.valueOf(SecurityContextHolder.getContext().getAuthentication().getPrincipal()));
        // 获取系统名称
        String path = request.getRequestURL().toString();
        String[] systemSign = path.split("/");
        String systemName;
        systemName = "基础平台";
        // 组合入参信息
        logger.error("|" + userName + "|" + controllerLog.operationName() + "|" + sd.format(new Date()) + "|"
                + getIpAddr() + "|" + systemName + "|" + "操作日志" + "|" + "null" + "|" + "null");
        logger.error("|" + userName + "|" + controllerLog.operationName() + "|" + sd.format(new Date()) + "|"
                + getIpAddr() + "|" + systemName + "|" + "接口调用日志" + "|" + request.getRequestURI() + "|" + args);
        logger.debug("错误信息为:" + e);
    }

    /**
     * 判断是否有注解
     *
     * @param joinPoint
     * @throws Exception
     */
    private Log getAnnotationLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null) {
            return method.getAnnotation(Log.class);
        }
        return null;
    }

    /**
     * 功能描述:执行日志操作
     *
     * @param: joinPoint ,e ,response
     * @return:
     */
    private void handleLog(final JoinPoint joinPoint, Result jsonResult) {
        Log controllerLog = getAnnotationLog(joinPoint);
        // 没有注解
        if (controllerLog == null) {
            return;
        }
        // 处理入参
        String args = this.argsArrayToString(joinPoint.getArgs());
        // 获取请求上下文信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        // 获取系统名称
        String path = request.getRequestURL().toString();
        String[] systemSign = path.split("/");
        String systemName;
         systemName = "基础平台";
        // 获取时间
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 获取用户信息
        String userName = (String.valueOf(SecurityContextHolder.getContext().getAuthentication().getPrincipal()));
        // 组合入参信息
        logger.info("|" + userName + "|" + controllerLog.operationName() + "|" + sd.format(new Date()) + "|"
                + getIpAddr() + "|" + systemName + "|" + "操作日志" + "|" + "null" + "|" + "null");
        logger.info("|" + userName + "|" + controllerLog.operationName() + "|" + sd.format(new Date()) + "|"
                + getIpAddr() + "|" + systemName + "|" + "接口调用日志" + "|" + request.getRequestURI() + "|" + args);
        logger.info("输出参数:" + JSONArray.toJSONString(jsonResult.getData()));
    }

    /**
     * 组装入参
     *
     * @param paramsArray
     * @return
     */
    private String argsArrayToString(Object[] paramsArray) {
        String params = "";
        if (paramsArray != null && paramsArray.length > 0) {
            for (int i = 0; i < paramsArray.length; i++) {
                if (!isFilterObject(paramsArray[i])) {
                    Object jsonObj = JSON.toJSON(paramsArray[i]);
                    params += jsonObj.toString() + " ";
                }
            }
        }
        if (("").equals(params.trim())) {
            params = "无入参";
        }
        return params.trim();
    }

    /**
     * 判断是否需要过滤的对象。
     *
     * @param o 对象信息。
     * @return 如果是需要过滤的对象,则返回true;否则返回false。
     */
    public boolean isFilterObject(final Object o) {
        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
    }

    public static String getIpAddr() {
        RequestAttributes requsetAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes)requsetAttributes).getRequest();
        String ip = null;
        try {
            ip = request.getHeader("x-forwarded-for");
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 判断为本机的情况
        if ("0:0:0:0:0:0:0:1".equals(ip) || "localhost".equals(ip)) {
            ip = "127.0.0.1";
        }
        return ip;
    }
}

这样就完成了日志收集的第一步!日志打印。