OpenTelemetry を Cloudflare Workers で動かす|OTLP/HTTP
Node.js標準SDKは使用不可。公式 observability 設定か @microlabs/otel-cf-workers を使用します。
なぜ Node.js OpenTelemetry SDK が Workers で動かないか
Cloudflare Workers は Node.js ではなく V8 分離環境(Isolate) で動作します。@opentelemetry/sdk-node は Node.js 固有の API(process・os・node:http 等)に依存しており、Workers ランタイムではこれらが利用できません。
Error: The 'cls-hooked' package requires node:async_hooks which is not available in Workers
このエラーが出た場合、Node.js SDK をそのまま Workers で使おうとしています。
設定手順
手順1:公式 observability 設定(推奨・ゼロコード)
2025年以降、Cloudflare はネイティブの OTLP エクスポート機能を提供しています。コードを書かずにトレースを有効化できます。
// wrangler.jsonc
{
"name": "my-worker",
"compatibility_date": "2025-01-01",
"observability": {
"enabled": true,
"head_sampling_rate": 1
}
}
Cloudflare ダッシュボードで OTLP 送信先を設定します。
- Workers & Pages → 対象 Worker → Observability タブ
- Destinations → Add destination
- Type: Traces / Endpoint:
https://your-collector.example.com/v1/traces - Custom Headers に認証ヘッダーを追加(例:
Authorization: Bearer <token>)
重要: Cloudflare は OTLP/gRPC 非対応です。必ず https://... の OTLP/HTTP エンドポイントを使ってください。
手順2:カスタムスパンが必要な場合(@microlabs/otel-cf-workers)
ビジネスロジックに独自スパンを追加したい場合は @microlabs/otel-cf-workers を使います。
pnpm add @microlabs/otel-cf-workers
// src/index.ts
import { instrument, ResolveConfigFn } from '@microlabs/otel-cf-workers';
import { trace } from '@opentelemetry/api';
const handler = {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
// カスタムスパンを追加
const tracer = trace.getTracer('my-worker');
return tracer.startActiveSpan('handle-request', async (span) => {
try {
const result = await processRequest(request, env);
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (error) {
span.recordException(error as Error);
span.setStatus({ code: SpanStatusCode.ERROR });
throw error;
} finally {
span.end();
}
});
},
};
const config: ResolveConfigFn = (env: Env) => ({
exporter: {
url: env.OTLP_ENDPOINT, // 例: https://api.honeycomb.io/v1/traces
headers: {
'x-honeycomb-team': env.HONEYCOMB_API_KEY,
},
},
service: {
name: 'my-worker',
version: '1.0.0',
},
});
export default instrument(handler, config);
ctx.waitUntil の必須性
Workers はレスポンスを return した瞬間に実行コンテキストを終了させます。トレースのエクスポートは非同期処理のため、ctx.waitUntil() に渡さないとデータが欠損します。
// ❌ ctx.waitUntil なし:エクスポートがキャンセルされる
async fetch(request, env, ctx) {
const response = await handleRequest(request);
exportTraces(); // レスポンス後に切断されて送信されない
return response;
}
// ✅ ctx.waitUntil でエクスポートを保証する
async fetch(request, env, ctx) {
const response = await handleRequest(request);
ctx.waitUntil(exportTraces()); // Workers がエクスポート完了まで待つ
return response;
}
@microlabs/otel-cf-workers の instrument ラッパーはこの ctx.waitUntil の処理を自動で行います。
トラブルシューティング
トレースが届かない場合の確認チェックリスト
| 確認項目 | コマンド・場所 |
|---|---|
エンドポイント URL が /v1/traces で終わっているか | wrangler.jsonc または Cloudflare ダッシュボード |
| 認証ヘッダーが正しく設定されているか | Destination の Custom Headers |
nodejs_compat が必要なライブラリを使っているか | wrangler.jsonc の compatibility_flags |
| コレクター側がリクエストを受け取っているか | コレクターのアクセスログ |
nodejs_compat フラグ
一部のライブラリが Node.js 組み込みモジュールを必要とする場合は nodejs_compat を有効化します。
{
"compatibility_flags": ["nodejs_compat"],
"compatibility_date": "2025-01-01"
}
ただし nodejs_compat でも Workers で利用できない Node.js API は存在します。child_process・fs・net 等のシステムコールに依存するライブラリは Workers では動作しません。
Failure Boundary:head_sampling_rate の設定
head_sampling_rate: 1 はすべてのリクエストをトレースします。高トラフィックの Worker ではトレースデータが膨大になり、コレクター側の料金が急増することがあります。本番環境では 0.1(10%)などに下げることを検討してください。
{
"observability": {
"enabled": true,
"head_sampling_rate": 0.1 // 10% サンプリング
}
}