コンテンツにスキップ

第26章: Workers Analytics Engine によるメトリクス集計(実践チュートリアル)

APIのレスポンスタイム、アクセス元国、ユーザーの行動イベントをリレーショナルDB(D1やPostgres)に毎秒何万件も書き込むと、DBの書き込み上限に達してクラッシュしてしまいます。 Workers Analytics Engine は、高スループットな時系列テレメトリデータをエッジから直接書き込めるように設計された専用分析基盤です。


本チュートリアルのゴール

  • wrangler.jsonc での Analytics Engine データセットの有効化
  • Workers からの非同期データポイント書き込み(writeDataPoint
  • Cloudflare SQL API を叩き、時系列集計クエリを実行してダッシュボード用のJSONを取得
【データフロー】
[ エッジWorkers (秒間10,000リクエスト) ]
│ writeDataPoint (非ブロッキング・超高速書き込み)
[ Workers Analytics Engine (時系列データレイク) ]
│ SQLクエリ (avg(double1), count(), group by)
[ 管理画面ダッシュボード / Grafana / API ]

Step 1: wrangler.jsonc の設定

データセット名(例: api_performance)をバインドします。

{
"name": "telemetry-service",
"main": "src/index.ts",
"compatibility_date": "2024-09-01",
"analytics_engine_datasets": [
{
"binding": "METRICS",
"dataset": "api_performance"
}
]
}

型定義を更新します。

Terminal window
npx wrangler types

Step 2: メトリクス収集ミドルウェアの実装(src/index.ts

すべてのAPIリクエストのレイテンシ、ステータスコード、国コードを自動記録します。

import { Hono } from 'hono';
type Bindings = {
METRICS: AnalyticsEngineDataset;
};
const app = new Hono<{ Bindings: Bindings }>();
// 1. メトリクス収集ミドルウェア
app.use('*', async (c, next) => {
const startTime = Date.now();
// 次のハンドラーを実行
await next();
const durationMs = Date.now() - startTime;
const status = c.res.status;
const path = c.req.path;
const method = c.req.method;
const country = c.req.header('cf-ipcountry') || 'XX';
// Analytics Engine へデータポイントを書き込み(処理速度に一切影響を与えません)
c.env.METRICS.writeDataPoint({
// 文字列データ(blobs: 最大20個まで)
blobs: [
method, // blob1: HTTPメソッド
path, // blob2: リクエストパス
country, // blob3: 国コード
],
// 数値データ(doubles: 最大20個まで、集計対象)
doubles: [
durationMs, // double1: レイテンシ(ms)
status, // double2: HTTPステータス
],
// インデックスキー(サンプリングやグループ化用)
indexes: [method],
});
});
// サンプルAPIエンドポイント
app.get('/api/products', (c) => c.json([{ id: 1, name: '商品A' }]));
app.get('/api/orders', (c) => c.json([{ id: 101, amount: 2500 }]));
export default app;

Step 3: SQL APIによるリアルタイム集計クエリの実行

CloudflareのAnalytics Engineは、専用のSQLエンドポイントを提供しています。ターミナルから curl で集計結果を取得してみます。

Terminal window
# アカウントIDとAPIトークンを設定
ACCOUNT_ID="your-cloudflare-account-id"
API_TOKEN="your-api-token"
# 直近24時間のエンドポイント別リクエスト数と平均レスポンス時間を集計
curl -X POST "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/analytics_engine/sql" \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Content-Type: text/plain" \
-d "
SELECT
blob2 AS endpoint,
count() AS total_hits,
round(avg(double1), 2) AS avg_duration_ms,
max(double1) AS max_duration_ms
FROM api_performance
WHERE timestamp > NOW() - INTERVAL '1' DAY
GROUP BY endpoint
ORDER BY total_hits DESC
LIMIT 5;
"

出力例(JSON):

{
"data": [
{
"endpoint": "/api/products",
"total_hits": 45200,
"avg_duration_ms": 12.45,
"max_duration_ms": 184.0
},
{
"endpoint": "/api/orders",
"total_hits": 8900,
"avg_duration_ms": 28.10,
"max_duration_ms": 320.0
}
]
}

自前でPrometheusやDatadogを立ち上げることなく、わずか数行のコードでエンタープライズ規模の時系列メトリクス集計基盤が完成します。


まとめ

  • 高スループット: 大量アクセス時もDBと違ってロックや接続制限の心配がゼロ。
  • 標準SQL互換: avg(), count(), quantile() などの強力な集計関数でダッシュボードを即座に構築可能。

💡 用語解説コラム

[!NOTE] テレメトリ (Telemetry)
遠隔のシステムからパフォーマンスデータや稼働状態、エラー情報を自動収集して集約・送信する仕組み。

[!NOTE] 時系列データベース (Time Series DB)
時間の経過に沿って発生するデータ(アクセス数、CPU使用率、センサー値等)の記録・集計に特化したデータベース。