← 中文资源

简体中文版本

在测试中断言链路 Span

用内存导出器断言 Span 名称、父子关系、属性与错误状态,在事故之前发现断开的调用链。

阅读英文原文

概述

链路追踪的失效是安静的。上下文没有传递、Provider 注册太晚、采样器丢弃全部数据,都会产生看起来合理但彼此断开或不完整的链路。平时没人注意,事故时才暴露,代价最大。链路测试把期望的结构写成断言,让问题在 CI 中失败。

步骤

  1. 在测试启动文件中注册带内存导出器的 Provider:
const exporter = new InMemorySpanExporter();
const provider = new NodeTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
provider.register();
  1. 发一次请求,按 http.route 属性而不是插桩生成的 Span 名称定位根 Span。
  2. 断言父子关系与关键属性,例如 db.system、http.response.status_code。
  3. 发送已知的 traceparent,断言导出的 Span 使用相同的 trace id。
  4. 每次断言前清空导出器,再制造依赖失败,断言对应 Span 状态为 ERROR 且包含 exception 事件。

验证

成功请求应同时出现服务端 Span 与 db.query orders,且后者的父 Span 是前者。带 traceparent: 00-4bf92f...-01 的请求,根 Span 的 trace id 应为 4bf92f3577b34da6a3ce929d0e0e4736。注入数据库失败后,该 Span 应为 ERROR 并记录异常。

注意事项

  • 内存导出器只覆盖当前进程,跨服务的链路需要端到端验证。
  • Span 名称与属性依赖插桩版本,应断言自己定义的契约而不是框架默认值。
  • 使用 BatchSpanProcessor 时必须在断言前 forceFlush,否则会丢 Span。
  • 不要重复注册全局 Provider,第二次注册会被忽略,测试实际断言的是错误的导出器。
  • 链路采集会改变时序,功能测试中不要断言 Span 耗时。