← 中文资源

简体中文版本

W3C traceparent 头解析

解析并校验 W3C traceparent 头,提取版本、trace id、span id 与标志位,拒绝畸形取值。

阅读英文原文

功能说明

该示例解析分布式追踪的 traceparent 传播头,把它拆成版本、trace id、span id 与采样标志。它对每个字段做格式与语义校验:版本须为两位十六进制且不能是保留值 ff,trace id 与 span id 的长度和字符集必须正确,且都不能为全零,标志位为两位十六进制,最低位表示是否采样。

关键代码

解析先按连字符切成四段,段数不对即抛错。长度校验用动态构造的正则表达式,避免为 trace 与 span 分别硬编码长度。全零校验是 W3C 规范要求:零值标识无效,必须拒绝而不是回退。标志位解析为整数后与 1 做按位与,判断采样位。所有失败路径都抛出带字段名的 SyntaxError,便于调用方定位。

使用注意

调用方在服务入口解析该头,若缺失或非法应自行生成新的随机 trace 与 span id 并继续,而不是让请求失败,否则会放大上游的错误。该实现只解析,不负责生成或传播;向下游转发时应原样透传版本与标志。注意大小写:规范要求十六进制为小写,本实现未自动归一化,调用前应确认输入已符合规范。

代码示例

const HEX = { trace: 32, span: 16 };

export function parseTraceparent(value) {
  if (typeof value !== 'string') throw new TypeError('traceparent must be a string');
  const parts = value.trim().split('-');
  if (parts.length !== 4) throw new SyntaxError('traceparent must have 4 fields');
  const [version, traceId, spanId, flags] = parts;
  if (!/^[0-9a-f]{2}$/.test(version)) throw new SyntaxError('invalid version: ' + version);
  if (version === 'ff') throw new SyntaxError('version ff is invalid');
  if (!new RegExp('^[0-9a-f]{' + HEX.trace + '}$').test(traceId)) {
    throw new SyntaxError('invalid trace id: ' + traceId);
  }
  if (traceId === '0'.repeat(HEX.trace)) throw new SyntaxError('trace id must not be all zeros');
  if (!new RegExp('^[0-9a-f]{' + HEX.span + '}$').test(spanId)) {
    throw new SyntaxError('invalid span id: ' + spanId);
  }
  if (spanId === '0'.repeat(HEX.span)) throw new SyntaxError('span id must not be all zeros');
  if (!/^[0-9a-f]{2}$/.test(flags)) throw new SyntaxError('invalid flags: ' + flags);
  return { version, traceId, spanId, sampled: (parseInt(flags, 16) & 1) === 1 };
}