---

title: API安全日志与可观测性(Trace-ID与脱敏)最佳实践

keywords:

  • Trace-ID
  • Sampling
  • Redaction
  • Audit
  • PII
  • Log Schema
  • Rate Limit
  • Correlation
  • JSON
  • Headers

description: 统一API安全日志与可观测性方案,包含Trace-ID注入与传播、采样与速率限制、PII脱敏与统一日志Schema,附中间件与审计示例。

categories:

  • 文章资讯
  • 技术教程

---

一、Trace-ID注入与传播

type Req = { headers: Record<string, string | undefined> }
type Res = { setHeader: (k: string, v: string) => void }

function randId(): string { return Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2) }

function attachTrace(req: Req, res: Res): string {
  const id = req.headers['x-trace-id'] || randId()
  res.setHeader('X-Trace-Id', id)
  return id
}

二、采样与速率限制

class RateGate {
  windowMs: number
  max: number
  hits = new Map<string, number[]>()
  constructor(windowMs: number, max: number) { this.windowMs = windowMs; this.max = max }
  allow(key: string): boolean {
    const now = Date.now()
    const arr = (this.hits.get(key) || []).filter(t => now - t < this.windowMs)
    if (arr.length >= this.max) return false
    arr.push(now); this.hits.set(key, arr); return true
  }
}

function sample(p: number): boolean { return Math.random() < p }

三、脱敏与Schema

type LogItem = { traceId: string; level: 'info' | 'warn' | 'error'; route: string; method: string; status?: number; userId?: string; payload?: Record<string, any>; timestamp: string }

function redactPII(obj: Record<string, any>): Record<string, any> {
  const out: Record<string, any> = {}
  for (const [k, v] of Object.entries(obj)) {
    const key = k.toLowerCase()
    if (key.includes('password') || key.includes('secret') || key.includes('token')) out[k] = '***'
    else if (key.includes('email')) out[k] = String(v).replace(/^[^@]+/, '***')
    else out[k] = v
  }
  return out
}

四、日志输出与审计

function nowIso(): string { return new Date().toISOString() }

function makeLog(traceId: string, route: string, method: string, level: 'info' | 'warn' | 'error', payload?: Record<string, any>, status?: number, userId?: string): LogItem {
  const p = payload ? redactPII(payload) : undefined
  return { traceId, level, route, method, status, userId, payload: p, timestamp: nowIso() }
}

function serializeLog(item: LogItem): string { return JSON.stringify(item) }

五、整合中间件

type Ctx = { req: Req; res: Res; route: string; method: string; userId?: string }

function loggingMiddleware(ctx: Ctx, gate: RateGate, p: number, emit: (line: string) => void) {
  const traceId = attachTrace(ctx.req, ctx.res)
  const ok = gate.allow(traceId)
  if (!ok) return
  if (sample(p)) emit(serializeLog(makeLog(traceId, ctx.route, ctx.method, 'info', undefined, undefined, ctx.userId)))
}

六、验收清单

  • X-Trace-Id注入与传播一致;采样概率与速率限制生效。
  • PII字段脱敏覆盖密码/Secret/Token与邮箱前缀;日志Schema统一且JSON输出。
  • 审计记录包含traceId/route/method/status/userId/timestamp并可关联上下游。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部