← 中文资源

简体中文版本

日志采样

日志采样保留事件中有代表性的子集,维持模式与错误可见,同时丢弃推高成本的冗余量。

阅读英文原文

概念定义

日志采样是只保留一部分日志事件的做法——通常按键于消息模板或产生服务等稳定签名——从而在存储量有界的同时保住日志的统计形态。它与日志丢弃不同:采样后的流仍可分析,因为采样概率已知;而被丢弃的流则不复存在。错误与稀有事件通常被豁免或始终保留。

为什么重要

日志是最容易无限增长的信号,因为开发者会自由地加行,而每一行都要存储。这些量很大一部分是重复:同样的重试、同样的心跳。采样在保留“它确实发生过、大致多频繁”这一事实的同时压缩重复,降低存储与索引成本,又不让运维对稀有事件视而不见。

工程实践

把错误与稀有签名钉住始终保留,只对高频重复采样,并始终在每个事件上附带采样率以便重建计数。优先对结构化字段而非自由文本采样,并保留足够的本地缓冲以捕获崩溃前几秒。测量采样究竟去掉了什么,以便证明而非假设没有丢失重要类别。

代码示例

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;
  }
}
#!/usr/bin/env bash
set -euo pipefail

LOG_LEVEL="${LOG_LEVEL:-info}"

declare -A LEVELS=([debug]=0 [info]=1 [warn]=2 [error]=3)

log() {
  local level="${1:?level required}"
  shift
  local threshold="${LEVELS[${LOG_LEVEL}]:-1}"
  local current="${LEVELS[${level}]:-1}"
  if (( current < threshold )); then
    return 0
  fi
  printf '{"timestamp":"%s","level":"%s","message":"%s"}\n' \
    "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "${level}" "$*" >&2
}

log info "job started"
log debug "this line is suppressed at info level"
log error "dependency unavailable"