Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

可観測性

最終更新 Markdown で表示Agent セットアップ

Dynamic Workers は、実行中に捕捉した console.log() の呼び出し、例外、リクエストメタデータをログとして扱えます。これらのログを使うには、Tail Worker を付けます。Tail Worker は Dynamic Worker の終了後に動くコールバックで、収集したログ、例外、メタデータを渡します。

このガイドでは、次の方法を説明します。

  • Dynamic Worker のログを保存し、検索、絞り込み、クエリできるようにする
  • 実行中にログを集め、開発やデバッグ向けにリアルタイムで返す

Tail Workers でログを捕捉する

Dynamic Worker が出したログを保存するには、捕捉して保存先へ書き込む必要があります。設定は次の 3 ステップです。

  1. ローダー Worker で Workers Logs を有効にし、ログ出力を保存します。
  2. Dynamic Worker からログを受け取り、Workers Logs へ書き込む Tail Worker を定義します。
  3. Dynamic Worker の作成時に、その Tail Worker を付けます。

ローダー Worker で Workers Logs を有効にする

ローダー Worker の Wrangler 設定に observability を追加し、Workers Logs を有効にします。ただし、Workers Logs が捕捉するのはローダー Worker 自身のログ出力だけです。Dynamic Workers は別なので、その console.log() は自動では含まれません。Dynamic Worker のログを Workers Logs へ入れるには、Dynamic Worker からログを受け取り、ローダー Worker の Workers Logs へ書き込む Tail Worker を定義します。

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "observability": {
    "enabled": true,
    "head_sampling_rate": 1
  }
}
[observability]
enabled = true
head_sampling_rate = 1

Tail Worker を定義する

Dynamic Worker が動くと、ランタイムはその console.log()、例外、リクエストメタデータをすべて集めます。初期値では、これらのログは Dynamic Worker の終了後に破棄されます。

残すには、ローダー Worker に Tail Worker を定義します。Tail Worker は tail() メソッドを持つクラスです。ここに、ログの扱いを決めるコードを書きます。ランタイムは Dynamic Worker の終了後にこのメソッドを呼び、実行中に集めた内容を渡します。

tail() の中では、JSON オブジェクトを console.log() に渡して、各ログエントリを Workers Logs へ書き込みます。各エントリに workerId フィールドを入れると、どの Dynamic Worker が出したログかを判別でき、あとから Dynamic Worker ごとに絞り込みや検索ができます。

import { WorkerEntrypoint } from "cloudflare:workers";

export class DynamicWorkerTail extends WorkerEntrypoint {
	async tail(events) {
		for (const event of events) {
			for (const log of event.logs) {
				console.log({
					source: "dynamic-worker-tail",
					workerId: this.ctx.props.workerId,
					level: log.level,
					message: log.message,
				});
			}
		}
	}
}

Tail Worker は this.ctx.props.workerId から workerId を読みます。この値は、次の手順で Tail Worker を Dynamic Worker に付けるときに設定します。

Tail Worker はローダー Worker 内に定義するため、その console.log() 出力は、ローダー Worker 自身のログと一緒に Workers Logs へ保存されます。

Tail Worker を Dynamic Worker に付ける

Dynamic Worker を作成するときは、tails 配列に Tail Worker を渡します。これにより、この Dynamic Worker の終了後に、収集したログを定義した Tail Worker へ送るようランタイムへ伝えます。

前の手順で定義した DynamicWorkerTail クラスを参照するには、ctx.exports を使います。ctx は、ローダー Worker の fetch(request, env, ctx) ハンドラーの第 3 引数です。ctx.exports で、ローダー Worker からエクスポートしたクラスにアクセスできます。Dynamic Worker は別コンテキストで動き、クラスへ直接アクセスできないため、ctx.exports.DynamicWorkerTail() で参照を作り、ランタイムが Dynamic Worker へつなげるようにします。

Tail Worker に、どの Dynamic Worker のログかを伝える必要もあります。Tail Worker はローダー Worker の fetch() ハンドラーとは別に動くため、ローカル変数にはアクセスできません。情報を渡すには、インスタンス作成時に props オプションを使います。props は、Tail Worker を付けるときに設定するキーと値のプレーンオブジェクトで、実行時に Tail Worker が this.ctx.props から読めます。ここでは workerId を渡し、どの Dynamic Worker が出したログかを Tail Worker が分かるようにします。

const worker = env.LOADER.get(workerId, () => ({
	mainModule: WORKER_MAIN,
	modules: {
		[WORKER_MAIN]: WORKER_SOURCE,
	},
	tails: [
		ctx.exports.DynamicWorkerTail({
			props: { workerId },
		}),
	],
}));

return worker.getEntrypoint().fetch(request);

ログをリアルタイムで返す

上の設定はログをあとで見るために保存します。ただし、リアルタイムの開発では、すぐにログが必要なこともあります。難しい点は、Tail Worker とローダー Worker の fetch() ハンドラーが別々に動くことです。ログを持っているのは Tail Worker で、応答を組み立てるのは fetch() ハンドラーです。Tail Worker が書き込み、fetch() ハンドラーが読める共有の場所が必要です。

この用途には Durable Object が向いています。Tail Worker と fetch() ハンドラーの両方から、同じ Durable Object インスタンスを名前で参照できます。Tail Worker は Dynamic Worker の終了後にログを書き込み、fetch() ハンドラーはそれを読み出して応答に含めます。

流れは次のとおりです。

  1. fetch() ハンドラーは、Dynamic Worker を動かす前に Durable Object でログセッションを作成します。
  2. Dynamic Worker が動き、ログを出します。
  3. Dynamic Worker の終了後、Tail Worker は収集したログを同じ Durable Object へ書き込みます。
  4. fetch() ハンドラーは Durable Object からログを読み、応答として返します。
import { exports } from "cloudflare:workers";

// 1. Create a log session before running the Dynamic Worker.
const logSession = exports.LogSession.getByName(workerName);
const logWaiter = await logSession.waitForLogs();

// 2. Run the Dynamic Worker.
const response = await worker.getEntrypoint().fetch(request);

// 3. Wait up to 1 second for the Tail Worker to deliver logs.
const logs = await logWaiter.getLogs(1000);

動作する実装の全体は、Dynamic Workers Playground の例 を参照してください。

役に立ちましたか?