← 中文资源

简体中文版本

尾部采样决策

依据完整链路的时长、错误状态与兜底采样率,决定是否保留该链路。

阅读英文原文

功能说明

该示例实现尾部采样决策:与头部采样在结果未知时下注不同,它看到整条链路的全部 span 后再判断。策略优先保留含错误的链路,其次保留耗时超过阈值的慢链路,最后对普通链路按兜底比例随机保留。返回带有决策原因,便于统计各类别的保留比例。

关键代码

Span 记录名称、时长与错误标志;Policy 集中可调阈值与开关。决策按优先级短路:空链路直接丢弃;开启错误保留且有任一 span 出错即保留;取全链路最大耗时与慢阈值比较;否则按兜底比例抽样。随机源可注入,测试时传入固定种子的 Random 即可得到可复现的决策,避免断言依赖真实随机。

使用注意

该函数假定调用方已经收齐同一链路的全部 span;若 span 分散在不同节点,必须先按 trace id 路由到同一决策点,否则决策基于不完整信息。真实实现还需环形缓冲与超时:等待窗口过短会漏掉慢链路,过长会占用大量内存。被保留或被丢弃都应计入采样率,使下游能正确加权统计,否则保留偏差会扭曲聚合指标。

代码示例

from dataclasses import dataclass, field
import random

@dataclass
class Span:
    name: str
    duration_ms: float
    error: bool = False

@dataclass
class Policy:
    slow_ms: float = 500.0
    keep_errors: bool = True,
    fallback_rate: float = 0.01

def decide(spans: list['Span'], policy: Policy, rng: random.Random | None = None) -> tuple[bool, str]:
    rng = rng or random.Random()
    if not spans:
        return False, 'empty'
    if policy.keep_errors and any(s.error for s in spans):
        return True, 'error'
    slowest = max(s.duration_ms for s in spans)
    if slowest >= policy.slow_ms:
        return True, 'slow'
    if rng.random() < policy.fallback_rate:
        return True, 'sampled'
    return False, 'dropped'