# log-tracing
**Repository Path**: mrbox/log-tracing
## Basic Information
- **Project Name**: log-tracing
- **Description**: Zero-dependency tracing library that correlates logs across HTTP, Feign, RabbitMQ, and async executions using unified traceId. With SkyWalking integration for microservices observability. / Spring Boot 微服务零依赖追踪库,通过统一 traceId 关联 HTTP、Feign、RabbitMQ 和异步执行日志,集成 SkyWalking 实现全面可观测性。
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-01-28
- **Last Updated**: 2026-01-28
## Categories & Tags
**Categories**: Uncategorized
**Tags**: 微服务, 接口日志, RabbitMQ, Skywalking, traceid
## README
# log-tracing 分布式链路追踪组件

[](https://github.com/mr-box/log-tracing/releases)
[](https://www.apache.org/licenses/LICENSE-2.0.html)
[](https://jitpack.io/#mr-box/log-tracing)
## 概述
在微服务架构中,一个用户请求往往需要经过多个服务协同处理。当系统出现问题时,如何快速定位问题?如何追踪请求的完整调用链路?
**log-tracing** 是一个轻量级、低侵入的分布式链路追踪组件,通过统一的 traceId 串联起分散在各个服务中的日志,让您能够:
- 在海量日志中快速检索出一个请求的所有相关日志
- 清晰地看到请求在各个服务间的流转路径和调用关系
- 快速定位问题发生在哪个服务、哪个环节
### 核心特性
- **开箱即用**:引入依赖即可使用,Spring Boot 自动配置
- **自动传递**:HTTP、Feign、RabbitMQ 自动传递 traceId
- **异步支持**:提供工具类和自动增强功能,解决线程池、`@Async`、消息队列等异步场景的链路断裂问题
- **SkyWalking 集成**:与 SkyWalking 无缝集成,保持链路连续性
- **安全可控**:支持 traceId 长度限制、格式验证,防止恶意攻击
- **灵活配置**:支持自定义键名,避免与其他追踪组件冲突
- **按需启用**:支持按需启用/禁用功能模块
### 模块结构
```text
log-tracing
├── log-tracing-core # 核心逻辑模块
│ ├── consts # 常量与枚举定义
│ ├── enhancer # 外部组件增强逻辑
│ │ └── rabbit # RabbitMQ 链路传递增强(支持 MDC 与 SkyWalking)
│ ├── generator # TraceId 生成策略接口及默认实现
│ ├── interceptor # 拦截器(Feign 客户端、WebService)
│ ├── toolkit # 链路追踪工具集
│ │ ├── TracedThreadPoolExecutor # 支持链路传递的 Java 原生线程池
│ │ ├── TracedThreadPoolTaskExecutor # 支持链路传递的 Spring 线程池
│ │ └── XxxTraceWrapper # 函数式接口装饰器(Runnable, Callable, etc.)
│ └── util # 工具类(MDC 操作、SkyWalking 状态检测等)
├── log-tracing-spring-boot-autoconfigure # 自动配置模块
│ ├── config # 各功能模块的条件装配配置
│ ├── processor # Bean 后置处理器(用于自动增强线程池、@Async 等)
│ └── TracingProperties # 属性配置类
└── log-tracing-spring-boot-starter # 启动器模块(快速引入依赖)
```
### 技术栈
- Java 8+
- Spring Boot 2.7.x
- Spring Framework 5.3.x
- SkyWalking 9.3.0(可选)
- RabbitMQ(可选)
- Feign(可选)
## 1. 快速开始
### 1.1 引入依赖
本组件通过 JitPack 发布。
**第一步**:在项目根目录的 `pom.xml` 中添加 JitPack 仓库源:
```xml
jitpack.io
https://jitpack.io
```
**第二步**:添加组件依赖:
```xml
com.github.mr-box.log-tracing
log-tracing-spring-boot-starter
1.0.0
```
组件会自动配置并启用以下功能:
1. Web 请求链路追踪
2. Feign 客户端链路追踪(如果使用了 Feign)
3. Spring Rabbit 消息链路追踪(如果使用了 Spring Rabbit)
4. SkyWalking 集成(如果使用了 SkyWalking Agent)
### 1.2 配置日志格式
在 `logback-spring.xml` 中配置日志格式,添加 traceId:
```xml
%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] %-5level %logger{36} - %msg%n
```
### 1.3 验证效果
启动应用后,查看日志,您会看到每条日志都包含了 traceId:
```
2024-01-23 10:30:15.123 [c466ca11-71c9-4dff-9fbe-d0471d421524] INFO c.e.UserService - 处理用户请求
2024-01-23 10:30:15.234 [c466ca11-71c9-4dff-9fbe-d0471d421524] INFO c.e.OrderService - 创建订单
```
## 2. 配置说明
### 2.1 配置总览
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| `enabled` | `true` | 组件总开关 |
| `enable-pool-task-executor-enhance` | `false` | 是否自动增强所有 ThreadPoolTaskExecutor |
| `enable-async-configurer-executor-enhance` | `false` | 是否自动增强通过 AsyncConfigurer 配置的 @Async 线程池 |
| `web-interceptor.accept-header-trace-id` | `true` | 是否接受请求头中的 traceId |
| `web-interceptor.max-trace-id-length` | `256` | traceId 最大长度 |
| `web-interceptor.validate-trace-id-format` | `false` | 是否验证 traceId 格式 |
| `rabbitmq.enabled` | `true` | 是否启用 RabbitMQ 增强 |
| `key-names.mdc-trace-id` | `traceId` | MDC 中的键名 |
| `key-names.http-header-trace-id` | `X-TraceId` | HTTP Header 中的键名 |
| `key-names.mq-header-trace-id` | `mdc-trace-id` | MQ Header 中的键名 |
### 2.2 完整配置示例
在 `application.yml` 中进行配置,以下示例配置无特殊说明均为默认配置:
```yaml
mr-box:
tracing:
# ========== 基础配置 ==========
# 组件总开关,默认开启
enabled: true
# 是否自动增强所有 ThreadPoolTaskExecutor Bean(默认:false)
# 开启后,Spring 容器中所有的 ThreadPoolTaskExecutor 都会自动支持链路追踪
enable-pool-task-executor-enhance: false
# 是否自动增强通过 AsyncConfigurer 配置的 @Async 线程池(默认:false)
# 开启后,通过实现 AsyncConfigurer 接口配置的 @Async 方法会自动传递 traceId
# 注意:仅对通过 AsyncConfigurer 方式配置的线程池生效,不影响其他配置方式
enable-async-configurer-executor-enhance: false
# ========== 追踪ID键名配置 ==========
# 用于避免与其他追踪组件(Sleuth、SkyWalking、OpenTelemetry)冲突
key-names:
# MDC中的trace id键名(默认:traceId)
mdc-trace-id: traceId
# HTTP请求头、响应头中的trace id键名(默认:X-TraceId)
http-header-trace-id: X-TraceId
# MQ消息header中的trace id键名(默认:mdc-trace-id)
mq-header-trace-id: mdc-trace-id
# ========== Web拦截器配置 ==========
web-interceptor:
# 是否接受请求头中的 traceId(默认:true)
# true: 从请求头中读取 traceId(适用于内部微服务)
# false: 忽略请求头中的 traceId,总是生成新的(适用于 最上游服务/API Gateway)
accept-header-trace-id: true
# traceId 最大长度限制(默认:256)
# 超过此长度将被截断并记录警告日志
# 设置为 0 或负数表示不限制长度
max-trace-id-length: 256
# 是否启用 traceId 格式验证(默认:false)
# true: 只接受符合格式规范的 traceId(字母、数字、中划线、下划线、点号)
# false: 不验证格式
# 建议:面向客户端的服务且 accept-header-trace-id=true 时,推荐启用
validate-trace-id-format: false
# ========== RabbitMQ配置 ==========
rabbitmq:
# 是否启用 RabbitMQ 的链路追踪增强(默认:true)
enabled: true
# 禁用的增强器名称列表(默认:空)
# 可选值:MDC, SkyWalking(不区分大小写)
disable-processors: []
```
### 2.3 Web 拦截器安全配置
针对不同的服务类型,推荐使用不同的安全配置:
#### API Gateway / 最上游服务
```yaml
mr-box:
tracing:
web-interceptor:
accept-header-trace-id: false # 不接受客户端 traceId,防止恶意注入
max-trace-id-length: 256
validate-trace-id-format: false
```
#### 内部微服务 - 高安全要求
```yaml
mr-box:
tracing:
web-interceptor:
accept-header-trace-id: true # 接受上游服务 traceId
max-trace-id-length: 256 # 限制长度,防止超长攻击
validate-trace-id-format: true # 启用格式验证,防止日志注入
```
#### 内部微服务 - 默认配置
```yaml
mr-box:
tracing:
web-interceptor:
accept-header-trace-id: true
max-trace-id-length: 256
validate-trace-id-format: false
```
### 2.4 追踪ID键名自定义
为了避免与其他追踪组件冲突(如 Sleuth ),组件提供了自定义键名的功能,支持自定义键名:
#### 与 Sleuth 共存
```yaml
mr-box:
tracing:
key-names:
http-header-trace-id: X-TraceId
```
**注意事项:**
- 修改键名后,需要确保所有服务使用相同的配置
- 日志配置中的 MDC 键名需要同步修改
- 建议在项目初期就确定键名
## 3. 功能详解
### 3.1 自动传递场景
组件会在以下场景自动传递 traceId:
| 场景 | 说明 | 配置要求 |
|------|------|----------|
| HTTP 请求 | Web 请求自动传递 | 默认启用 |
| Feign 调用 | Feign 客户端自动传递 | 默认启用 |
| RabbitMQ 消息 | 消息生产和消费自动传递 | 默认启用 |
| SkyWalking | 与 SkyWalking 集成 | 需要 SkyWalking Agent |
### 3.2 异步场景支持
#### 方式一:自动增强(推荐)
**增强所有 ThreadPoolTaskExecutor:**
```yaml
mr-box:
tracing:
enable-pool-task-executor-enhance: true
```
开启后,Spring 容器中所有的 `ThreadPoolTaskExecutor` Bean 都会自动支持链路追踪,无需修改代码。
**增强 @Async 线程池(通过 AsyncConfigurer 配置):**
如果您通过实现 `AsyncConfigurer` 接口来配置 `@Async` 的线程池:
```java
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.initialize();
return executor;
}
}
```
可以开启自动增强:
```yaml
mr-box:
tracing:
enable-async-configurer-executor-enhance: true
```
开启后,`@Async` 注解的方法会自动传递 traceId,无需修改代码。
**注意:** 此配置仅对通过 `AsyncConfigurer` 接口配置的线程池生效。如果您使用其他方式配置 `@Async`(如 `@Bean` 方式),请使用方式一或方式二。
#### 方式二:使用 TracedThreadPoolTaskExecutor / TracedThreadPoolExecutor
```java
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
TracedThreadPoolTaskExecutor executor = new TracedThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(200);
executor.setThreadNamePrefix("async-");
return executor;
}
```
#### 方式三:手动包装任务
```java
// Runnable 包装
Runnable task = RunnableTraceWrapper.of(() -> {
// 异步任务,可以获取主线程的 traceId
})
executor.execute(task);
// Callable 包装
Future future = executor.submit(CallableTraceWrapper.of(() -> {
// 业务逻辑
}));
// Consumer 包装(适用于 Stream)
list.parallelStream().forEach(ConsumerTraceWrapper.of(item -> {
// 业务逻辑
}));
// Supplier 包装
Supplier supplier = SupplierTraceWrapper.of(() -> {
// 业务逻辑
});
// Function 包装
Function function = FunctionTraceWrapper.of(item -> {
// 业务逻辑
});
```
### 3.3 工具类
#### 获取 TraceId
```java
// 获取当前 MDC 中的 traceId
Optional traceId = TraceUtils.getMDCTraceId();
// 获取或生成 traceId
String traceId = TraceUtils.getOrGenerateMDCTraceId();
```
#### 设置 TraceId
```java
// 设置 traceId
TraceUtils.setMDCTraceId("your-trace-id");
// 清理 traceId
TraceUtils.removeMDCTraceId();
```
## 4. 高级用法
### 4.1 自定义 TraceId 生成器
默认情况下,组件使用 SkyWalking的TID或UUID 作为 TraceId。如果需要自定义生成策略(如雪花算法、短ID、业务前缀等),可以实现 `TraceIdGenerator` 接口。
当存在多个生成器时,优先级顺序为:
```
手动设置 > Spring Bean > SPI > 默认实现
```
**方式一:Spring Bean(推荐)**
```java
@Configuration
public class TracingConfig {
@Bean
public TraceIdGenerator traceIdGenerator() {
// 使用雪花算法生成数字ID
return new SnowflakeTraceIdGenerator(1L, 1L);
// 或使用短ID(16位随机字符串)
// return new ShortIdGenerator();
// 或使用自定义格式
// return () -> "TRC-" + System.currentTimeMillis() + "-" + UUID.randomUUID().toString().substring(0, 8);
}
}
```
**方式二:SPI 机制**
1. 实现 `TraceIdGenerator` 接口
2. 在 `META-INF/services/com.github.mrbox.logtracing.core.generator.TraceIdGenerator` 文件中注册实现类
**方式三:手动设置**
适用于需要在运行时动态切换生成器的场景。
```java
package com.example;
import com.github.mrbox.logtracing.core.generator.TraceIdGeneratorHolder;
import com.example.tracing.CustomTraceIdGenerator;
public class Application {
public static void main(String[] args) {
// 在应用启动时手动设置生成器
TraceIdGeneratorHolder.setGenerator(new CustomTraceIdGenerator());
// 启动 Spring Boot 应用
SpringApplication.run(Application.class, args);
}
}
```
### 4.2 CompletableFuture 使用
**推荐方式:使用支持追踪的线程池**
```java
TracedThreadPoolTaskExecutor executor = new TracedThreadPoolTaskExecutor();
executor.initialize();
CompletableFuture
.runAsync(() -> { /* 任务1 */ }, executor)
.thenRunAsync(() -> { /* 任务2 */ }, executor)
.thenRun(() -> { /* 任务3 */ })
.exceptionally(ex -> { /* 异常处理 */ return null; });
```
**不推荐方式:手动包装所有任务**
```java
CompletableFuture
.runAsync(RunnableTraceWrapper.of(() -> { /* 任务1 */ }))
.thenRunAsync(RunnableTraceWrapper.of(() -> { /* 任务2 */ }))
.thenRun(RunnableTraceWrapper.of(() -> { /* 任务3 */ }))
.exceptionally(FunctionTraceWrapper.of(ex -> { return null; }));
```
### 4.3 RabbitMQ 自定义配置
如果需要自定义 RabbitMQ 的线程池,注意不要使用 `TracedThreadPoolTaskExecutor` / `TracedThreadPoolExecutor`:
```java
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// ❌ 错误:使用增强的 TracedThreadPoolTaskExecutor
// ✅ 正确:使用普通的 ThreadPoolTaskExecutor
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
// ... 其他配置
executor.initialize();
factory.setTaskExecutor(executor);
return factory;
}
```
**原因:** 如果使用了`TracedXxxExecutor`,每个消费者线程都会创建一个异步链路且一直复用。
虽然当开启SkyWalking增强时会在首次消费时终止该链路,仍建议尽量避免使用。
## 5. 最佳实践
### 5.1 日志配置
**Logback 配置示例:**
```xml
%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] [%thread] %-5level %logger{36} - %msg%n
logs/application.log
%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] [%thread] %-5level %logger{36} - %msg%n
logs/application.%d{yyyy-MM-dd}.log
30
```
### 5.2 服务分层配置
**API Gateway:**
```yaml
mr-box:
tracing:
web-interceptor:
accept-header-trace-id: false # 不接受客户端 traceId
```
**业务服务:**
```yaml
mr-box:
tracing:
web-interceptor:
accept-header-trace-id: true # 接受上游 traceId
validate-trace-id-format: true # 启用格式验证
enable-pool-task-executor-enhance: true # 启用线程池自动增强
```
**消息消费者:**
```yaml
mr-box:
tracing:
rabbitmq:
enabled: true
enable-pool-task-executor-enhance: true
```
## 6. 故障排查
### 6.1 traceId 没有传递
**检查清单:**
1. 确认组件已启用
```yaml
mr-box:
tracing:
enabled: true
```
2. 确认日志配置正确
```xml
%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] ...
```
3. 确认 MDC 键名匹配
```yaml
key-names:
mdc-trace-id: traceId # 与日志配置中的 %X{traceId} 匹配
```
### 6.2 异步任务没有 traceId
**解决方案:**
1. 启用自动增强
```yaml
enable-pool-task-executor-enhance: true
```
2. 或使用 `TracedThreadPoolTaskExecutor`
3. 或手动包装任务
```java
executor.execute(RunnableTraceWrapper.of(() -> { ... }));
```
### 6.3 RabbitMQ 消息没有 traceId
**检查清单:**
1. 确认 RabbitMQ 增强已启用
```yaml
rabbitmq:
enabled: true
```
2. 检查是否禁用了增强器
```yaml
rabbitmq:
disable-processors: [] # 确保为空
```
## 7. 常见问题
### Q1: 与 Spring Cloud Sleuth 有什么区别?
**A:** 两者的侧重点完全不同。**log-tracing** 专注于解决“日志串联”问题,特别是针对 **Spring RabbitMQ 消费者端 SkyWalking 链路断裂** 的痛点进行了深度增强。
| 维度 | log-tracing | Spring Cloud Sleuth |
| :--- | :--- | :--- |
| **核心定位** | **轻量级日志增强工具** | **全功能链路追踪方案** |
| **RabbitMQ 支持** | **深度增强**
在串联业务日志的基础上,重点解决了 **Consumer 端的 SkyWalking 链路断裂问题** | **基础支持**
支持生产/消费者日志串联,但**无法解决**异步消息消费导致的 SkyWalking 链路断开 |
| **SkyWalking 集成** | **深度协同**
核心目标是保证 **SkyWalking 链路在异步/消息场景下的连续性**,同时也支持复用其 TraceId | **独立体系**
通常作为独立的追踪体系运行,无法解决 SkyWalking 的链路连续性痛点 |
| **复杂度与性能** | **极低开销**
仅操作 MDC 和 Header,适合对性能要求严苛且只需日志串联的场景 | **中等开销**
包含 Span 管理、采样、耗时统计及数据上报,依赖较重 |
**核心价值点:**
如果您在使用 SkyWalking 时发现 **RabbitMQ 消费者端链路断裂**,或者觉得 Sleuth 太重、只想纯粹地串联日志,**log-tracing** 是更精准的选择。它能完美补齐 APM 工具(如 SkyWalking)在消息队列场景下的“断链”短板。
### Q2: 是否支持 Spring Boot 3.x?
**A:** 当前版本基于 Spring Boot 2.7.x,Spring Boot 3.x 暂不支持。
### Q3: 是否支持 RocketMQ/Kafka?
**A:** 当前版本只支持 RabbitMQ,RocketMQ/Kafka 支持计划在后续版本中添加。
### Q4: 如何与 SkyWalking 集成?
**A:** 只需在启动时添加 SkyWalking Agent,组件会自动集成:
```bash
java -javaagent:/path/to/skywalking-agent.jar -jar your-app.jar
```
## 8. 贡献指南
[CONTRIBUTING.md](CONTRIBUTING.md)
## 9. 许可证
本项目采用 [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html) 许可证。
## 10. 联系方式
- **Issues**: [GitHub Issues](https://github.com/mr-box/log-tracing/issues)
- **Email**: wel.come@qq.com
---
**⭐ 如果这个项目对您有帮助,请给个 Star!**