入门

选择 TypeScript 日志记录器

根据你的调试方式选择 TypeScript 日志库。了解 evlog 的定位、现有配置中可以保留的内容,以及如何进行尝试。

TypeScript 日志库应该让下一个 bug 更容易理解。如果你花在拼凑请求信息上的时间比修复问题还多,evlog 可以将你收集的上下文汇总到一个事件中:谁发起了请求、请求执行了什么,以及最终结果如何。

本指南将帮助你确定 evlog 在项目中的定位。要查看一个可运行的示例,请参阅 Node.js 中的结构化日志

围绕你向日志提出的问题进行选择

脚本可能只需要报告进度。对于单条结构化消息,可以使用 evlog 的简单日志 API

当一次结账流程跨越身份验证、库存和支付代码时,有用的答案通常是整个操作过程。宽事件让每个步骤都能向同一个事件添加上下文。这样,你就可以按客户、支付提供商或订单金额筛选失败的结账流程,而不必先合并彼此独立的消息。

如果你当前的日志记录器已经能提供所需的答案,可以继续保留它。当你希望同时获得上下文累积、请求生命周期处理和结构化错误时,evlog 就会发挥作用。上面的功能对比涵盖了与其他日志记录器的差异,包括你可能希望保留的功能。

让 TypeScript 保持上下文一致

随着越来越多的人添加日志记录,一个地方名为 orderId 的字段可能会在另一个地方变成 orderID。evlog 允许你选择使用共享上下文类型,这样编辑器和编译器就能在你工作时发现这些不一致。

例如,下面这个结账日志记录器接受一组已知的结果,以及一个数值类型的支付金额:

typed-context.ts
import { createLogger, initLogger } from 'evlog'

initLogger({ env: { service: 'checkout' }, pretty: false })

type CheckoutContext = {
  orderId: string
  payment: { chargeId: string, amount: number }
  outcome: 'paid' | 'declined'
}

const log = createLogger<CheckoutContext>()
log.set({ orderId: 'order-123' })
log.set({ payment: { chargeId: 'ch_123', amount: 2999 } })
log.emit({ outcome: 'paid' })

类型检查会在 set()emit() 中捕获以字符串形式传入的金额,或不属于该联合类型的结果。字段可以逐步添加;该类型不会要求在发出事件前提供所有字段,也不会验证传入的数据。类型化字段介绍了类型模式和框架配置。

带上你现有的配置

从一个路由或后台任务开始。在其他地方继续使用现有的日志记录器。在更广泛地采用 evlog 之前,先使用生成的事件调查一个真实问题。

简单日志中的迁移示例将 console.log、Pino、Consola 和 Winston 中常见的调用映射到 evlog。由于 API 存在差异,更新调用时可以参考这些示例。如果你将多条记录合并为一个事件,也要相应更新读取这些记录的查询。

当你的可观测性后端具有受支持的 drain adapter 时,可以继续使用它。日志记录器会在应用程序中收集上下文;适配器会将其发送到你用来搜索和存储事件的服务。

在你的项目中尝试

使用上面的快速开始了解 API,然后选择你的框架集成。对于脚本和后台任务,Standalone TypeScript介绍了初始化和传送。有关打包体积和基准测试条件,请参阅性能