解决SkyWalking在gateway中logback链路丢失

type
status
date
slug
summary
tags
category
icon
password

契机

😀
吴晟大佬:Why ping me? The plugin is not written by me. I don't know anything about agent running in Spring cloud.
一年半以前,公司就从单体应用逐步迁移到微服务管理。奈何业务绑定太深,一直在两边混合开发。由于迁移到微服务的进程完成了一大半了,之前在单体项目中打的链路追踪就不太好用了。随即想到了SkyWalking,随即发现了一个大坑,那就是在gateway组件中logback日志会丢失TraceId,网上搜了一圈都没有解决问题,我又跑到SkyWalking的issue中搜了一大圈,发现大佬以下回答,还是得自己想办法。
notion image

场景复现

版本

  • spring-cloud-gateway-dependencies = 3.1.3
  • skywalking-oap-server:9.3.0
  • skywalking-ui:9.3.0
  • apache-skywalking-java-agent:9.0.0
  • 假设有gateway+user两个模块
 

skyWalking环境搭建

agent目录配置

maven依赖

项目运行配置

gateway和user模块都配上一下参数,注意SW_AGENT_NAME要变一下
notion image
 

logback配置

gateway模块请求日志打印代码

就是打印四条信息:请求开始,请求头,请求结束信息,请求结束返回

user模块测试代码

 

访问测试

通过网关访问testSkywalking测试结果如下
gateway日志
user日志
可以明显看到user模块的tid是正常输出的,可是gateway的日志死活都是N/A
 

尝试解决

分析问题

首先去去看看哪里输出的这个追踪码,没有找到9.0.0的源码,只找到8.7.0的源码,先搞下来研究研究:https://github.com/apache/skywalking/blob/v8.7.0/。然后定位到logback插件,去寻找tid在哪里输出的,最终找到如下:
apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/log/logback/v1/x/PrintTraceIdInterceptor.java
观察代码无非就是skyWalkingContext.getTraceId()和ContextManager.xx输出的N/A。
Reator模式又有点陌生,无从下手。无意间从另外一篇博客中发现,其实exchange中是有这个tid的
notion image

曲线救国

gateway也就拦截器打印点日志,要不然就是exceptionHandler中打印。我要不然直接把这个值传给skywalking-logback插件就完了嘛。拿什么传呢,对的,使用MDC来传,同一个线程都可以传,并且改动最小。直接修改插件中PrintTraceIdInterceptor的源码如下,然后直接打包这个8.7的skywalking-logback插件替换掉原本apm-toolkit-logback-1.x-activation-9.0.0.jar插件(完全可用)
然后再搞一个工具类
然后在gateway拦截器日志打印的地方加上以下代码,但是请求开始和请求结束是两个不同的线程啊,无法使用MDC来传递,架不住打印日志的地方都使用的一个exchange,当然为了保险你可以在每一个gatway模块的log之前加上以下语句

验证

gateway日志
user日志
确实可用,完美解决

总结

  • 就是把apm-toolkit-logback-1.x-activation插件改了点代码替换掉
  • 然后在gatway模块的日志前面用MDC传了点值进到插件里面
  • 相当取巧,因为gatway也没啥日志
  • 目前看来没什么问题

写到最后

notion image
是在往前走就好 bothsavage.github.io
 
notion image
 
Java部署脚本&重启备份检查&配置环境Notion文章自动同步GitPage