非Spring Boot应用中Spring Cloud Sleuth日志链路ID测试方案
你不需要依赖Spring Boot自动配置就能完成验证,核心逻辑很明确:Spring Cloud Sleuth的链路字段本质是写入SLF4J的MDC上下文,你的Logback配置只是从MDC读取对应key输出,验证分两个层面做就可以,既可以在模块本身做无Spring依赖的单元测试,也可以模拟下游引入场景做集成验证。
单元层验证(无Spring容器依赖,模块内直接完成)
这个测试不需要启动Spring上下文,也不需要引入Spring Boot相关依赖,直接在当前unified-logging模块的test作用域下完成即可:
- 先确认test作用域的依赖:你本身已经有logback-classic依赖,额外加junit、spring-cloud-sleuth-core(仅核心API,不带自动配置)即可,这些依赖不会打包进模块最终产物,也不会传递给下游业务应用。
- Sleuth的核心链路组件本身就是普通Java对象,完全可以手动初始化,不需要Spring容器托管。直接写测试类初始化Tracer,模拟链路场景即可:
import brave.Span; import brave.Tracer; import brave.Tracing; import brave.propagation.StrictCurrentTraceContext; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; public class LogTraceConfigTest { private static final Logger log = LoggerFactory.getLogger(LogTraceConfigTest.class); @Test public void testMdcInjectAndLogOutput() { // 手动初始化Sleuth核心组件,无Spring依赖 StrictCurrentTraceContext traceContext = StrictCurrentTraceContext.create(); Tracing tracing = Tracing.newBuilder() .currentTraceContext(traceContext) .build(); Tracer tracer = tracing.tracer(); Span testSpan = tracer.newTrace().name("test-log-op").start(); try (Tracer.SpanInScope ignored = tracer.withSpanInScope(testSpan)) { // 第一步验证MDC写入是否正常 String traceId = MDC.get("traceId"); String spanId = MDC.get("spanId"); assert traceId != null && !traceId.isBlank(); assert spanId != null && !spanId.isBlank(); // 第二步打日志验证Logback输出规则 log.info("test trace logging output"); } finally { testSpan.finish(); tracing.close(); traceContext.close(); } } }
- 运行测试后直接看控制台日志输出,如果你配置的trace嵌套字段里traceId、spanId都有实际的十六进制值,不是空字符串,就说明MDC注入+Logback配置的链路是通的。
小提示:如果MDC读不到值,先检查你引入的Sleuth对应brave版本是否默认开启MDC注入,高版本brave默认加载MDCScopeDecorator,只要没有手动禁用,Span进入作用域时就会自动把链路信息写入MDC,不需要额外写配置。
集成层验证(模拟下游业务应用引入场景)
因为你的模块最终是给Spring Boot业务系统当依赖用的,你可以在test作用域下加最小化的Spring Boot测试环境,完全模拟真实使用场景,这部分测试代码不会影响模块的正式打包:
- 在test作用域添加依赖:spring-boot-starter-test、spring-cloud-starter-sleuth,scope统一设为test,不会传递给下游。
- 在test目录下写一个最简Spring Boot启动类,不需要加任何额外配置:
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MockBizApplication { public static void main(String[] args) { org.springframework.boot.SpringApplication.run(MockBizApplication.class, args); } }
- 写对应的Spring环境测试用例:
import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest(classes = MockBizApplication.class) public class BizScenarioLogTest { private static final Logger log = LoggerFactory.getLogger(BizScenarioLogTest.class); @Test public void testLogOutput() { log.info("mock biz request log"); } }
- 运行测试后检查日志输出,如果trace字段下的三个链路id都正常生成非空值,就说明业务应用引入你的模块后,链路日志注入可以正常工作。
快速校验Logback配置正确性
如果你想先排除Logback配置本身的问题,完全不需要引入Sleuth,直接写个最简单的测试手动往MDC塞固定值即可:
@Test public void testLogbackConfig() { MDC.put("traceId", "test-trace-id-001"); MDC.put("parentSpanId", "test-parent-id-001"); MDC.put("spanId", "test-span-id-001"); log.info("test logback pattern"); MDC.clear(); }
运行后看日志,如果trace字段里的三个值和你手动塞的固定值完全一致,就说明Logback的输出规则没有问题,后续只要确认Sleuth能正常往MDC写值就可以。
内容的提问来源于stack exchange,提问作者Obaid Maroof
相关产品推荐
相关产品推荐

