Workers可观测性技能 workers-observability

这个技能是关于Cloudflare Workers的可观测性实现,包括日志记录、指标收集、分布式追踪和警报设置。用于监控、调试和优化Serverless应用,提高生产环境的可靠性和性能。关键词:Cloudflare Workers、可观测性、日志、指标、追踪、警报、Serverless、云原生。

Serverless 0 次安装 0 次浏览 更新于 3/7/2026

name: workers-observability description: Cloudflare Workers 可观测性,包括日志记录、Analytics Engine、Tail Workers、指标和警报。用于监控、调试、追踪,或解决日志解析、指标聚合、警报配置错误。

Cloudflare Workers 可观测性

生产级 Cloudflare Workers 可观测性:日志记录、指标、追踪和警报。

快速开始

// 结构化日志记录与上下文
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const requestId = crypto.randomUUID();
    const logger = createLogger(requestId, env);

    try {
      logger.info('请求已接收', { method: request.method, url: request.url });

      const result = await handleRequest(request, env);

      logger.info('请求已完成', { status: result.status });
      return result;
    } catch (error) {
      logger.error('请求失败', { error: error.message, stack: error.stack });
      throw error;
    }
  }
};

// 简单的日志记录器工厂函数
function createLogger(requestId: string, env: Env) {
  return {
    info: (msg: string, data?: object) => console.log(JSON.stringify({ level: 'info', requestId, msg, ...data, timestamp: Date.now() })),
    error: (msg: string, data?: object) => console.error(JSON.stringify({ level: 'error', requestId, msg, ...data, timestamp: Date.now() })),
    warn: (msg: string, data?: object) => console.warn(JSON.stringify({ level: 'warn', requestId, msg, ...data, timestamp: Date.now() })),
  };
}

关键规则

  1. 始终使用结构化 JSON 日志记录 - 纯文本日志难以解析和聚合
  2. 包含请求上下文 - 在每个日志条目中添加请求 ID、方法、路径
  3. 切勿记录敏感数据 - 从日志中脱敏令牌、密码、个人身份信息
  4. 使用适当的日志级别 - ERROR 用于失败,WARN 用于可恢复问题,INFO 用于操作
  5. 对高容量日志进行采样 - 在生产环境中对请求日志使用 1-10% 采样

可观测性组件

组件 目的 何时使用
console.log 基本日志记录 开发、调试
Tail Workers 实时日志流 生产日志聚合
Analytics Engine 自定义指标/分析 业务指标、性能跟踪
Logpush 日志导出到外部服务 长期存储、合规性
Workers Trace Events 分布式追踪 请求流调试

前 8 个预防错误

错误 症状 预防
日志不显示 仪表板无输出 在 wrangler.jsonc 中启用 “Standard” 日志记录
日志截断 消息在 128KB 处截断 分块大负载,使用采样
Tail Worker 未接收 无事件处理 检查绑定名称是否与 wrangler.jsonc 匹配
Analytics Engine 写入失败 数据未记录 验证 AE 绑定,检查 blobs 格式
日志中包含 PII 安全/合规违规 实现脱敏中间件
缺少请求上下文 无法关联日志 在所有日志条目中添加 requestId
日志量爆炸 高成本、噪音 对高频事件实施采样
警报缺失 事件未检测到 为错误率阈值配置监视器

日志记录配置

wrangler.jsonc:

{
  "name": "my-worker",
  "observability": {
    "enabled": true,
    "head_sampling_rate": 1 // 0-1,1 = 100% 的请求
  },
  "tail_consumers": [
    {
      "service": "log-aggregator", // Tail Worker 名称
      "environment": "production"
    }
  ],
  "analytics_engine_datasets": [
    {
      "binding": "ANALYTICS",
      "dataset": "my_worker_metrics"
    }
  ]
}

结构化日志记录模式

interface LogEntry {
  level: 'debug' | 'info' | 'warn' | 'error';
  message: string;
  requestId: string;
  timestamp: number;
  // 上下文数据
  method?: string;
  path?: string;
  status?: number;
  duration?: number;
  // 错误详情
  error?: {
    name: string;
    message: string;
    stack?: string;
  };
  // 自定义字段
  [key: string]: unknown;
}

