使用自定义注解打印 logstash 日志
作者:小黄鸡1992
- 2021 年 12 月 03 日
本文字数:3698 字
阅读完需:约 12 分钟
在收集日志时,首先需要打印 logstash 日志。所以使用 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;
}
}
复制代码
这样就完成了日志收集的第一步!日志打印。
划线
评论
复制
发布于: 3 小时前阅读数: 6
版权声明: 本文为 InfoQ 作者【小黄鸡1992】的原创文章。
原文链接:【http://xie.infoq.cn/article/3786fffd43182700320b8f5d6】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
小黄鸡1992
关注
小黄鸡加油 2021.07.13 加入
一位技术落地与应用的博主,带你从入门,了解和使用各项顶流开源项目。
评论