既存の Next.js ルートを一つ観測する
既存の Next.js App Router アプリで、最新の修正を含む現行バージョンと対応する Node.js デプロイを使用してください。after API は Next.js 15.1 から安定版ですが、この API の最低バージョンは未修正の旧バージョンの推奨ではありません。ハンドラーが Response を返したか、例外を投げたかを観測します。ブラウザーへの到達、ストリーム本体の完了、バックグラウンド業務の完了は測定しません。
ルートを変更する前に
管理しているルートと、安全に実行できる承認済みの操作を選びます。認証、検証、業務ロジックを保持してください。TELEMETRY_API_KEY はサーバー環境だけに置き、NEXT_PUBLIC_ を付けません。ホームページの匿名キーは送信とクエリに使えます。アカウントキーで確認する場合は read-and-write 権限が必要です。送信だけのアプリは取り込み専用キーを使えます。
サーバーヘルパーを追加する
lib/with-telemetry.js に保存します。顧客の識別子を含まない固定ルートテンプレートを使います。生成する ID は一回のハンドラー呼び出しを表し、人物や論理ジョブを表しません。URL、本文、Cookie、ヘッダー、エラーメッセージは送信しません。
import { after } from 'next/server';
import { randomUUID } from 'node:crypto';
function warnTelemetry(message) {
try {
console.warn(message);
} catch {
// Diagnostic failure must not change the application outcome.
}
}
export function withTelemetry(handler, routeTemplate) {
return async function observedHandler(request, context) {
const started = performance.now();
const invocationId = randomUUID();
let outcome = 'threw';
let statusCode = null;
try {
const response = await handler(request, context);
outcome = 'returned_response';
statusCode = response.status;
return response;
} finally {
const event = {
invocation_id: invocationId,
route_template: routeTemplate,
method: request.method,
handler_outcome: outcome,
status_code: statusCode,
latency_ms: performance.now() - started,
environment: process.env.NODE_ENV || 'development',
};
try {
after(async () => {
const key = process.env.TELEMETRY_API_KEY;
if (!key) {
warnTelemetry('Telemetry key missing; event not sent');
return;
}
try {
const response = await fetch('https://api.telemetry.sh/log', {
method: 'POST',
headers: {
Authorization: `Bearer ${key}`,
'Content-Type': 'application/json',
},
cache: 'no-store',
signal: AbortSignal.timeout(2000),
body: JSON.stringify({ table: 'nextjs_route_observed', data: event }),
});
if (!response.ok) warnTelemetry('Telemetry event send rejected');
} catch {
warnTelemetry('Telemetry event send failed');
}
});
} catch {
warnTelemetry('Telemetry background scheduling failed');
}
}
};
}
既存のハンドラーをラップする
既存の export された GET 関数を existingGET に改名し、本文は変えません。その後、下のラッパーを export します。メソッドと固定テンプレートは実際のルートに合わせます。設定完了のために常に成功する架空のハンドラーを作らないでください。
import { withTelemetry } from "@/lib/with-telemetry";
export const GET = withTelemetry(existingGET, "/api/reports/:id");
実際の呼び出しを確認する
アプリで承認済み操作を実行し、Telemetry のテーブルをクエリします。ルート、メソッド、時刻、結果、ステータスを直前の操作と照合します。HTTP の受理だけでは確認になりません。オフラインのテスト、デモルート、エージェント QA は顧客の統合ではありません。架空の送信には telemetry_quickstart を使います。
SELECT invocation_id, route_template, method, handler_outcome,
status_code, latency_ms, environment, timestamp_utc
FROM nextjs_route_observed
WHERE timestamp_utc >= now() - INTERVAL '15 minutes'
ORDER BY timestamp_utc DESC
LIMIT 20;
保証しないこと
Next.js after はレスポンス終了後に送信をスケジュールします。永続キューではなく、実行時間の上限、停止、タイムアウト、ネットワーク障害でイベントを失う可能性があります。送信は二秒でタイムアウトし、警告は秘密を含まない固定文です。自動再試行や重複排除は保証しません。既存ログを残し、必須の監査記録には永続的な配信経路を使ってください。
latency_ms はハンドラーが返すか投げるまでの時間で、イベント送信時間を含みません。returned_response は 4xx や 5xx の場合もあります。threw にはフレームワークのリダイレクトなども含まれ、自動的にサーバー障害とは判断できません。キー不足やテレメトリー障害で元のレスポンスや例外を置き換えないでください。導入前に自分の実行環境で確認します。
フレームワークの参考と次の手順
Next.js after のリファレンスでバージョンとデプロイの対応を確認できます。静的エクスポートには対応せず、アダプターには明示的な対応が必要です。レスポンスの保持、例外、テレメトリー送信の失敗を、隔離された Next.js 16.3.8 の開発用 App Router アプリで確認しました。イベント送信は捕捉し、外部ネットワークは無効にしました。実際の Telemetry への取り込みや利用者の本番ホストを検証したものではありません。イベント取り込み確認と JavaScript SDK ガイドを続けて読んでください。