evlog 提供了三种日志 API,每种都针对不同的使用场景设计。你可以在同一个项目中使用全部三种。
三种模式
快速对比
简单日志(log)
每次调用一个事件。不累积上下文,也不管理生命周期。
src/index.ts
import { log } from 'evlog'
log.info('auth', 'User logged in')
log.error({ action: 'payment', error: 'card_declined', userId: 42 })
大型事件(createLogger / createRequestLogger)
每个工作单元一个事件。逐步累积上下文,完成时发出。
import { createLogger } from 'evlog'
const log = createLogger({ jobId: 'sync-001', queue: 'emails' })
log.set({ batch: { size: 50, processed: 50 } })
log.emit()
import { createRequestLogger } from 'evlog'
const log = createRequestLogger({ method: 'POST', path: '/api/checkout' })
log.set({ user: { id: 1, plan: 'pro' } })
log.emit()
createRequestLogger 是 createLogger 的轻量封装,预填充了 method、path 和 requestId。
请求日志(框架中间件)
框架集成会在每个请求上自动创建一个大型事件日志记录器。useLogger(event) 用于获取已附加到请求上下文的日志记录器:
server/api/checkout.post.ts
import { useLogger } from 'evlog'
export default defineEventHandler(async (event) => {
const log = useLogger(event)
log.set({ user: { id: 1, plan: 'pro' } })
return { success: true }
// 在响应结束时自动发出
})
useLogger(event) 并不会创建日志记录器,而是获取框架中间件已附加到事件上的日志记录器。每个框架有各自的获取方式(useLogger、req.log、c.get('log') 等)。在 Nuxt 中,useLogger 是自动导入的。何时使用什么
log | createLogger / createRequestLogger | 框架中间件 | |
|---|---|---|---|
| 使用场景 | 快速的一次性事件 | 脚本、任务、工作者、队列、无框架的 HTTP 请求 | 使用框架集成的 API 路由 |
| 上下文 | 单次调用 | 使用 set() 累积 | 使用 set() 累积 |
| 发射 | 立即发射 | 手动调用 emit() | 响应结束时自动发射 |
| 生命周期 | 无 | 手动管理 | 框架管理 |
| 输出 | 控制台 + 导出 | 控制台 + 导出 | 控制台 + 导出 + 增强 |
从
log 开始进行快速结构化日志记录。当需要跨操作累积上下文时,切换到 createLogger(在 HTTP 场景中使用 createRequestLogger)。使用框架集成时,中间件会自动处理一切,只需调用 useLogger(event) 获取日志记录器即可。共享特性
所有三种模式都基于同一底层能力:
- 开发环境美化输出,生产环境输出 JSON(默认,无需配置)
- 导出管道,可将事件发送到 Axiom、Sentry、PostHog 等
- 结构化错误,提供
why、fix和link,并可选包含仅后端可见的internal字段 - 采样,用于控制生产环境中的日志数量
- 零依赖,约 5 kB 压缩后大小