カートサービス

このサービスはユーザーがショッピングカートに入れた商品を管理します。 ショッピングカートデータへの高速アクセスのために Valkey キャッシュサービスと連携します。

カートサービスのソースコード

Note .NET 向け OpenTelemetry は、トレースとメトリクスに標準の OpenTelemetry API の代わりに System.Diagnostic.DiagnosticSource ライブラリを API として使用します。 ログには Microsoft.Extensions.Logging.Abstractions ライブラリが使用されます。

トレース

トレースの初期化

OpenTelemetry は .NET の依存性注入コンテナで設定されます。 AddOpenTelemetry() ビルダーメソッドを使用して、目的の計装ライブラリの設定、エクスポーターの追加、その他のオプションの設定を行います。 エクスポーターとリソース属性の設定は環境変数を通じて行われます。

Action<ResourceBuilder> appResourceBuilder =
    resource => resource
        .AddContainerDetector()
        .AddHostDetector();

builder.Services.AddOpenTelemetry()
    .ConfigureResource(appResourceBuilder)
    .WithTracing(tracerBuilder => tracerBuilder
        .AddSource("OpenTelemetry.Demo.Cart")
        .AddRedisInstrumentation(
            options => options.SetVerboseDatabaseStatements = true)
        .AddAspNetCoreInstrumentation()
        .AddGrpcClientInstrumentation()
        .AddHttpClientInstrumentation()
        .AddOtlpExporter());

自動計装されたスパンへの属性の追加

自動計装されたコードの実行中に、コンテキストから現在のスパン(アクティビティ)を取得できます。

var activity = Activity.Current;

スパン(アクティビティ)への属性(.NET ではタグ)の追加は、アクティビティオブジェクトの SetTag を使用して行います。 services/CartService.csAddItem 関数では、自動計装されたスパンにいくつかの属性が追加されます。

activity?.SetTag("app.user.id", request.UserId);
activity?.SetTag("app.product.quantity", request.Item.Quantity);
activity?.SetTag("app.product.id", request.Item.ProductId);

スパンイベントの追加

スパン(アクティビティ)イベントの追加は、アクティビティオブジェクトの AddEvent を使用して行います。 services/CartService.csGetCart 関数ではスパンイベントが追加されます。

activity?.AddEvent(new("Fetch cart"));

メトリクス

メトリクスの初期化

OpenTelemetry トレースの設定と同様に、.NET の依存性注入コンテナは AddOpenTelemetry() の呼び出しを必要とします。 このビルダーで目的の計装ライブラリやエクスポーターなどを設定します。

Action<ResourceBuilder> appResourceBuilder =
    resource => resource
        .AddContainerDetector()
        .AddHostDetector();

builder.Services.AddOpenTelemetry()
    .ConfigureResource(appResourceBuilder)
    .WithMetrics(meterBuilder => meterBuilder
        .AddMeter("OpenTelemetry.Demo.Cart")
        .AddProcessInstrumentation()
        .AddRuntimeInstrumentation()
        .AddAspNetCoreInstrumentation()
        .SetExemplarFilter(ExemplarFilterType.TraceBased)
        .AddOtlpExporter());

Exemplars

Exemplars は、カートサービスでトレースベースの Exemplar フィルターを使用して設定されます。 これにより、OpenTelemetry SDK がメトリクスに Exemplar を付与できるようになります。

まず CartActivitySourceMeter、および2つの Histogram を作成します。 ヒストグラムは AddItem メソッドと GetCart メソッドのレイテンシーを追跡します。 これらはカートサービスにおける2つの重要なメソッドです。

ユーザーがカートに商品を追加するときや、チェックアウトに進む前にカートを表示するときに長時間待たされるべきではないため、これらの2つのメソッドはカートサービスにとって重要です。

private static readonly ActivitySource CartActivitySource = new("OpenTelemetry.Demo.Cart");
private static readonly Meter CartMeter = new Meter("OpenTelemetry.Demo.Cart");
private static readonly Histogram<long> addItemHistogram = CartMeter.CreateHistogram<long>(
    "app.cart.add_item.latency",
    advice: new InstrumentAdvice<long>
    {
        HistogramBucketBoundaries = [ 500000, 600000, 700000, 800000, 900000, 1000000, 1100000 ]
    });
private static readonly Histogram<long> getCartHistogram = CartMeter.CreateHistogram<long>(
    "app.cart.get_cart.latency",
    advice: new InstrumentAdvice<long>
    {
        HistogramBucketBoundaries = [ 300000, 400000, 500000, 600000, 700000, 800000, 900000 ]
    });

カートサービスが返すマイクロ秒単位の結果にはデフォルト値が適合しないため、カスタムバケット境界も定義されていることに注意してください。

変数が定義されたら、各メソッドの実行レイテンシーは次のように StopWatch で追跡されます。

var stopwatch = Stopwatch.StartNew();

(method logic)

addItemHistogram.Record(stopwatch.ElapsedTicks);

すべてを結びつけるには、トレースパイプラインで作成したソースを追加する必要があります。 (上記のスニペットにすでに含まれていますが、参照のためにここに記載します):

.AddSource("OpenTelemetry.Demo.Cart")

そして、メトリクスパイプラインに MeterExemplarFilter を追加します。

.AddMeter("OpenTelemetry.Demo.Cart")
.SetExemplarFilter(ExemplarFilterType.TraceBased)

Exemplar を可視化するには、Grafana http://localhost:8080/grafana > Dashboards > Demo > Cart Service Exemplars に移動します。

Exemplar は95パーセンタイルチャート上に特別な「ダイヤモンド型のドット」として、またはヒートマップチャート上に小さな正方形として表示されます。 任意の Exemplar を選択するとそのデータが表示されます。 データには測定のタイムスタンプ、生の値、記録時のトレースコンテキストが含まれます。 trace_id を使用してトレーシングバックエンド(この場合は Jaeger)に移動できます。

Cart Service Exemplars

ログ

ログは .NET の依存性注入コンテナで LoggingBuilder レベルで AddOpenTelemetry() を呼び出すことにより設定されます。 このビルダーで目的のオプションやエクスポーターなどを設定します。

builder.Logging
    .AddOpenTelemetry(options => options.AddOtlpExporter());