Skip to content

可观测性

日志、请求追踪与告警机制的协作方式。

1. 全链路概览

HTTP Request
  → RequestPreprocessingMiddleware  [分配 ULID req.id,注入 req.version]
  → RequestScopeMiddleware          [初始化 AsyncLocalStorage 上下文]
  → 业务链路(任意层可调用 AlsService.get())
  → DatabaseService.$on('query')    [查询耗时 → 分级日志,含脱敏参数]
  → PerformanceInterceptor          [响应后计算总耗时 → 分级日志]
  → 响应头 flx-request-id: req.id   [透传给客户端,便于端侧关联]

2. 日志基础设施

组件说明
核心库Pino 10(原生 JSON,多线程友好,高性能)
NestJS 集成nestjs-pino + pino-http
开发环境pino-pretty(彩色格式化 console 输出)
生产环境写入 logs/app.log(JSON Lines 格式)

3. 请求链路追踪

每个 HTTP 请求使用 ULID 作为追踪 ID,通过 AsyncLocalStorage 贯穿全链路,无需手动传参:

mermaid
sequenceDiagram
    participant C as Client
    participant RP as RequestPreprocessing
    participant RS as RequestScope
    participant Svc as 任意 Service
    participant DB as DatabaseService
    participant PI as PerformanceInterceptor

    C->>RP: 请求(可含 flx-request-id 头)
    RP->>RS: req.id = 客户端传入值,或生成新 ULID
    RS->>RS: ALS.run({ requestId, time, version })
    RS->>Svc: 调用链(无需手动传 requestId)
    Svc->>Svc: AlsService.get().requestId
    Svc->>DB: 数据库查询
    DB->>DB: 日志含 requestId(从 ALS 读取)
    PI->>PI: 响应后:get().requestId + 计算耗时
    PI->>C: 响应头 flx-request-id: req.id

4. AlsService

AsyncLocalStorage 的类型化封装,提供请求级别的隔离上下文。

方法说明
run(context, callback)在指定上下文中执行回调(由 RequestScopeMiddleware 调用)
get()返回当前上下文的深拷贝(任意层均可调用)

RequestContext 结构:

typescript
{
  requestId: string;       // ULID,来自 req.id
  time: number;            // 请求开始时间戳(ms)
  version?: string;        // 应用版本(来自 req.version)
}

调用 get() 时若上下文不存在(非 HTTP 上下文,如定时任务),返回 undefined,调用方需自行处理。

5. 告警阈值

所有阈值在 src/constants/observability.constant.ts 中定义,可通过环境变量覆盖:

类型warn 阈值error 阈值环境变量
HTTP 请求耗时≥ 1000ms≥ 3000msSLOW_REQUEST_WARN_MS, SLOW_REQUEST_ERROR_MS
数据库查询耗时≥ 100ms≥ 500msSLOW_QUERY_WARN_MS, SLOW_QUERY_ERROR_MS

6. 日志分级规则

PerformanceInterceptor(HTTP 请求耗时):

条件日志级别
耗时 ≥ SLOW_REQUEST_ERROR_MS(3000ms)error
SLOW_REQUEST_WARN_MS ≤ 耗时 < SLOW_REQUEST_ERROR_MS(1000–3000ms)warn
耗时 < 1000ms 且 HTTP ≥ 400info
耗时 < 1000ms 且 HTTP < 400debug

DatabaseService(查询耗时,详见 database.md):

条件日志级别
耗时 ≥ SLOW_QUERY_ERROR_MS(500ms)error
SLOW_QUERY_WARN_MS ≤ 耗时 < SLOW_QUERY_ERROR_MS(100–500ms)warn
耗时 < 100msdebug

7. 日志字段参考

pino-http 自动注入或手动记录时的通用字段:

字段来源说明
req.idpino-http请求 ID(ULID)
responseTimepino-http请求总耗时(ms)
levelPinotrace / debug / info / warn / error / fatal
contextNestJS logger日志来源模块名(如 AuthService
requestIdRequestContext链路追踪 ID(同 req.id
versionRequestContext应用版本号