关于 workers-observability
用于为 Cloudflare Workers 实施可观测性的技能,涵盖日志、指标、追踪和告警,并提供配置指导、模式、模板及脚本,支持生产环境监控。
主要功能
- 01结构化 JSON 日志模式
- 02Tail Workers 日志流
- 03Analytics Engine 指标
- 04Logpush 与追踪事件指导
- 05告警和日志分析资源
适用场景
- 01为日志添加请求上下文
- 02聚合 Worker 日志
- 03记录自定义性能指标
- 04监控错误率和故障
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill workers-observability安装后在 Claude Code 中输入/workers-observability确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/alerting.mdanalytics-engine.mdcustom-metrics.mdlogging.mdtail-workers.mdscripts/analyze-logs.shsetup-logging.shtemplates/analytics-worker.tslogging-setup.tstail-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() })),
};
}
关键规则
- 始终使用结构化 JSON 日志 —— 纯文本日志难以解析和聚合
- 包含请求上下文 —— 在每条日志中包含请求 ID、方法和路径
- 绝不记录敏感数据 —— 从日志中删除令牌、密码和个人身份信息
- 使用适当的日志级别 —— 故障使用 ERROR,可恢复的问题使用 WARN,操作使用 INFO
- 对高容量日志进行采样 —— 在生产环境中,对请求日志使用 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.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 |
资源
评论
支持 Markdown