レコメンデーションサービス

このサービスは、ユーザーが閲覧中の既存の商品 ID に基づいて、おすすめ商品のリストを取得する役割を担います。

レコメンデーションサービスのソースコード

計装

このサービスは、通信に Spring gRPC を使用する Spring Boot 4 アプリケーションです。 Java エージェントの代替として、OpenTelemetry Spring Boot スターターを使用して OpenTelemetry SDK を設定し、OpenTelemetry Bean として利用できるようにしています。 エクスポートエンドポイント、リソース属性、サービス名は、標準の OTEL_* 環境変数から取得されます。

Java エージェントは Spring Boot アプリケーションのデフォルトの選択肢であり、広告サービスで使用されています。 スターターがより適している場合については、スターターのページで説明されています。

implementation platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom:${opentelemetryInstrumentationVersion}")
implementation "io.opentelemetry.instrumentation:opentelemetry-spring-boot-starter"

トレース

gRPC スパン

スターターは gRPC を計装しないため、このサービスは gRPC 計装ライブラリを追加し、そのインターセプターを Spring gRPC のグローバルインターセプターとして登録しています。 これにより、ListRecommendations サーバースパンと ListProducts クライアントスパンが作成され、トレースコンテキストが商品カタログサービスに伝搬されます。

@Bean
GrpcTelemetry grpcTelemetry(OpenTelemetry openTelemetry) {
  return GrpcTelemetry.create(openTelemetry);
}

@Bean
@GlobalServerInterceptor
ServerInterceptor grpcTelemetryServerInterceptor(GrpcTelemetry grpcTelemetry) {
  return grpcTelemetry.createServerInterceptor();
}

@Bean
@GlobalClientInterceptor
ClientInterceptor grpcTelemetryClientInterceptor(GrpcTelemetry grpcTelemetry) {
  return grpcTelemetry.createClientInterceptor();
}

現在のスパンへの属性の追加

gRPC ハンドラー内では、現在のスパンはインターセプターによって作成されたサーバースパンです。 listRecommendations では、このスパンに属性が追加されます。

Span.current().setAttribute("demo.product.recommended.count", productIds.size());

新しいスパンの作成

このサービスは OpenTelemetry Bean から Tracer を取得します。 getProductList メソッドは spanBuilder で get_product_list スパンを作成し、makeCurrent でコンテキストに配置し、finally ブロックでスパンを終了します。 例外はスパンに記録され、スパンのステータスがエラーに設定されます。 レコメンドされた商品は文字列配列属性 demo.product.filtered.list として記録されます。

Tracer tracer = openTelemetry.getTracer("recommendation");

Span span = tracer.spanBuilder("get_product_list").startSpan();
try (Scope ignored = span.makeCurrent()) {
  ...
  span.setAttribute(FILTERED_LIST, recommended);
} catch (RuntimeException e) {
  span.recordException(e);
  span.setStatus(StatusCode.ERROR);
  throw e;
} finally {
  span.end();
}

メトリクス

メトリクスの初期化

このサービスは同じ OpenTelemetry Bean から Meter を取得し、カウンターを構築します。

LongCounter recommendations =
    openTelemetry
        .getMeter("recommendation")
        .counterBuilder("demo.recommendation.requests")
        .setDescription("Counts the total number of given recommendations")
        .setUnit("{recommendation}")
        .build();

リクエストごとに、レコメンドした商品の数が加算されます。

recommendations.add(productIds.size(), CATALOG_RECOMMENDATION);

現在生成されるメトリクス

以下のすべてのメトリクス名は、Prometheus/Grafana では . が _ に変換されて表示されます。

カスタムメトリクス

  • demo.recommendation.requests:レコメンドされた商品のカウンターで、recommendation.type 属性が catalog に設定されます。

自動計装メトリクス

ログ

このサービスは、Spring Boot のデフォルトである SLF4J と Logback を通じてログを記録します。 スターターが OpenTelemetry Logback アペンダーを自動的にインストールするため、サービス側でのログ設定は不要です。 ログレコードは、アクティブなスパンのトレース ID とスパン ID とともに OTLP 経由でエクスポートされます。

logger.info("Receive ListRecommendations for product ids:{}", productIds);