skywalking gateway 日志traceId 丢失

问题描述

当前运维监控系统会将超时接口的告警信息发送至企业邮箱,但邮件中未包含Gateway的TraceID,导致在排查分布式链路问题时难以快速定位和追踪。

排查思路

1. 检查插件依赖

首先确认在APM插件(plugin)中是否已正确引入Gateway相关依赖包。若缺少Gateway组件包,会导致无法捕获和传递TraceID。

2.项目工程是否确实相关依赖
        <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-logback-1.x</artifactId>
            <version>8.5.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-trace</artifactId>
            <version>8.5.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-webflux</artifactId>
            <version>9.4.0</version>
        </dependency>

以上验证完成,但是日志中还是无TID。偶然debug发现TraceId可以再ServerWebExchange获取到。

于是就考虑到自己将traceId 拿到到,利用MDC工具拼接到日志中。

简单普及一下MDC的做作用

MDC(Mapped Diagnostic Context)是日志框架提供的用于跨方法传递上下文信息的工具,特别适合在分布式系统中传递 TraceID、用户信息等公共参数。

代码实现

  • 1.通过反射将tid值获取到
public class SkywalkingUtil {

	/**
	 * tid放入MDC
	 *
	 * @param exchange
	 */
	public static void putTidIntoMdc(ServerWebExchange exchange) {
		try {
			Object entrySpanInstance = exchange.getAttributes().get("SKYWALING_SPAN");
			if (ObjectUtil.isEmpty(entrySpanInstance)) {
				return;
			}
			Class<?> entrySpanClazz = entrySpanInstance.getClass().getSuperclass().getSuperclass();
			Field field = entrySpanClazz.getDeclaredField("owner");
			field.setAccessible(true);
			Object ownerInstance = field.get(entrySpanInstance);
			Class<?> ownerClazz = ownerInstance.getClass();
			Method getTraceId = ownerClazz.getMethod("getReadablePrimaryTraceId");
			String traceId = (String) getTraceId.invoke(ownerInstance);
			MDC.put("qinqing", traceId);
		} catch (Exception e) {
			log.error("未加载加到skywalking信息", e);
		}
	}

}
    • 2.添加过滤器再请求被订阅时将traceId放入
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        return chain.filter(exchange)
                .doOnSubscribe(s -> {  // 当订阅发生时(请求开始时)执行
                    String traceId = WebFluxSkyWalkingTraceContext.traceId(exchange);
                    if (traceId.isEmpty()) {  // 如果SkyWalking未生成TraceID
                        SkywalkingUtil.putTidIntoMdc(exchange);  // 自定义工具类生成并存入MDC
                    }
                })
                .doFinally(s -> MDC.remove("qinqing"));  // 请求结束时清理MDC
    }
    关键点说明
    1. 执行时机

      • doOnSubscribe:在请求处理管道被订阅时触发(相当于Servlet过滤器的doFilter

      • doFinally:无论成功/异常都会执行(类似finally块)

    2. TraceID处理逻辑

      • 优先尝试从WebFluxSkyWalkingTraceContext获取SkyWalking的TraceID

      • 如果获取失败(空值),则通过SkywalkingUtil生成并存入MDC

      • 使用的MDC Key为"CBIMTID"(推测是项目自定义的键名)

    3. 资源清理

      • 通过MDC.remove()确保线程局部变量不会内存泄漏

      • 在响应完成后立即清理,避免污染后续请求

    3. 日志中组装为TID输出格式
        <property name="CONSOLE_LOG_PATTERN"
                  value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [${servername}] [%thread] [%logger{50}:%L] [TID: %X{qinqing}] %msg%n"/>

    测试验证

    • gateway 中打印的日志

    • A服务中调用的日志

    • skywalking中日志追踪链
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值