扩展

尾部采样

在事后根据完整的结果信息(状态、持续时间、错误)决定是否保留一个事件。它与头部采样相反——保留所有错误和慢请求,同时丢弃健康流量中的噪声。
sampling decision· tail → head
tail rules: status ≥ 400 duration ≥ 1000 path: /api/payments/**
#1POST/api/users·200·45ms
dropped
#2POST/api/users·500·45ms
kept
#3GET/api/products·200·2300ms
kept
#4POST/api/payments/charge·200·120ms
kept
#5POST/api/checkout·200·120ms
kept
#6GET/api/health·200·12ms
dropped
tail-kept0 / 0
head-kept0 / 0
dropped0

尾部采样是在请求执行之后做出的决定,并且对其结果(状态、持续时间、错误、自定义标志)有完整了解。这就是你保留所有错误和慢请求,同时丢弃大部分健康流量的方式——与头部采样相反,头部采样是在事先还不知道会发生什么时就做出决定。

完整的理论和配置参考——内置 keep 规则、通过 evlog:emit:keep 的自定义谓词、头部 + 尾部采样的组合——请参见 采样。本页介绍的是扩展接口:如何将你自己的保留逻辑接入管道。

在 evlog 上配置尾部采样

当内置规则还不够用时

内置的声明式 keep 规则覆盖了典型场景(状态码阈值、持续时间阈值、路径匹配、级别匹配)。当你需要以下能力时,请切换到自定义钩子:

  • 对多个字段进行条件逻辑判断(例如:“如果 status >= 500user.plan === 'enterprise',则保留”)
  • 基于派生值保留(例如:“如果 event.audit?.context.actor.role === 'admin',则保留”)
  • 有状态的决策(较少见;需要谨慎,因为采样运行在热路径上)

自定义保留钩子

无论框架如何,钩子签名都是相同的。具体接线方式取决于你的运行时。

nitroApp.hooks.hook('evlog:emit:keep', (ctx) => {
  if (ctx.context.user?.plan === 'enterprise' && ctx.status >= 500) {
    ctx.shouldKeep = true
  }
})

对于非平凡逻辑,优先使用插件形式——它会与 evlog 的其他配置(drains、enrichers)一起携带,并且可在不同框架之间复用。

组合多个保留谓词

使用 evlog/toolkit 中的 composeKeep 将多个谓词组合成一个钩子。每个谓词独立运行,如果其中任意一个将最终的 shouldKeep 设为 true,则结果为 true

import { composeKeep } from 'evlog/toolkit'

const keep = composeKeep([
  ({ duration, shouldKeep }) => duration && duration > 2000 ? true : shouldKeep,
  ({ event }) => event.level === 'error',
  ({ context, status }) => context.user?.plan === 'enterprise' && status >= 500,
])

单个谓词中的错误是隔离的(会以 [evlog/keep] 前缀记录),因此有缺陷的谓词不会在不知不觉中丢弃合法事件。

你将收到什么

保留钩子会接收一个 TailSamplingContext

interface TailSamplingContext {
  /** 事件级别(debug | info | warn | error) */
  level: string
  /** HTTP 响应状态(如果已知) */
  status?: number
  /** 请求持续时间(毫秒),如果已测量 */
  duration?: number
  /** 完整的累计上下文(所有 log.set 的内容) */
  context: Record<string, unknown>
  /** 完全丰富后的、准备排出的事件 */
  event: WideEvent
  /** 可变:设为 true 以强制保留此事件 */
  shouldKeep: boolean
}

shouldKeep = true 会强制让事件通过。将 shouldKeep = false 则无效(其他谓词仍可能保留它;默认由头部采样器决定)。

下一步

  • 采样 — 头部采样、尾部采样、内置的声明式 keep 规则
  • 插件 — 当保留逻辑属于多钩子插件时
  • 最佳实践 — 保留所有错误,仔细检查规则