この記事では、OpenTelemetry を使用して .NET Web API をインストルメント化し、OTLP を使用してそのログ、メトリック、トレースを Aspire ダッシュボードに送信する方法について説明します。 OpenTelemetry パッケージを追加し、カスタム メトリックとトレースを構成し、ダッシュボードで結果を表示します。
Aspire ダッシュボードはAspireの標準的な部分ですが、テレメトリを送信するための OTLP エンドポイントを提供するスタンドアロンの Docker コンテナーとしても使用できます。 ダッシュボードでは、ログ、メトリック、およびトレースが視覚化されます。 この方法でダッシュボードを使用すると、 Aspireに依存せず、OTLP を使用してテレメトリを送信するすべてのアプリからのテレメトリが視覚化されます。 テレメトリを OTLP エンドポイントに送信できる場合、Java、Go、またはPythonで記述されたアプリでも同様に機能します。
Aspire ダッシュボードでは、Prometheus、Grafana、Jaeger などのオープンソース ソリューションよりも構成が少なく、セットアップ手順も少なくなります。 ただし、これらのツールとは異なり、 Aspire ダッシュボードは開発者向けの視覚化ツールであり、運用監視ツールではありません。
1.プロジェクトを作成する
Visual Studio の ASP.NET Core Empty テンプレートまたは次の .NET CLI コマンドを使用して、単純な Web API プロジェクトを作成します。
dotnet new web
2. OpenTelemetry パッケージを参照する
OpenTelemetry パッケージを追加するには、NuGet パッケージ マネージャーを使用するか、次のdotnet add packageコマンドを実行します。
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Instrumentation.Http
または、次の PackageReference 項目をプロジェクト ファイルに直接追加します。
<ItemGroup>
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.19.1" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.19.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.19.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.19.0" />
</ItemGroup>
注
OTel API は絶えず進化しているため、最新バージョンを使用します。
3. using ディレクティブを追加する
次の using ディレクティブをファイルの先頭に追加します。
using System.Diagnostics;
using System.Diagnostics.Metrics;
using OpenTelemetry.Exporter;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
4. メトリックとアクティビティの定義を追加する
次のコードでは、クライアントが API を呼び出す回数をカウントする新しいメトリック (greetings.count) と、新しいアクティビティ ソース (Otel.Example) を定義します。
builder.Buildする前に、次のコードを挿入します。
// Custom metrics for the application
var greeterMeter = new Meter("OTel.Example", "1.0.0");
var countGreetings = greeterMeter.CreateCounter<int>("greetings.count", description: "Counts the number of greetings");
// Custom ActivitySource for the application
var greeterActivitySource = new ActivitySource("OTel.Example");
5. OpenTelemetry と適切なプロバイダーを構成する
builder.Build の前に次のコードを挿入:
// Configure the shared OTLP connection used by logs, metrics, and traces.
var otlpEndpoint = new Uri(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]!);
Action<OtlpExporterOptions> configureOtlp = options =>
{
options.Endpoint = otlpEndpoint;
options.Protocol = OtlpExportProtocol.Grpc;
options.Headers = builder.Configuration["OTEL_EXPORTER_OTLP_HEADERS"]; // To secure endpoint (not in this example)
};
// Setup logging to be exported via OpenTelemetry
builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeFormattedMessage = true;
logging.IncludeScopes = true;
logging.AddOtlpExporter(configureOtlp);
});
var otel = builder.Services.AddOpenTelemetry();
// Identify this application as a single service in the Aspire dashboard.
otel.ConfigureResource(resource => resource.AddService(builder.Configuration["OTEL_SERVICE_NAME"]!));
// Add Metrics for ASP.NET Core and our custom metrics and export via OTLP
otel.WithMetrics(metrics =>
{
// Metrics provider from OpenTelemetry
metrics.AddAspNetCoreInstrumentation();
// Our custom metrics
metrics.AddMeter(greeterMeter.Name);
// Metrics provided by ASP.NET Core in .NET
metrics.AddMeter("Microsoft.AspNetCore.Hosting");
metrics.AddMeter("Microsoft.AspNetCore.Server.Kestrel");
// Export the metrics via OTLP
metrics.AddOtlpExporter(configureOtlp);
});
// Add Tracing for ASP.NET Core and our custom ActivitySource and export via OTLP
otel.WithTracing(tracing =>
{
tracing.AddAspNetCoreInstrumentation();
tracing.AddHttpClientInstrumentation();
tracing.AddSource(greeterActivitySource.Name);
tracing.AddOtlpExporter(configureOtlp);
});
このコードでは、さまざまなテレメトリ ソースを使用して OpenTelemetry を設定します。
- ログ レコードを収集する
ILoggerに OTel プロバイダーを追加します。 - メトリックを設定し、ASP.NET とカスタム メーターのインストルメンテーション プロバイダーとメーターを登録します。
- トレースを設定し、インストルメンテーション プロバイダーとカスタム
ActivitySourceを登録します。
その後、構成に環境変数を使用して OTLP エクスポーターを登録します。
6. OTLP 設定を構成する
コード、環境変数、またはアプリケーション構成の API を使用して OTLP エクスポーターを構成できます。 この例では、Logging セクションの後に、appsettings.Development.jsonのルートに OTLP 設定を追加します。
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
"OTEL_SERVICE_NAME": "OTLP-Example"
}
.NET OTLP エクスポーターのその他の設定、またはリソース属性を定義するための OTEL_RESOURCE_ATTRIBUTES などの一般的な OTel 設定を追加します。
注
ASP.NET Coreは、appsettings.jsonとappsettings.Development.jsonの両方を読み込みます。
appsettings.Development.jsonの設定は、開発環境でアプリを実行するときに、appsettings.jsonの重複する設定をオーバーライドします。
7. API エンドポイントを作成する
builder.Buildとapp.Run()の間に次のコードを挿入します。
app.MapGet("/", SendGreeting);
ファイルの一番下に次の関数を挿入:
async Task<string> SendGreeting(ILogger<Program> logger)
{
// Create a new Activity scoped to the method
using var activity = greeterActivitySource.StartActivity("GreeterActivity");
// Log a message
logger.LogInformation("Sending greeting");
// Increment the custom counter
countGreetings.Add(1);
// Add a tag to the Activity
activity?.SetTag("greeting", "Hello World!");
return "Hello World!";
}
注
エンドポイント定義では、OpenTelemetry に固有のものを使用しません。 監視のために .NET API を使用します。
8. Aspire ダッシュボード コンテナーを起動する
dockerを使用して、ダッシュボード コンテナーをダウンロードして実行します。
docker run --rm -it `
-p 18888:18888 `
-p 4317:18889 `
--name aspire-dashboard `
mcr.microsoft.com/dotnet/aspire-dashboard:latest
ダッシュボードに表示されるデータは機密性の高いものである場合があります。 既定では、ダッシュボードにはサインインするための認証トークンが必要です。 コンテナーは、このトークンを出力に表示します。
URL をコピーし、 0.0.0.0 を localhost ( http://localhost:18888/login?t=123456780abcdef123456780など) に置き換えて、ブラウザーで開きます。 または、サインイン ダイアログで /login?t= した後にキーを貼り付けます。 トークンは、コンテナーを開始するたびに変更されます。
9. プロジェクトを実行する
dotnet runを使用してプロジェクトを実行します。 コンソール出力には、アプリがリッスンする URL が表示されます。次に例を示します。
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5086
この記事の例とは異なる場合があるため、独自のコンソール出力に示されているポートを使用してください。 ブラウザーまたは curl を使用して、そのポートの API にアクセスします。
curl -k http://localhost:5086
ページをリクエストするたびに、挨拶の回数が増えていきます。
9.1 ログ出力
このコードでは、 ILoggerを使用してステートメントをログに記録します。 既定では、.NETコンソール プロバイダーが有効になり、コンソールに出力が送信されます。
.NET からログを外部送信する方法はいくつかあります:
-
Kubernetes などのコンテナー システムは、
stdoutとstderr出力をログ ファイルにリダイレクトします。 -
Serilog や NLog などの
ILoggerと統合されるログ ライブラリを使用します。 - OTLP などの OTel のログ プロバイダーを使用します。 手順 5 のコードのログセクションでは、OTel プロバイダーが追加されます。
ダッシュボードには、ログが構造化されたログとして表示されます。 ログ メッセージで設定したプロパティは、ログ レコードのフィールドになります。
9.2 メトリックビュー
Aspire ダッシュボードには、リソースごとにメトリックが表示されます。 リソースは、たとえばプロセスのようなテレメトリの発生元を指す、OTel の用語です。 リソースを選択すると、リソースが OTLP エンドポイントに送信した各メトリックがダッシュボードに一覧表示されます。 メトリックの一覧は動的であり、ダッシュボードが新しいメトリックを受信すると更新されます。
メトリック ビューは、使用するメトリックの種類によって異なります。
- ダッシュボードには、カウンターが直接表示されます。
- 要求ごとの値 (要求ごとに送信された期間やバイト数など) を追跡するヒストグラムの場合、ダッシュボードは値を一連のバケットに収集し、P50、P90、P99 パーセンタイルをグラフ化します。 ヒストグラムの結果には、エグザンプラ(各リクエストのトレース/スパン ID が付いた個々のデータポイント)を含めることができます。 ダッシュボードには、グラフ上にドットとして表示されます。 1 つを選択してそれぞれのトレースに移動し、その値の原因を確認できます。 この機能は、外れ値の診断に役立ちます。
- メトリックには、個々の値に関連付けられたキーと値のペアであるディメンションを含めることができます。 ダッシュボードでは、ディメンションごとの値が集計されます。 ビューのドロップダウンを使用して、
GET要求のみ、または ASP.NET 内の特定の URL ルートなど、特定のディメンションで結果をフィルター処理します。
9.3 トレースビュー
トレースビューにはトレースが表示されます。 各トレースは、同じトレース ID を共有するアクティビティのセットです。 スパンは作業を追跡し、各スパンは作業単位を表します。 ASP.NET 要求を処理すると、スパンが作成されます。 HttpClient 要求の実行はスパンです。 各スパンの親を追跡することで、視覚化できるスパンの階層を構築します。 各リソース (プロセス) からスパンを収集すると、一連のサービス全体の作業を追跡できます。 HTTP 要求には、トレース ID と親スパン ID を次のサービスに渡すヘッダーが含まれます。 各リソースはテレメトリを収集し、同じコレクターに送信する必要があります。これにより、スパンの階層が集計されて表示されます。
ダッシュボードには、概要情報を含むトレースの一覧が表示されます。 ダッシュボードは、新しいトレース ID を持つスパンを検出するたびに、テーブルに行を追加します。 トレース内のすべてのスパンを表示するには、[ 表示] を選択します。
スパンを選択すると、スパンのプロパティ (手順 7 で設定したgreeting タグなど) を含む詳細が表示されます。
.NET