class Logger {
  constructor(private requestId: string, private baseContext: object = {}) {}

  private log(level: LogEntry['level'], message: string, data?: object) {
    const entry: LogEntry = {
      level,
      message,
      requestId: this.requestId,
      timestamp: Date.now(),
      ...this.baseContext,
      ...data,
    };

    // 脱敏敏感字段
    const sanitized = this.redact(entry);

    const output = JSON.stringify(sanitized);
    level === 'error' ? console.error(output) : console.log(output);
  }

  private redact(entry: LogEntry): LogEntry {
    const sensitiveKeys = ['password', 'token', 'secret', 'authorization', 'cookie'];
    const redacted = { ...entry };

    for (const key of Object.keys(redacted)) {
      if (sensitiveKeys.some(s => key.toLowerCase().includes(s))) {
        redacted[key] = '[REDACTED]';
      }
    }
    return redacted;
  }

  info(message: string, data?: object) { this.log('info', message, data); }
  warn(message: string, data?: object) { this.log('warn', message, data); }
  error(message: string, data?: object) { this.log('error', message, data); }
  debug(message: string, data?: object) { this.log('debug', message, data); }
}

Analytics Engine 使用

interface Env {
  ANALYTICS: AnalyticsEngineDataset;
}

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const start = Date.now();
    const url = new URL(request.url);

    try {
      const response = await handleRequest(request, env);

      // 写入成功指标
      env.ANALYTICS.writeDataPoint({
        blobs: [request.method, url.pathname, String(response.status)],
        doubles: [Date.now() - start], // 响应时间(毫秒)
        indexes: [url.pathname.split('/')[1] || 'root'], // 索引用于快速查询
      });

      return response;
    } catch (error) {
      // 写入错误指标
      env.ANALYTICS.writeDataPoint({
        blobs: [request.method, url.pathname, 'error', error.message],
        doubles: [Date.now() - start],
        indexes: ['error'],
      });
      throw error;
    }
  }
};

Tail Worker 模式

// tail-worker.ts - 接收来自其他 Workers 的日志
interface TailEvent {
  scriptName: string;
  event: {
    request?: { method: string; url: string };
    response?: { status: number };
  };
  logs: Array<{
    level: string;
    message: unknown[];
    timestamp: number;
  }>;
  exceptions: Array<{
    name: string;
    message: string;
    timestamp: number;
  }>;
  outcome: 'ok' | 'exception' | 'exceededCpu' | 'exceededMemory' | 'canceled';
  eventTimestamp: number;
}

export default {
  async tail(events: TailEvent[], env: Env): Promise<void> {
    for (const event of events) {
      // 过滤并转发日志
      const errorLogs = event.logs.filter(l => l.level === 'error');
      const exceptions = event.exceptions;

      if (errorLogs.length > 0 || exceptions.length > 0) {
        // 发送到外部日志服务
        await fetch(env.LOGGING_ENDPOINT, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            scriptName: event.scriptName,
            timestamp: event.eventTimestamp,
            errors: errorLogs,
            exceptions,
            outcome: event.outcome,
          }),
        });
      }
    }
  }
};

何时加载参考

根据任务加载特定参考:

  • 设置日志记录? → 加载 references/logging.md 以获取结构化日志记录模式、日志级别、脱敏
  • 构建自定义指标? → 加载 references/analytics-engine.md 以获取 Analytics Engine SQL 查询、数据建模
  • 实现日志聚合? → 加载 references/tail-workers.md 以获取 Tail Worker 模式、外部服务集成
  • 创建仪表板/跟踪? → 加载 references/custom-metrics.md 以获取业务指标、性能跟踪
  • 设置警报? → 加载 references/alerting.md 以获取错误率监控、PagerDuty/Slack 集成

模板

模板 目的 何时使用
templates/logging-setup.ts 生产日志记录类 设置新 Worker 并配置日志记录
templates/analytics-worker.ts Analytics Engine 集成 添加自定义指标
templates/tail-worker.ts 完整 Tail Worker 构建日志聚合管道

脚本

脚本 目的 命令
scripts/setup-logging.sh 配置日志记录设置 ./setup-logging.sh
scripts/analyze-logs.sh 查询和分析日志 ./analyze-logs.sh --errors --last 1h

资源