-
前言
-
一. 从controller层api的日志封装打印:
-
二.Dubbo调用日志插件:
-
结尾
前言
日志对于java项目来说非常的重要,很多时候排查问题需要我们根据日志去分析,所以项目的日志打印封装非常重要,下面根据我总结的针对控制器controller层的api和常见的dubbo日志封装进行总结,希望能对java从业者有帮助。
一. 从controller层api的日志封装打印:
1.1. 切包:
从controller控制器层进行切注解完成日志日的切面打印是比较常规的做法:
1.2. 切注解:
当然有些非控制器controller的地方通过自定义注解进行切面打印日志也是可以的:
1.3. 总结AOP切面你的流程图:
无论是切控制器controller还是切注解,都是利用AOP的方式进行了切面打印日志的方法,下面的额流程图可以很直观的反映出来处理流程:
二.Dubbo调用日志插件:
如果微服务是基于dubbo的微服务,可以利用dubbo的特性进行封装对应的logfilter,能够完整的把消费者和提供者的日志完全的打印,主要是利用的com.alibaba.dubbo.rpc.Filter:
2.1.代码实现:
@Activate(group = {"provider", "consumer"})
@Slf4j
public class LogFilter implements Filter {
public static List<String> IGNORE_LIST = new ArrayList<>();
static {
IGNORE_LIST.add("org.apache.dubbo.monitor.MonitorService");
IGNORE_LIST.add("com.alibaba.dubbo.monitor.MonitorService");
}
/**
* @Author:
* @Description:进行dubbo调用封装
* @Params:
* @Return:
* @Date: 2023/4/23 10:00
*/
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
Long takeTime = 0L;//耗时取值
Result result = null;
String className = "";
boolean isProvider = false;
long startTime = System.currentTimeMillis();
String fullClassName = "";
try {
className = invoker.getInterface().getSimpleName();
fullClassName = invoker.getInterface().getName();
if ("consumer".equals(invoker.getUrl().getParameter("side"))) {
if (!IGNORE_LIST.contains(fullClassName)) {
log.info("[DubboMethod]:{} [Param]:{}", className + "." + invocation.getMethodName(), JSON.toJSONString(invocation.getArguments()));
}
result = invokeConsumer(invoker, invocation);
} else {
isProvider = true;
result = invokeProvider(invoker, invocation);
}
takeTime = System.currentTimeMillis() - startTime;
if (!IGNORE_LIST.contains(fullClassName)) {
String methodName = invocation.getMethodName();
if (!methodName.endsWith("Bytes")) {// 约定Bytes结尾的方法不打印日志
log.info(LogUtil.overTime(takeTime) + "[DubboMethod]:{} [Result]:{},耗时:{}ms", className + "." + invocation.getMethodName(), JSON.toJSONString(result.getValue()), takeTime);
}
}
} catch (Exception e) {
takeTime = System.currentTimeMillis() - startTime;
if (!IGNORE_LIST.contains(fullClassName)) {
log.error(LogUtil.overTime(takeTime) + "[DubboMethod]:{} 耗时:{}ms exception:", className + "." + invocation.getMethodName(), takeTime, e);
}
throw e;
} finally {
if (isProvider) {
MDC.clear();
}
}
return result;
}
/**
* @Author:
* @Description:消费方
* @Params:
* @Return:
* @Date: 2022/9/20 11:26
*/
private Result invokeConsumer(Invoker<?> invoker, Invocation invocation) {
return invoker.invoke(invocation);
}
/**
* @Author:
* @Description:提供方
* @Params:
* @Return:
* @Date: 2022/9/20 11:25
*/
private Result invokeProvider(Invoker<?> invoker, Invocation invocation) {
try {
String className = invoker.getInterface().getSimpleName();
String fullClassName = invoker.getInterface().getName();
if (!IGNORE_LIST.contains(fullClassName)) {
log.info("[DubboMethod]:{} [Param]:{}", className + "." + invocation.getMethodName(), JSON.toJSONString(invocation.getArguments()));
}
} catch (Exception e) {
log.error("自定义切面发生异常", e);
}
return invoker.invoke(invocation);
}
2.2 实现效果:
[INFO ] 2022-11-02 09:43:21.783 [http-nio-8080-exec-4] [com.xxxx.ka.plugin.dubbo.LogFilter] [dd47975101a61c78] - [DubboMethod]:ESCPrivilegeService.authPrivilege [Param]:[{"authContent":"lmt_privilege_modify","authType":1,"subPlatform":1,"sysType":5,"userId":2752119}]
[INFO ] 2022-11-02 09:43:21.799 [http-nio-8080-exec-4] [com.xxxx.ka.plugin.dubbo.LogFilter] [dd47975101a61c78] - [DubboMethod]:ESCPrivilegeService.authPrivilege [Result]:{"code":"0000","data":{"pass":true},"result":"成功","success":true},耗时:16ms
结尾
上面是整个梳理的java中打印日志的常用的解决方案,其实已经是概括的比较全面的,也是经过生产实践验证通过的,当然没有完全的把代码进行粘贴,使用的时候需要再进行改造下。如果有问题,欢迎随时交流。
原文始发于微信公众号(Java时间屋):Java项目日志天花板
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/251770.html