広告サービス

このサービスは、コンテキストキーに基づいてユーザーに表示する適切な広告を決定します。 広告はストアで販売されている商品に対するものです。

広告サービスのソースコード

自動計装

このサービスは、gRPC などのライブラリを自動的に計装し、OpenTelemetry SDK を設定するために、OpenTelemetry Java エージェントに依存しています。 エージェントは -javaagent コマンドライン引数を使用してプロセスに渡されます。 コマンドライン引数は DockerfileJAVA_TOOL_OPTIONS を通じて追加され、自動生成された Gradle 起動スクリプトで利用されます。

ENV JAVA_TOOL_OPTIONS=-javaagent:/app/opentelemetry-javaagent.jar

トレース

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

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

Span span = Span.current();

スパンへの属性の追加は、スパンオブジェクトの setAttribute を使用して行います。 getAds 関数では、スパンに複数の属性が追加されます。

span.setAttribute("app.ads.contextKeys", req.getContextKeysList().toString());
span.setAttribute("app.ads.contextKeys.count", req.getContextKeysCount());

スパンイベントの追加

スパンへのイベントの追加は、スパンオブジェクトの addEvent を使用して行います。 getAds 関数では、例外がキャッチされたときに属性付きのイベントが追加されます。

span.addEvent("Error", Attributes.of(AttributeKey.stringKey("exception.message"), e.getMessage()));

スパンステータスの設定

操作の結果がエラーの場合、スパンオブジェクトの setStatus を使用して、スパンステータスを適切に設定する必要があります。 getAds 関数では、例外がキャッチされたときにスパンステータスが設定されます。

span.setStatus(StatusCode.ERROR);

新しいスパンの作成

新しいスパンは Tracer.spanBuilder("spanName").startSpan() を使用して作成および開始できます。 新しく作成されたスパンは Span.makeCurrent() を使用してコンテキストに設定する必要があります。 getRandomAds 関数は、新しいスパンを作成し、コンテキストに設定し、操作を実行し、最後にスパンを終了します。

// 新しいスパンを手動で作成して開始する
Tracer tracer = GlobalOpenTelemetry.getTracer("ad");
Span span = tracer.spanBuilder("getRandomAds").startSpan();

// スパンをコンテキストに配置し、子スパンが開始された場合に親が適切に設定されるようにする
try (Scope ignored = span.makeCurrent()) {

  Collection<Ad> allAds = adsMap.values();
  for (int i = 0; i < MAX_ADS_TO_SERVE; i++) {
    ads.add(Iterables.get(allAds, random.nextInt(allAds.size())));
  }
  span.setAttribute("app.ads.count", ads.size());

} finally {
  span.end();
}

メトリクス

メトリクスの初期化

スパンの作成と同様に、メトリクスを作成する最初のステップは Meter インスタンスの初期化です。 たとえば GlobalOpenTelemetry.getMeter("ad") を使用します。 そこから、Meter インスタンスで利用可能なさまざまなビルダーメソッドを使用して、目的のメトリクス計装を作成します。 例:

meter
  .counterBuilder("app.ads.ad_requests")
  .setDescription("Counts ad requests by request and response type")
  .build();

OTel 以外のカスタムメトリクスの橋渡し(Prometheus クライアントライブラリ)

広告サービスは、OpenTelemetry SDK のかわりに Prometheus Java クライアントライブラリを使用して、少数のカスタムメトリクスも公開しています。 これらのメトリクスは別の HTTP エンドポイント(AD_PROMETHEUS_PORT/metrics、デフォルトは 9465)で公開され、OpenTelemetry Collector の prometheus レシーバーによってスクレイプされ、OTel SDK メトリクスと同じパイプラインに転送されます。

private static final Counter adsServedCounter =
    Counter.builder()
        .name("demo_ad_served_total")
        .help("Total number of ads served, labeled by category")
        .labelNames("category")
        .register();

HTTPServer prometheusServer =
    HTTPServer.builder().port(prometheusPort).buildAndStart();

これを接続する Collector の設定は次のとおりです。

receivers:
  prometheus/ad:
    config:
      scrape_configs:
        - job_name: ad
          scrape_interval: 10s
          static_configs:
            - targets: ['ad:${env:AD_PROMETHEUS_PORT}']

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

以下のメトリクス名はすべて、Prometheus/Grafana では . 文字が _ に変換されて表示されることに注意してください。

カスタムメトリクス

現在利用可能なカスタムメトリクスは以下のとおりです。

  • app.ads.ad_requests(OpenTelemetry SDK):広告リクエストのカウンターで、リクエストがコンテキストキーでターゲット指定されたかどうか、およびレスポンスがターゲット広告かランダム広告かを示すディメンションを持ちます。
  • demo_ad_served_total(Prometheus クライアントライブラリ、Collector によりスクレイプ):配信された広告のカウンターで、category(例:telescopesbinocularsrandom)でラベル付けされています。 上記の OTel 以外のカスタムメトリクスの橋渡しを参照してください。

自動計装メトリクス

アプリケーションで利用可能な自動計装メトリクスは以下のとおりです。

ログ

広告サービスは Log4J を使用しており、OTel Java エージェントによって自動的に設定されます。

ログレコードにトレースコンテキストが含まれるため、ログとトレースの相関が可能です。