日志记录

客户端日志记录

捕获浏览器事件并使用结构化日志记录。与服务器端拥有相同的 API,自动添加控制台样式、用户身份上下文,并可选择发送到服务器。

服务器日志告诉你后端发生了什么。客户端日志补全了整个画面:用户交互、页面浏览、前端错误,以及那些不会到达服务器的性能信号(除非你主动捕获它们)。

快速起步

evlog 提供了一个可在任何浏览器环境中使用的客户端日志 API:

import { initLog, log } from 'evlog/client'

export default defineNuxtPlugin(() => {
  initLog({ service: 'web' })

  log.info({ action: 'app_init', path: window.location.pathname })
})

log 对象可以在你的客户端代码中任何地方使用:组件、composables、事件处理器。

最低级别(minLevel

使用 initLog({ minLevel: 'warn' }) 来保持浏览器控制台安静(仅显示警告和错误)。严重性顺序为:debug < info < warn < error。默认值为 'debug'(输出所有级别)。

如果需要无需重新加载即可切换调试模式,可以在用户选择开启或关闭详细日志时,从 evlog/client 调用 setMinLevel('debug')setMinLevel('warn')

minLevel 同时适用于控制台输出和向服务器发送日志 的有效载荷。

两种调用签名

log API 根据上下文接受两种形式。

对象形式(结构化上下文)

传递一个对象以捕获结构化数据,就像服务器端的 log.set() 一样:

pages/products.vue
log.info({ action: 'page_view', path: '/products', referrer: document.referrer })
浏览器控制台
[web] info  { action: 'page_view', path: '/products', referrer: 'https://google.com' }

标签 + 消息形式(快速日志)

传递标签和消息以输出快速、可读的日志:

composables/useAuth.ts
log.info('auth', 'User logged in')
浏览器控制台
[auth] User logged in

可用级别

两种形式均支持四个级别:log.info()log.warn()log.error()log.debug()

在浏览器中,log.debug() 会通过 console.log(而不是 console.debug)输出,以便在默认的 DevTools Info 过滤器下仍可见;结构化事件仍然包含 level: 'debug'

身份上下文

使用 setIdentity() 跟踪生成日志的用户:

composables/useAuth.ts
import { setIdentity, clearIdentity, log } from 'evlog/client'

// 登录后
setIdentity({ userId: 'usr_123', plan: 'pro' })

log.info({ action: 'dashboard_view' })
// → { userId: 'usr_123', plan: 'pro', action: 'dashboard_view', ... }

// 注销后
clearIdentity()

身份字段会在清除之前自动合并到每个日志事件中。这使得你可以在可观测性工具中将浏览器事件关联到特定用户。

配置

initLog() 接受以下选项:

选项默认值描述
enabledtrue启用或禁用所有客户端日志记录
consoletrue输出日志到浏览器控制台
prettytrue使用带颜色的格式化控制台输出
minLevel'debug'最低严重级别:debug < info < warn < error
service'client'每个日志事件中包含的服务名称
transport-将日志发送到服务器端点(参见下文)
app/plugins/logger.client.ts
initLog({
  service: 'web',
  transport: {
    enabled: true,
    endpoint: '/api/_evlog/ingest', // 默认端点
  },
})
enabledconsolepretty 默认均为 true。仅当你希望修改默认值时才需要设置它们。

向服务器发送日志

默认情况下,客户端日志只会显示在浏览器控制台中。若要持久化存储,有两种选择:

内置传输

最简单的方法是在 initLog() 中启用内置传输。每个日志都会通过 fetchkeepalive: true 单独发送。适合低流量应用。

import { initLog } from 'evlog/client'

export default defineNuxtPlugin(() => {
  initLog({
    service: 'web',
    transport: {
      enabled: true,
      endpoint: '/api/_evlog/ingest',
    },
  })
})
在 Nuxt 中配合 evlog 模块使用时,服务器接收端点会自动注册。对于其他框架,你需要手动创建该端点。请参考 HTTP 接收器 文档获取 Express 和 Hono 的示例。

HTTP 接收器管道

对于更高流量或需要批量、重试以及在页面关闭时刷新的场景,请使用 HTTP 接收器(evlog/http)。这适用于任何前端,且不依赖具体框架。

import { initLogger, log } from 'evlog'
import { createHttpLogDrain } from 'evlog/http'

export default defineNuxtPlugin(() => {
  const drain = createHttpLogDrain({
    drain: { endpoint: '/api/_evlog/ingest' },
    pipeline: {
      batch: { size: 25, intervalMs: 2000 },
      retry: { maxAttempts: 2 },
    },
  })

  initLogger({ drain })
  log.info({ action: 'app_init' })
})

HTTP 接收器会自动:

  • 批量处理事件(按大小和时间间隔)
  • 重试失败的发送(带指数退避)
  • 刷新缓冲的事件,在页面隐藏时(标签切换、导航、关闭)通过 sendBeacon 发送
请参考 HTTP 接收器 适配器文档,获取完整的配置参考、认证说明和服务器端点示例。

后续步骤