機能このページを編集.md

オブザーバビリティ

@lazarv/react-server は開発環境と本番環境の両方で完全な可観測性を実現する組み込みの OpenTelemetry 統合を提供します。有効化するとランタイムは自動的に HTTP リクエスト、SSR レンダリング、サーバー関数、ミドルウェアを計測し、アプリケーションコードを変更することなく分散トレースとメトリクスを発行します。

OpenTelemetryの依存関係はすべてオプションであり、遅延読み込みされます。テレメトリが無効化されている場合(デフォルト)、実行時のオーバーヘッドはゼロです。すべての計測はノーオペレーションオブジェクトに解決されます。

OpenTelemetryパッケージをインストールする

pnpm add @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/sdk-trace-base @opentelemetry/exporter-trace-otlp-http @opentelemetry/exporter-metrics-otlp-http @opentelemetry/sdk-metrics @opentelemetry/core @opentelemetry/resources @opentelemetry/semantic-conventions

テレメトリを有効にする

テレメトリは次のいずれかの方法で有効にできます。

1. 設定ファイルreact-server.config.mjstelemetry セクションを追加する

export default { telemetry: { enabled: true, serviceName: "my-app", }, };

2. 環境変数 — 標準のOpenTelemetryエンドポイントを設定する

OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318

3. ランタイム固有の環境変数

REACT_SERVER_TELEMETRY=true

有効にするとランタイムはサーバー起動時にOpenTelemetry SDKを初期化し、サーバー終了時には適切にシャットダウンします。

すべてのテレメトリ設定は設定ファイル内の telemetry キー配下に存在します。

