核心概念

采样

通过两级采样控制日志量。头部采样按级别丢弃噪声,尾部采样根据结果恢复关键事件。永远不会错过错误、慢请求或关键路径。

在规模较大时,记录所有内容会迅速增加成本。采样可以让你在不丢失对重要内容的可观测性的同时控制成本。evlog 使用两级方法:头部采样在源头丢弃噪声,尾部采样事后恢复关键事件。

头部采样

头部采样按每个级别随机保留一定百分比的日志。它在请求完成之前运行,就像在发射时抛硬币一样。

export default defineNuxtConfig({
  modules: ['evlog/nuxt'],
  evlog: {
    sampling: {
      rates: {
        info: 10,    // 保留 10% 的 info 日志
        warn: 50,    // 保留 50% 的警告
        debug: 0,    // 丢弃所有 debug 日志
        error: 100,  // 始终保留错误(默认)
      },
    },
  },
})

每个级别都是 0 到 100 的百分比。你未配置的级别默认保留 100%(保留所有内容)。即使配置了其他级别,错误默认也保留 100%,因此必须显式设置 error: 0 才能丢弃错误。

头部采样是随机的。10% 的比率意味着大约每 10 条 info 日志保留 1 条,而不是精确的每 10 条保留 1 条。

尾部采样

头部采样是盲目的:它不知道请求是否变慢、失败或命中了关键路径。尾部采样通过在请求完成后评估条件来修复这一点,并强制保留匹配特定条件的日志。

nuxt.config.ts
// 采样配置,在所有框架中工作方式相同
evlog: {
  sampling: {
    rates: { info: 10 },
    keep: [
      { status: 400 },              // HTTP 状态 >= 400
      { duration: 1000 },           // 请求耗时 >= 1 秒
      { path: '/api/payments/**' }, // 关键路径(通配符)
    ],
  },
}

条件对 statusduration 使用 >= 比较,对 path 使用通配符匹配。如果任意条件匹配,无论头部采样如何都会保留日志(OR 逻辑)。

可用条件

条件类型描述
statusnumber如果 HTTP 状态 >= 值则保留(例如 400 会捕获所有 4xx 和 5xx)
durationnumber如果请求耗时 >= 指定毫秒数则保留
pathstring如果请求路径匹配通配符模式(例如 '/api/critical/**')则保留

它们如何协同工作

这两个级别相互补充:

  1. 请求完成 - evlog 已知状态、耗时和路径
  2. 尾部采样评估 - 如果任何 keep 条件匹配,则强制保留日志
  3. 头部采样应用 - 仅当尾部采样未强制保留时,才会执行随机百分比检查
  4. 日志发出或丢弃 - 保留的日志按正常流程进行增强和传输

这意味着对 /api/payments/charge 的请求如果返回 500 且耗时 2 秒,无论 info 设置为 1% 都会被记录,尾部条件会将其保留。

sampling: {
  rates: { info: 10 },
  keep: [
    { status: 400 },
    { duration: 1000 },
  ],
}

自定义尾部采样

对于超出状态、耗时和路径的条件,在 Nuxt/Nitro 中使用 evlog:emit:keep 钩子,在其他框架中使用 keep 回调。

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

ctx 对象包含:

字段类型描述
statusnumber | undefinedHTTP 响应状态
durationnumber | undefined请求耗时(毫秒)
pathstring | undefined请求路径
methodstring | undefinedHTTP 方法
contextRecord<string, unknown>通过 log.set() 设置的所有字段
shouldKeepboolean设置为 true 以强制保留

生产环境示例

平衡成本与可见性的典型生产配置:

export default defineNuxtConfig({
  modules: ['evlog/nuxt'],
  evlog: {
    env: { service: 'my-app' },
  },
  $production: {
    evlog: {
      sampling: {
        rates: {
          info: 10,
          warn: 50,
          debug: 0,
          error: 100,
        },
        keep: [
          { status: 400 },
          { duration: 1000 },
          { path: '/api/payments/**' },
          { path: '/api/auth/**' },
        ],
      },
    },
  },
})
在 Nuxt 中,使用 $production 覆盖配置可以在开发环境中保留完整日志,在生产环境中启用采样。在其他框架中,请使用自己的环境检查或配置系统。

下一步