コンテンツにスキップ

OpenTelemetry

🌐 AI と人間による翻訳

この翻訳は、人間のガイドに基づいて AI によって作成されました。🤝

原文の意図を取り違えていたり、不自然な表現になっている可能性があります。🤖

AI LLM をより適切に誘導するのを手伝う ことで、この翻訳を改善できます。

英語版

APIを実行しているとき、受信するトラフィックの量、遅いリクエスト、エラーが発生するタイミングを把握したくなることがあります。

テレメトリーは、こうした疑問に答えるためのアプリケーションの動作に関するデータです。一般的には、次の種類があります:

  • メトリクス: レスポンス時間や処理中のリクエスト数など、時間の経過に沿って集計できる測定値です。
  • トレース: 個々のリクエストと、それを処理するために実行された操作の記録です。時間を計測する各操作をスパンと呼びます。
  • ログ: アプリケーションの起動や操作の失敗など、イベントのタイムスタンプ付きの記録です。

OpenTelemetryは、テレメトリーを収集して監視サービスに送信するための標準とツールのセットです。監視サービスのダッシュボードで、そのデータを確認できます。

FastAPIはデフォルトでOpenTelemetryをサポートしており、HTTPリクエストのトレース、メトリクス、ログを提供します。WebSocket接続でもトレースとログを提供します。このデータを確認するには、受信する監視サービスを設定してください。

FastAPIのインストール

テレメトリーを送信するためのパッケージを含むstandardオプションを指定してFastAPIをインストールします:

$ uv add "fastapi[standard]"
---> 100%

アプリの作成

main.pyファイルを作成します:

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}

テレメトリーを収集するための独自のコードを書く必要はありません。

FastAPI Cloud

fastapi[standard]を使用してFastAPI Cloudにデプロイすると、メトリクスは自動的に機能します。追加の設定は不要です。

Proプランでは、メトリクスダッシュボードでリクエスト数、エラー率、レスポンス時間を確認できます。

サンプルデータを表示したFastAPI Cloud Proのメトリクスダッシュボード

その他の監視サービス

別の監視サービスにテレメトリーを送信するには、テレメトリー送信用のOpenTelemetryプロトコルであるOTLPを受け付けるエンドポイントを設定します。サービスのHTTP/protobufベースエンドポイントを使用してください。

例のURLを自分のエンドポイントに置き換えて、次の環境変数を設定します:

export FASTAPI_OTEL_AUTO_CONFIGURE=true
export OTEL_SERVICE_NAME=my-api
export OTEL_EXPORTER_OTLP_ENDPOINT=https://collector.example.com

FASTAPI_OTEL_AUTO_CONFIGURE=trueは、FastAPIによるエクスポーターの自動設定を有効にします。OTEL_SERVICE_NAMEは、監視サービス内でアプリを識別するための名前です。エンドポイントはデータを受信するためのベースURLです。そのURL配下の/v1/tracesにトレース、/v1/metricsにメトリクス、/v1/logsにログが送信されます。

サービスで認証が必要な場合は、OTEL_EXPORTER_OTLP_HEADERSにサービスが指定するヘッダー(例: api-key=YOUR_API_KEY)を設定してください。

アプリの実行

同じターミナルでアプリを起動します:

$ uv run fastapi run

別のターミナルでリクエストを送信します:

$ curl http://127.0.0.1:8000/items/1
{"item_id":1}

監視サービスを開き、my-apiを探します。次のエクスポート後に、GET /items/{item_id}スパンを含むトレースと、リクエスト数、レスポンス時間、処理中のリクエスト数のメトリクスを確認できます。

テレメトリーのカスタマイズ

プロバイダーとエクスポーターの設定

プロバイダーは、トレース、メトリクス、ログを記録するオブジェクトを提供します。その設定によって、データの処理方法とエクスポート方法を制御します。

テレメトリーライブラリは、OpenTelemetryのグローバルプロバイダーを設定できます。アプリの起動前にライブラリを設定すると、FastAPIはそれらのプロバイダーを自動的に使用します。

デフォルトでは、FastAPIはエクスポーターを追加せずに、設定済みのプロバイダーを使用します。自動設定が有効で、環境変数にOTLPエンドポイントが設定されている場合、FastAPIは有効な各プロバイダーに、その送信先のエクスポーターを追加します。既存のエクスポーターは、それぞれの送信先にデータを送信し続けます。