export default { telemetry: { // テレメトリを有効/無効にする (デフォルト: false) enabled: true, // バックエンドに報告されるサービス名(デフォルト:パッケージ名または"@lazarv/react-server") serviceName: "my-app", // OTLPエンドポイント (default: "http://localhost:4318") endpoint: "http://localhost:4318", // Exporterタイプ: "otlp" | "console" | "dev-console" (default: auto-detected) exporter: "otlp", // サンプリングレート 0.0–1.0 (default: 1.0 — sample everything) sampleRate: 1.0, // メトリクス構成 metrics: { // メトリクスの収集を有効化/無効化 (default: テレメトリが有効な場合true) enabled: true, // エクスポート間隔 ミリ秒単位 (default: 30000) interval: 30000, }, }, };

環境変数

以下の環境変数が有効です。

変数説明
OTEL_EXPORTER_OTLP_ENDPOINTOTLPコレクターエンドポイント。これを設定するとテレメトリも有効になります。
OTEL_SERVICE_NAMEサービス名のオーバライド
REACT_SERVER_TELEMETRYテレメトリを有効にするには "true" に設定してください。

標準のOpenTelemetry環境変数(OTEL_*)はSDKに渡されます。

テレメトリが有効化されている場合、ランタイムは自動的に以下のトレーススパンを作成します。

HTTPリクエストスパン

HTTPリクエスト — 受信するすべてのHTTPリクエストのルートスパン。受信ヘッダーからW3C TraceContextを抽出し、レスポンスヘッダーにトレースコンテキストを挿入します。

属性説明
http.methodHTTPメソッド (GET, POST, etc.)
http.url完全なリクエストURL
http.targetリクエストパス
http.hostホストヘッダー
http.schemeプロトコル (http/https)
http.user_agentUser-Agentヘッダー
http.status_codeレスポンスステータスコード(レスポンス後に設定される)
http.response_content_typeレスポンスContent-Type (レスポンス後に設定される)
net.peer.ipクライアントIPアドレス

ミドルウェアスパン

ミドルウェア: {displayName} — コンポーズチェーン内の各ミドルウェアごとに1つのスパンを生成します。各スパンは当該ミドルウェア自身の処理のみを計測します — next()を呼び出すと、次のミドルウェアが実行される前にスパンが終了します。

属性説明
react_server.middleware.indexミドルウェアチェーン内の位置(0ベース)
react_server.middleware.nameミドルウェア関数名
react_server.middleware.display_name人間が読みやすい名前(例: "CORS"、"静的ファイル"、"SSRハンドラー")

レンダリングスパン

レンダラーはリクエストごとに2つのネストされた**Render**スパンを作成します。

  1. RSCレンダー — RSC → SSRパイプライン全体を覆う外側のスパン
  2. SSRレンダー — HTMLストリームレンダリングのための内部スパン(RSCの子要素)
属性説明
react_server.render_type"RSC" or "SSR"
react_server.outletアウトレット名 or "PAGE_ROOT"
http.urlリクエストURL

サーバ関数スパン

サーバ関数 — 各サーバ関数呼び出しの期間

属性説明
react_server.server_function.id関数識別子
react_server.server_function.is_formフォーム送信によって呼び出されるかどうか
react_server.server_function.has_error関数がエラーを生成したかどうか(実行後に設定される)

キャッシュスパン

キャッシュ検索 — 各 useCache() 呼び出しに対するスパン。結果に基づいて動的に キャッシュヒット または キャッシュミス → 再計算 に名前が変更されます。

属性説明
react_server.cache.providerキャッシュプロバイダー名 (or "default")
react_server.cache.ttlTTL値 (or "Infinity")
react_server.cache.forceキャッシュが強制的に更新されたかどうか
react_server.cache.hitヒット時はtrue、ミス時はfalse(ルックアップ後に設定)

サーバー起動スパン

サーバー起動 — サーバーの初期化(開発環境と本番環境の両方)をカバーするスパン。

属性説明
react_server.mode"development" or "production"
react_server.rootアプリケーションルート or "file-router"

Vite開発サーバー初期化スパン

Vite Dev Server Init — Vite開発サーバー作成の処理時間(開発時のみ)。

属性説明
react_server.vite.modeViteモード
react_server.vite.force依存性最適化が強制されたかどうか

Viteプラグインフックスパン

Vite plugin [{pluginName}].{hookName} — 開発中、すべてのViteプラグインフック(resolveIdloadtransformbuildStartbuildEndhandleHotUpdate)は自動的に計測されます。

属性説明
react_server.vite.pluginプラグイン名
react_server.vite.hookフック名
react_server.vite.module_id処理中のモジュール(resolveIdloadtransform 用)

以下のメトリクスは自動的に記録されます。

メトリックタイプ説明
http.server.request.durationヒストグラム (ms)HTTPリクエストの実行時間
http.server.active_requestsアップダウンカウンターフライト中のHTTPリクエスト数
react_server.server_function.durationヒストグラム (ms)サーバ関数の実行時間
react_server.rsc.render.durationヒストグラム (ms)RSCレンダリングの実行時間
react_server.dom.render.durationヒストグラム (ms)SSR DOMレンダリングの継続時間
react_server.cache.hitsCounterキャッシュヒット数
react_server.cache.missesCounterキャッシュミス数

@lazarv/react-server/telemetry をインポートして、サーバーコンポーネント、サーバ関数、またはミドルウェア内でカスタムスパンとメトリクスを用いて組み込みテレメトリを拡張します。

withSpan(name, attributes?, fn)

子スパン内で関数を実行する。

import { withSpan } from "@lazarv/react-server/telemetry"; export async function fetchProducts() { return withSpan("db.query", { "db.system": "postgres" }, async (span) => { const rows = await db.query("SELECT * FROM products"); span.setAttribute("db.row_count", rows.length); return rows; }); }

getSpan()

現在のリクエストスパンを取得し、属性やイベントを追加する。

import { getSpan } from "@lazarv/react-server/telemetry"; export function MyComponent() { const span = getSpan(); span.addEvent("component.render", { component: "MyComponent" }); // ... }

getTracer()

手動でスパンを作成するためのアクティブなOpenTelemetryトレーサーを取得します。

import { getTracer } from "@lazarv/react-server/telemetry"; const tracer = getTracer(); const span = tracer.startSpan("custom.operation"); try { // ... your code } finally { span.end(); }

getMeter()

カスタムメトリクス用のアクティブなOpenTelemetryメーターを取得する。

import { getMeter } from "@lazarv/react-server/telemetry"; const meter = getMeter(); const counter = meter.createCounter("my_app.api_calls", { description: "Number of external API calls", }); counter.add(1, { "api.name": "stripe" });

getOtelContext()

現在のリクエストのOTelコンテキストを取得します。高度な伝播シナリオで有用です。

import { getOtelContext } from "@lazarv/react-server/telemetry"; const ctx = getOtelContext();

injectTraceContext(headers)

サービス間分散トレーシングのため、送信ヘッダーにW3Cトレースコンテキストを挿入する。

import { injectTraceContext } from "@lazarv/react-server/telemetry"; const headers = new Headers(); await injectTraceContext(headers); const res = await fetch("https://api.example.com/data", { headers });

ランタイムは自動的に行われる。

  1. 抽出 受信リクエストから W3C TraceContext ヘッダー(traceparenttracestate)を取得
  2. 伝播 ミドルウェアチェーン、SSR ハンドラー、サーバー関数を通じてコンテキストを伝播
  3. 挿入 送信レスポンスヘッダーにトレースコンテキストを挿入

これは上流サービス(APIゲートウェイ、ロードバランサー)からのトレースが自動的にreact-serverトレースと相関付けられ、下流サービスがトレースを引き継げることを意味します。

開発時、OTLPエンドポイントを設定せずにテレメトリを有効にすると、ランタイムはコンソールエクスポーターを使用します。このエクスポーターはターミナルにコンパクトなトレースツリーを表示します。

GET /about 200 45.2ms ├─ Middleware: CORS 0.3ms ├─ Middleware: Cookies 0.1ms ├─ Middleware: SSR Handler ░░░░░░ 42.1ms ├─ Render RSC ░░░░ 18.3ms └─ Render SSR ░░░░░ 22.4ms ├─ Vite plugin [vite:resolve].resolveId: ×47 3.2ms ├─ Vite plugin [vite:css].transform: ×12 1.1ms └─ 8 spans (<1ms)

特徴

開発者コンソールエクスポーターを明示的に使用するには、

export default { telemetry: { enabled: true, exporter: "dev-console", }, };

Jaeger

OTLPサポートでJaegerをローカルで実行する。

docker run -d --name jaeger \ -p 16686:16686 \ -p 4318:4318 \ jaegertracing/all-in-one:latest

次にテレメトリを有効にします。

OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 pnpm react-server start

http://localhost:16686 を開いてトレースを表示します。

Grafana / Tempo

設定ファイルでOTLPエンドポイントを構成してください。

export default { telemetry: { enabled: true, endpoint: "https://tempo.grafana.net/otlp", serviceName: "my-production-app", }, };

Honeycomb / Datadog / New Relic

ほとんどの可観測性プラットフォームはOTLP取り込みをサポートしています。環境変数を使用して、エンドポイントと必要なヘッダーを設定してください。

OTEL_EXPORTER_OTLP_ENDPOINT=https://api.honeycomb.io OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=your-api-key"

エッジランタイム(Cloudflare Workers、Netlify Edge Functionsなど)でも軽量トレーサーによるテレメトリがサポートされています。プラットフォームの制約により、エッジではトレースのみがサポートされ、メトリクスは利用できません。

エッジ向けにビルドする場合、バンドラーは自動的にOpenTelemetryパッケージを処理します。

エッジテレメトリはBasicTracerProviderSimpleSpanProcessorを使用し、OTLP HTTPエクスポーターの利用を試みます。利用できない場合はコンソール出力にフォールバックします。

テレメトリが有効になっていない場合、

これによりテレメトリを使用しないアプリケーションのパフォーマンスへの影響がなくなります。