mcpField
W
workers-observability

workers-observability

github.com/secondsky云与 DevOps24081 次安装5 周前更新
代码仓库

关于 workers-observability

用于为 Cloudflare Workers 实施可观测性的技能,涵盖日志、指标、追踪和告警,并提供配置指导、模式、模板及脚本,支持生产环境监控。

主要功能

  1. 01结构化 JSON 日志模式
  2. 02Tail Workers 日志流
  3. 03Analytics Engine 指标
  4. 04Logpush 与追踪事件指导
  5. 05告警和日志分析资源

适用场景

  1. 01为日志添加请求上下文
  2. 02聚合 Worker 日志
  3. 03记录自定义性能指标
  4. 04监控错误率和故障

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/secondsky/claude-skills --skill workers-observability

安装后在 Claude Code 中输入/workers-observability确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
alerting.md
analytics-engine.md
custom-metrics.md
logging.md
tail-workers.md
scripts/
analyze-logs.sh
setup-logging.sh
templates/
analytics-worker.ts
logging-setup.ts
tail-worker.ts

详细介绍

Cloudflare Workers 可观测性

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

快速入门

// Structured logging with context
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const requestId = crypto.randomUUID();
    const logger = createLogger(requestId, env);

    try {
      logger.info('Request received', { method: request.method, url: request.url });

      const result = await handleRequest(request, env);

      logger.info('Request completed', { status: result.status });
      return result;
    } catch (error) {
      logger.error('Request failed', { error: error.message, stack: error.stack });
      throw error;
    }
  }
};

// Simple logger factory
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 格式
日志中包含个人身份信息违反安全/合规要求实施脱敏中间件
缺少请求上下文无法关联日志在所有日志条目中添加 requestId
日志量激增成本高、噪声大对高频事件实施采样
告警缺失未能检测到事件配置错误率阈值监控器

日志配置

wrangler.jsonc:

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

结构化日志模式

interface LogEntry {
  level: 'debug' | 'info' | 'warn' | 'error';
  message: string;
  requestId: string;
  timestamp: number;
  // Contextual data
  method?: string;
  path?: string;
  status?: number;
  duration?: number;
  // Error details
  error?: {
    name: string;
    message: string;
    stack?: string;
  };
  // Custom fields
  [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,
    };

    // Redact sensitive fields
    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);

      // Write success metric
      env.ANALYTICS.writeDataPoint({
        blobs: [request.method, url.pathname, String(response.status)],
        doubles: [Date.now() - start], // Response time in ms
        indexes: [url.pathname.split('/')[1] || 'root'], // Index for fast queries
      });

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

Tail Worker 模式

// tail-worker.ts - Receives logs from other 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) {
      // Filter and forward logs
      const errorLogs = event.logs.filter(l => l.level === 'error');
      const exceptions = event.exceptions;

      if (errorLogs.length > 0 || exceptions.length > 0) {
        // Send to external logging service
        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.tsAnalytics Engine 集成添加自定义指标
templates/tail-worker.ts完整的 Tail Worker构建日志聚合管道

脚本

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

资源

评论

支持 Markdown