分布式项目集成TLog实现轻量级日志链路追踪

hello,大家好,我是灰小猿!

随着公司业务的不断扩增,不同的业务中心逐渐开始采用不同的服务来完成,这就出现了典型的服务调用场景,随着调用服务节点的不断增加,分布式服务日志链路问题便随之出现,这也导致了开发同学在做请求日志链路排查时变得十分困难,往往很难完整的获取到整个链路的日志信息。

其实做日志链路追踪的基本思想:都是在整条调用链路中设置一个Trace_id,并不断传递输出在日志中,同时再结合标准输出的全局异常捕获,即可满足,基本原理如下:

但当前市面上已经有了比较完善的原理基本类似的解决框架,所以经过技术分析和对比,并结合项目情况,我采用TLog的方式来进行日志链路追踪,

具体的集成操作我就不再赘述,TLog官网已经介绍的十分详细:
TLog官网

这里我主要记录在springboot版本是3.2.4,jakarta版本是6.0.0的情况下,引入1.5.2版本的TLog,出现的若干问题及解决。(1.5.2版本的TLog是我截止发文能获取到的最新版本)

问题一:TLog底层依赖javax.*,但该依赖已停用并更新至 jakarta.*,导致控制台无法打印Trace_id等信息问题解决

如果你的项目仍然在使用javax依赖,那么大概率不会出现任何问题,但是如果你和我一样,已经更新为了Jakarta依赖,那么问题就会接踵而至。

想要解决这个问题,需要将"TLog的过滤器"和"TLog web的逻辑封装"这两个核心方法进行重写,主要是为了替换成Jakarta依赖

具体如下:

重写-TLog的过滤器

java 复制代码
import com.yomahub.tlog.constant.TLogConstants;
import com.yomahub.tlog.context.TLogContext;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

/**
 * 重写TLog过滤器,兼容jakarta
 */
public class TLogFilter implements Filter {


  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
      try {
        TLogWebCommon.loadInstance().preHandle((HttpServletRequest) request);
        //把traceId放入response的header,方便从前端拿整条链路的traceId
        ((HttpServletResponse) response).addHeader(TLogConstants.TLOG_TRACE_KEY, TLogContext.getTraceId());
        chain.doFilter(request, response);
        return;
      } finally {
        TLogWebCommon.loadInstance().afterCompletion();
      }
    }
    chain.doFilter(request, response);
  }

}

重写-TLog web的逻辑封装

java 复制代码
import com.yomahub.tlog.constant.TLogConstants;
import com.yomahub.tlog.core.rpc.TLogLabelBean;
import com.yomahub.tlog.core.rpc.TLogRPCHandler;
import jakarta.servlet.http.HttpServletRequest;
 
 
/**
 * TLog web的逻辑封装
 */
public class TLogWebCommon extends TLogRPCHandler {
 
    private static volatile TLogWebCommon tLogWebCommon;
 
    public static TLogWebCommon loadInstance() {
        if (tLogWebCommon == null) {
            synchronized (TLogWebCommon.class) {
                if (tLogWebCommon == null) {
                    tLogWebCommon = new TLogWebCommon();
                }
            }
        }
        return tLogWebCommon;
    }
 
    public void preHandle(HttpServletRequest request) {
        String traceId = request.getHeader(TLogConstants.TLOG_TRACE_KEY);
        String spanId = request.getHeader(TLogConstants.TLOG_SPANID_KEY);
        String preIvkApp = request.getHeader(TLogConstants.PRE_IVK_APP_KEY);
        String preIvkHost = request.getHeader(TLogConstants.PRE_IVK_APP_HOST);
        String preIp = request.getHeader(TLogConstants.PRE_IP_KEY);
 
        TLogLabelBean labelBean = new TLogLabelBean(preIvkApp, preIvkHost, preIp, traceId, spanId);
 
        processProviderSide(labelBean);
    }
 
    public void afterCompletion() {
        cleanThreadLocal();
    }
}

之后将其注册到配置

java 复制代码
import com.yomahub.tlog.feign.filter.TLogFeignFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 日志链路配置
 */
@Configuration
public class LogLinkConfig {

  @Bean
  public FilterRegistrationBean<TLogFilter> loggingFilter() {
    FilterRegistrationBean<TLogFilter> registrationBean = new FilterRegistrationBean<>();
    registrationBean.setFilter(new TLogFilter());
    // 拦截所有请求路径
    registrationBean.addUrlPatterns("/*");
    return registrationBean;
  }
}

这样重写之后,TLog在控制台的日志就可以正常输出Trace_id信息

问题二:服务间调用时,同一请求在不同的服务下打印日志输出的Trace_id不同问题解决

问题和上述同理,也是由于TLog引用的是jacx导致的,导致原来注册在TLog的config都不会生效,因此我们需要将TLogFeignFilter在我们的配置中重新注入:

直接在上面的LogLinkConfig 中添加注入TLogFeignFilter后,完整配置代码如下:

java 复制代码
import com.yomahub.tlog.feign.filter.TLogFeignFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 日志链路配置
 */
@Configuration
public class LogLinkConfig {

  @Bean
  public FilterRegistrationBean<TLogFilter> loggingFilter() {
    FilterRegistrationBean<TLogFilter> registrationBean = new FilterRegistrationBean<>();
    registrationBean.setFilter(new TLogFilter());
    // 拦截所有请求路径
    registrationBean.addUrlPatterns("/*");
    return registrationBean;
  }

  @Bean
  public TLogFeignFilter getTLogFeignFilter() {
    return new TLogFeignFilter();
  }
}

之后重启服务并重新调用,可见在不同的服务下对同一次请求输出的Trace_id完全一致,达到链路追踪的目的。

目前在集成的过程中就遇到了这两个问题,如果后面有发现其他问题我会再继续补充,

我是灰小猿,我们下期见!

相关推荐
2501_914245939 小时前
Java应用性能调优与生产监控部署:2026年实战手册
java·开发语言
爱学习的小可爱卢9 小时前
SpringCloud——微服务排错实战:从Gateway到Feign全链路解析
运维·springcloud
吴声子夜歌9 小时前
MongoDB 4.x——微服务入门
java·mongodb·微服务
霸道流氓气质9 小时前
Kiro 中配置 RabbitMQ MCP Server 指南
分布式·rabbitmq·ruby
好好沉淀9 小时前
主键选择(自增 vs UUID vs 雪花算法)
java·算法
国科安芯9 小时前
AS32S601型抗辐射MCU在分布式太空算力架构中的技术演进与应用前景
人工智能·分布式·单片机·嵌入式硬件·架构·边缘计算
带刺的坐椅9 小时前
Solon AI:Tool 与 Talent 怎么选?从函数到领域专家
java·ai·llm·agent·solon
小白说大模型10 小时前
AI Agent 调试实战:链路追踪、Prompt 可视化与异常定位的系统方法
java·人工智能·python·算法·prompt
静水楼台x10 小时前
spring security
java·数据库·spring
重生之我是Java开发战士10 小时前
【Java EE】Spring Boot配置文件
java·spring boot·java-ee