.NET 8 × OpenTelemetry で Web API をトレーシングする方法|Jaegerによる分散トレーシングの可視化と実装手順

C#

開発中のAPIやサービスで「どこで何が起きているのか」を可視化したいと思ったことはありませんか?
そんなときに役立つのが トレーシング です。本記事では、.NET のトレーシング機能として注目されている OpenTelemetry を利用して、アプリケーションの動作を可視化する方法を解説します。
トレース情報の表示には、分散トレーシングプラットフォーム Jaeger を使用します。開発環境でも簡単にトレーシングを始められるよう、Docker を使った手順を紹介します。

環境

以下の環境で動作確認を行っています。

oswindows11(4cpu、16GB)
.NET8.0.304
IDEVisual Studio 2022 Community
Jaeger(コンテナ)2.8.0
Docker28.3.0

記事のコードは、解説をわかりやすくするために、エラーチェックなど一部の処理を省略しています。

Jaegerの起動

ローカル(Windows)の Docker 環境で Jaeger を動作させます。Docker のセットアップ手順は本記事では省略します。

まず、以下の内容で docker-compose.yml ファイルを作成します。

services:
  jaeger:
    image: jaegertracing/jaeger:2.8.0
    ports:
      - "16686:16686"
      - "4317:4317"
      - "4318:4318"
    restart: always

作成したら、ファイルのあるディレクトリで以下のコマンドを実行し、コンテナを起動します。

docker compose up -d

ブラウザで http://localhost:16686/ にアクセスし、Jaeger UI が表示されれば起動成功です。

OpenTelemetryの設定

次に、トレーシング情報を Jaeger に送信するための設定を行います。ASP.NET Core Web API プロジェクトを作成し、以下のライブラリを NuGet から追加します。

パッケージ名概要
OpenTelemetry.Extensions.Hosting (1.12.0)DI(依存関係注入)を通じた OpenTelemetry の構成用拡張ライブラリ
OpenTelemetry.Instrumentation.AspNetCore (1.12.0)ASP.NET Core のリクエスト処理(受信)を自動トレース
OpenTelemetry.Instrumentation.Http (1.12.0)HttpClient による外部リクエスト(送信)を自動トレース
OpenTelemetry.Exporter.OpenTelemetryProtocol (1.12.0)OTLP 形式でトレース情報を外部へ送信
Npgsql.OpenTelemetry (9.0.3)PostgreSQL(Npgsql)による SQL 実行をトレース

トレーシング設定

以下のように OpenTelemetry の初期化処理を記述します。

builder.Services.AddOpenTelemetry()
	.ConfigureResource(r => r.AddService(builder.Environment.ApplicationName))
	.WithTracing(b =>
	{
		b.AddAspNetCoreInstrumentation()
		.AddHttpClientInstrumentation()
		.AddNpgsql()
		.AddOtlpExporter();
	});
  • ConfigureResourceでは、サービス名を指定します。これは Jaeger の UI 上で「Service」名として表示され、トレースのタイトルにも使用されます。
  • AddXXXInstrumentation を用いることで、それぞれのコンポーネントに対する自動トレース設定が行われます。
  • AddOtlpExporterにより、トレース情報を外部(ここでは Jaeger)に送信します。

トレース情報送信先の設定

OTLP 送信先の設定を行います。ポート4317がgRPC、4318がHTTPエンドポイントです。HTTPエンドポイントを使う場合は「“OTEL_EXPORTER_OTLP_PROTOCOL”: “http/protobuf”」を追加で設定します。

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Npgsql.Command": "Trace",
            "Microsoft.AspNetCore": "Information"
        }
    },
    "AllowedHosts": "*",
    "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317"
}

APIの作成

トレースを確認するため、2 つの API を用意します:

  • /entry:select 文と /sub API 呼び出しを行う
  • /sub:select 文と update 文を実行する

詳細は割愛しますが、ざっと以下のような感じです。

	[HttpGet]
	[Route("/entry")]
	public async Task<IActionResult> Entry()
	{
        // http post localhost:xxxx/sub
        // select...
    }

	[HttpPost]
	[Route("/sub")]
	public async Task<IActionResult> Sub([FromBody] Body body)
	{
        // select...
        // update...
    }

動作確認

/entry API を実行後、http://localhost:16686 にアクセスし、サービス名として Program.cs で指定した名前が表示されていれば、トレース情報の送信に成功しています。

「Find Traces」ボタンをクリックすると、収集されたトレース情報の一覧が表示されます。リクエストをクリックすると詳細が表示され、HTTP 通信や SQL 実行のトレースが確認できます。

各スパンをクリックするとプロパティ情報などの詳細をさらに確認できます。

こちらはsubAPIへのHTTPリクエスト情報です。「OpenTelemetry.Instrumentation.Http」ライブラリで取得されたものになります。

こちらはNpgsqlでのSQL実行情報の詳細です。

複雑な設定をしなくても簡単にこのようなトレース情報を取得確認できて非常に便利です。

追加設定

トレースで取得する情報をカスタマイズできます。今回はNpgsqlのトレース情報をカスタマイズしてみましょう。NpgsqlをDIしている場合はProgram.csでカスタマイズできます。

スパン名の変更

デフォルトではスパン名は DB 名(例:postgres)ですが、変更することができます。ここでは実行されたSQL文に変更してみます。

builder.Services.AddNpgsqlDataSource("connection string", b =>
{
	b.ConfigureTracing(o =>
	{
		o.ConfigureCommandSpanNameProvider(c => c.CommandText);
	});
});

「postgres」の個所が実行されたSQL文に変更されています。

タグの変更

先ほど確認したSQLのトレースには接続文字列が含まれていました。パスワードなどのセキュリティ情報は送りたくないのでこれを削除します。

SetTagでトレースの各種情報を変更できます。削除する場合は値にnullを設定します。

builder.Services.AddNpgsqlDataSource("connection string", b =>
{
	b.ConfigureTracing(o =>
	{
		o.ConfigureCommandSpanNameProvider(c => c.CommandText);
		o.ConfigureCommandEnrichmentCallback((c, a) =>
		{
			c.SetTag("db.connection_string", null);
			c.SetTag("db.custom", "custom info");
		});
	});
});

まとめ

OpenTelemetry を利用することで、複雑な設定なしに Web API の HTTP 処理やデータベース操作のトレース情報を収集・可視化できます。特に Jaeger との連携により、開発時の問題調査や性能分析がより直感的に行えるようになります。

また、スパン名やタグのカスタマイズも可能で、セキュリティや可読性に配慮した運用も実現できます。

コメント