別のライブラリがすでに同じ送信先へのエクスポートを設定している場合は、テレメトリーの重複を避けるため、FASTAPI_OTEL_AUTO_CONFIGUREを未設定のままにするか、falseに設定してください。

telemetry辞書にプロバイダーを直接渡すこともできます。例えば、次のプロバイダーはOpenTelemetryのコンソールエクスポーターを使用して、リクエストのスパンをターミナルに出力します:

from fastapi import FastAPI
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter

tracer_provider = TracerProvider()
tracer_provider.add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))

app = FastAPI(telemetry={"tracer_provider": tracer_provider})


@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}

エクスポーターは、スパンを送信先に送ります。BatchSpanProcessorはスパンをまとめ、バックグラウンドで送信します。監視ライブラリの送信先を使用するには、コンソールエクスポーターをそのライブラリが提供するエクスポーターに置き換えてください。その他の設定オプションについては、OpenTelemetryのPython計装ガイドを参照してください。

メトリクスやログのプロバイダーを指定するには、同じ辞書内でmeter_providerまたはlogger_providerを使用します。プロバイダーを作成したアプリケーションまたはライブラリが、そのシャットダウンを管理します。FastAPIは、自身が追加したエクスポートコンポーネントを管理します。

注意

OpenTelemetryはデフォルトでグローバルプロバイダーを使用します。マウントされたサブアプリケーションごとに独立したテレメトリー設定は保証されません。

リクエスト操作のトレース

デフォルトでは、リクエストのトレースには、依存関係の解決、path operation関数の実行、レスポンスのシリアライズ、FastAPIのBackgroundTasks内の各タスクの実行に対応するスパンが含まれます。これらのスパンは同じプロバイダーとエクスポーターを使用します。

バックグラウンドタスクのスパンも、リクエストのトレースの一部として扱われます。これらはHTTPレスポンスのスパンが終了した後に実行されるため、測定されるレスポンス時間は増加しません。

HTTPリクエストのスパンのみを記録するには、operation_spansをFalseに設定します:

from fastapi import FastAPI

app = FastAPI(telemetry={"operation_spans": False})


@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}

WebSocket接続のトレース

各WebSocket接続には、WS /ws/{room}のようなスパンがあり、ハンドラーと依存関係のクリーンアップを対象とします。同じプロバイダーと設定を使用し、依存関係の解決とエンドポイントの実行にはoperation_spansの設定も適用されます。

HTTPリクエストのメトリクスは、HTTPリクエストのみを対象とします。コード1000または1001による正常なWebSocket切断では、エラーログは生成されません。

エラーの確認

FastAPIは、未処理の例外をOpenTelemetryのログとして記録し、リクエストまたは接続のトレースに関連付けます。トレースがサンプリングされていない場合でも、エラーログは記録されます。

例外ログには、例外の型、メッセージ、スタックトレースが含まれます。メッセージやスタックトレースには機密情報が含まれる可能性があります。プロバイダーのログプロセッサーを使用してフィルタリングやマスキングを行うか、logsをFalseに設定してこれらのログを無効にしてください。

FastAPIは、リクエストのバリデーション失敗も、ルートとエラー数を含む警告ログとして記録します。これらのログに無効な入力値は含まれません。

記録対象の選択

telemetry辞書では、次の設定も指定できます:

設定 目的 デフォルト
tracing HTTPリクエストとWebSocket接続のスパンを記録します True
metrics HTTPリクエストのメトリクスを記録します True
logs バリデーション失敗と未処理の例外を記録します True
operation_spans リクエスト操作のスパンを追加します True
exclude ASGIスコープを受け取る関数がTrueを返した場合、そのリクエストを除外します None
auto_configure 環境変数に設定されたエンドポイントのエクスポーターを追加します FASTAPI_OTEL_AUTO_CONFIGURE=trueの場合はTrue、それ以外はFalse

例えば、ヘルスチェックを除外してメトリクスを収集するには、次のようにします:

from fastapi import FastAPI

app = FastAPI(
    telemetry={
        "tracing": False,
        "exclude": lambda scope: scope["path"] == "/health",
    }
)

telemetry辞書で明示的に指定したauto_configureの値は、FASTAPI_OTEL_AUTO_CONFIGUREより優先されます。コードで自動設定を有効にするにはtelemetry={"auto_configure": True}を使用します。環境変数で有効になっていても、アプリで無効にするにはtelemetry={"auto_configure": False}を使用してください。