扩展

尾部采样

在了解事件状态、持续时间和错误后再决定是否保留事件。保留所有错误,丢弃健康流量中的噪声
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 配置的其他部分(排出器、丰富器)一起使用,并且可以跨框架复用。

组合多个保留谓词

使用 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 规则
  • 插件:何时应将保留逻辑放入多钩子插件中
  • 最佳实践:保留所有错误,再次检查规则