对于日志收集,是系统离不开的功能,那么如何实现简易的日志收集呢。市面上最常见的就是使用自定义注解。本文将介绍如何使用自定义注解收集日志。
1.添加自定义注解
@Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Log { /** * 注释 */ String operationName() default ""; }
2.使用AOP拦截注解
该类的含义是:没调用一个接口,都会判断该接口是否带有上文的自定义注解,如果带有,就会执行AOP中的功能,本文是获取入参,出参,sql,方法名,系统名,调用ip等参数,并打印。
@Component public class LogAspect { private Logger logger = LoggerFactory.getLogger(LogAspect.class); private String succeed = "true"; /** * 在注释@log的方法中进入本类 */ @Pointcut("@annotation(com.resource.business.modular.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())); // 组合入参信息 logger.error("|" + userName + "|" + controllerLog.operationName() + "|" + sd.format(new Date()) + "|" + IpUtil.getIpAddr() + "|" + "XXX系统" + "|" + "操作日志" + "|" + "null" + "|" + "null"); logger.error("|" + userName + "|" + controllerLog.operationName() + "|" + sd.format(new Date()) + "|" + IpUtil.getIpAddr() + "|" + "XXX系统" + "|" + "接口日志" + "|" + 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(); // 获取时间 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()) + "|" + IpUtil.getIpAddr() + "|" + "XXX系统" + "|" + "操作日志" + "|" + "null" + "|" + "null"); logger.info("|" + userName + "|" + controllerLog.operationName() + "|" + sd.format(new Date()) + "|" + IpUtil.getIpAddr() + "|" + "XXX系统" + "|" + "接口日志" + "|" + 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; } }
注意:楼主使用elk收集了日志,输出在logstash中获取“|” 然后拆分成不同字段,并保存在es中,可在后续文章看到。