框架

AWS Lambda

在 AWS Lambda 函数中进行广泛的事件记录和结构化日志记录,包括 SQS 消费者和事件驱动的处理程序。

AWS Lambda 没有像 Nuxt 或 Express 那样的 HTTP 中间件生命周期,因此 evlog 的行为类似于 独立 TypeScript:调用一次 initLogger(),然后为每次调用(或每条 SQS 消息)使用 createLogger() 创建一个日志记录器,最后在工作完成时调用 log.emit()

在我的 AWS Lambda 函数中设置 evlog

为何不使用一个全局的 createLogger

Lambda 执行环境会被复用:同一个进程可以按顺序处理多次调用。模块级变量会持续存在,因此一个共享的日志记录器实例可能会将前一次调用的字段泄漏到下一次调用中。

请这样做: 仅在顶层(仅配置)调用一次 initLogger(),并在处理程序中(或在遍历 SQS 记录时)对每次工作单元调用 createLogger()

依赖注入(将 log 传递给函数)是可选的——它有助于测试和清晰度——但重要的是每次调用一个日志记录器,而不是是否使用 DI。

快速开始

1. 安装

pnpm add evlog

2. 初始化一次,每次调用记录日志

src/handler.ts
import type { SQSEvent } from 'aws-lambda'
import { initLogger, createLogger } from 'evlog'

initLogger({
  env: { service: 'sqs-consumer', environment: process.env.NODE_ENV },
})

export async function handler(event: SQSEvent) {
  for (const record of event.Records) {
    const log = createLogger({
      messageId: record.messageId,
      approximateReceiveCount: record.attributes?.ApproximateReceiveCount,
    })

    try {
      log.set({ queue: { name: record.eventSourceARN } })
      // … 解析 record.body 并处理消息
      log.set({ status: 'ok' })
    } catch (error) {
      log.error(error instanceof Error ? error : new Error(String(error)))
      log.set({ status: 'error' })
      throw error
    } finally {
      log.emit()
    }
  }
}

如果将整个批次作为一个逻辑单元处理,请在每次处理程序调用中使用一个 createLogger(),并附带批次元数据,而不是为每条记录创建一个日志记录器。

标准输出与 silent 模式

许多团队通过 stdout 从 CloudWatch 摄取 Lambda 日志。如果你使用 drain 适配器(OTLP、Datadog、Axiom 等),并且希望在没有重复控制台噪音的情况下输出 JSON 或平台特定格式,请在生产环境中设置 silent: true——请参阅 配置

src/handler.ts
import { createAxiomDrain } from 'evlog/axiom'
import { initLogger } from 'evlog'

initLogger({
  env: { service: 'sqs-consumer' },
  silent: process.env.NODE_ENV === 'production',
  drain: createAxiomDrain(),
})
如果启用了 silent 但没有配置 drain,事件可能无法在任何地方可见。请参阅配置文档获取详细信息。

错误处理

在需要结构化字段(whyfixlink)的地方使用 createError。将失败映射到 Lambda 的返回值或重新抛出,以确保 SQS 重试/DLQ 行为保持正确——evlog 不会替代 AWS 错误语义。

src/handler.ts
import { createError } from 'evlog'

throw createError({
  message: '无效的有效载荷',
  status: 400,
  why: '缺少必需字段',
  fix: '在消息体中包含 orderId',
})

相关内容

  • 独立 TypeScript:相同的 initLogger + createLogger + emit() 模型
  • 配置silentenv.regionAWS_REGION)、drains
  • 宽事件:为每个工作单元设计一个全面的事件