功能说明
该示例针对高频重复日志做采样。每条消息先归一化为一个稳定签名(例如去掉变量后的模板),首次出现的签名必然保留,随后的重复才按比例采样。错误等需要始终保留的类别由 alwaysKeep 决定。这样新的日志模式不会被漏掉,而同一行的风暴被显著削减。
关键代码
seen 集合记录已出现过的签名,用于区分首次与重复。alwaysKeep 接收签名并返回布尔,调用方可据此把错误级别或特定来源钉住。被写出的事件附带 sampledRate,让下游在统计时按概率还原计数。采用注入式 write 而非直接打印,方便测试与替换输出目标。
使用注意
必须记录采样率,否则从日志推断出的事件计数会有偏差,把采样率随事件一同输出正是为此。签名归一化要足够稳定:若把 id 保留在签名里,每个请求都会被视为新签名而失去采样意义。内存中的 seen 集合会随不同签名增长,应设置上限或定期清理。采样只应压缩重复,绝不能以采样为名丢弃错误类别。
代码示例
export class LogSampler {
constructor({ rate = 0.01, alwaysKeep = () => false } = {}) {
this.rate = rate;
this.alwaysKeep = alwaysKeep;
this.seen = new Set();
}
shouldEmit(signature) {
if (this.alwaysKeep(signature)) return true;
if (!this.seen.has(signature)) {
this.seen.add(signature);
return true;
}
return Math.random() < this.rate;
}
emit(signature, write) {
if (!this.shouldEmit(signature)) return false;
write({ signature, sampledRate: this.rate });
return true;
}
}