Java でトレースと指標を生成する

このドキュメントでは、オープンソースの OpenTelemetry フレームワークを使用してトレースと指標データを収集するように Java アプリを変更する方法と、構造化 JSON ログを標準出力に出力する方法について説明します。このドキュメントでは、インストールして実行できる Java Spring Boot アプリのサンプルについても説明します。このアプリは、指標、トレース、ログを生成するように構成されています。この手順は、Spring Boot Framework を使用しているかどうかにかかわらず同じです。

始める前に

Cloud Logging API, Cloud Monitoring API, and Cloud Trace API API を有効にします。

API を有効にする

アプリを計測してトレース、指標、ログを収集する

アプリを計測して、トレースと指標データを収集し、構造化 JSON を標準出力に出力するには、このドキュメントの以降のセクションで説明する手順を実施します。

  1. OpenTelemetry Java エージェントを使用するようにアプリを構成する
  2. OpenTelemetry を構成する
  3. 構造化ロギングを構成する
  4. 構造化ログを書き込む

OpenTelemetry Java エージェントを使用するようにアプリを構成する

構造化ログを書き込むようにアプリを構成し、OpenTelemetry を使用して指標とトレースデータを収集するには、OpenTelemetry Java Agent を使用するようにアプリの呼び出しを更新します。このアプリの計測方法は、アプリコードを変更する必要がないことから、自動計測と呼ばれます。

次のコードサンプルは、OpenTelemetry Java Agent JAR ファイルをダウンロードして、-javaagent フラグを渡すようにコマンドライン呼び出しを更新する Dockerfile を示しています。

RUN wget -O /opentelemetry-javaagent.jar https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v1.31.0/opentelemetry-javaagent.jar
CMD sh -c "java -javaagent:/opentelemetry-javaagent.jar -cp app:app/lib/* com.example.demo.DemoApplication \
	2>&1 | tee /var/log/app.log"

また、JAVA_TOOL_OPTIONS 環境変数で -javaagent フラグを設定することもできます。

export JAVA_TOOL_OPTIONS="-javaagent:PATH/TO/opentelemetry-javaagent.jar"

OpenTelemetry を構成する

OpenTelemetry Java Agent のデフォルト構成では、OTLP プロトコルを使用してトレースと指標をエクスポートします。また、トレース コンテキストの伝播W3C トレース コンテキスト形式を使用するように OpenTelemetry を構成します。この構成により、トレース内でスパンが正しい親子関係を持つことが保証されます。

詳細と構成オプションについては、OpenTelemetry Java 自動計測をご覧ください。

構造化ロギングを構成する

標準出力に書き込まれる JSON 形式のログにトレース情報を含めるには、構造化ログを JSON 形式で出力するようにアプリを構成します。ロギングの実装として Logback を使用することをおすすめします。次のコードサンプルは、Logstash エンコーダを使用して JSON 構造化ログを出力するように構成された logback.xml ファイルを示しています。

<encoder class="net.logstash.logback.encoder.LogstashEncoder">
  <!-- Format JSON logs for the Logging agent
  https://cloud.google.com/logging/docs/structured-logging#special-payload-fields -->
  <provider class="net.logstash.logback.composite.loggingevent.LoggingEventPatternJsonProvider">
    <pattern>
      {
        "logging.googleapis.com/trace": "%mdc{trace_id}",
        "logging.googleapis.com/spanId": "%mdc{span_id}",
        "logging.googleapis.com/trace_sampled": "#asBoolean{%replace(%mdc{trace_flags}){'01', 'true'}}"
      }
    </pattern>
  </provider>

  <!-- Rename fields for the Logging agent -->
  <fieldNames>
    <level>severity</level>
    <timestamp>timestamp</timestamp>
    <levelValue>[ignore]</levelValue>
  </fieldNames>

  <!-- Exclude tracing MDC keys which are handled above -->
  <excludeMdcKeyName>trace_id</excludeMdcKeyName>
  <excludeMdcKeyName>span_id</excludeMdcKeyName>
  <excludeMdcKeyName>trace_flags</excludeMdcKeyName>
</encoder>

この構成では、SLF4J のマッピングされた診断コンテキストから、アクティブなスパンに関する情報が抽出され、その情報が属性としてログに追加されます。これらの属性を使用して、ログをトレースに関連付けることができます。

  • logging.googleapis.com/trace: ログエントリに関連付けられているトレースのリソース名。
  • logging.googleapis.com/spanId: ログエントリに関連付けられているトレースのスパン ID。
  • logging.googleapis.com/trace_sampled: このフィールドの値は true または false にする必要があります。

これらのフィールドの詳細については、LogEntry 構造体をご覧ください。

構造化ログを書き込む

トレースにリンクする構造化ログを書き込むには、SLF4J ロギング API を使用します。たとえば、次のステートメントは Logger.info() メソッドを呼び出す方法を示しています。

logger.info("handle /multi request with subRequests={}", subRequests);

OpenTelemetry Java エージェントは、OpenTelemetry Context で現在アクティブなスパンのスパン コンテキストを、SLF4J のマッピングされた診断コンテキストに自動的に挿入します。これは、構造化ロギングを構成するで説明されているように、JSON ログに含まれます。

テレメトリーを収集するように構成されたサンプルアプリを実行する

サンプルアプリでは、JSON ログ、OTLP 指標、トレース、Spring Boot Framework など、ベンダーに依存しない形式を使用しています。テレメトリーを Google Cloud にルーティングするため、このサンプルでは Google エクスポータで構成された OpenTelemetry Collector を使用します。このアプリには 2 つのエンドポイントがあります。

  1. /multi

    このエンドポイントは、handleMulti 関数によって処理されます。アプリの負荷生成ツールが /multi エンドポイントにリクエストを発行します。リクエストを受け取り、3~7 件のリクエストをローカル サーバーの /single エンドポイントに送信します。

    /**
     * handleMulti handles an http request by making 3-7 http requests to the /single endpoint.
     *
     * <p>OpenTelemetry instrumentation requires no changes here. It will automatically generate a
     * span for the controller body.
     */
    @GetMapping("/multi")
    public Mono<String> handleMulti() throws Exception {
      int subRequests = ThreadLocalRandom.current().nextInt(3, 8);
    
      // Write a structured log with the request context, which allows the log to
      // be linked with the trace for this request.
      logger.info("handle /multi request with subRequests={}", subRequests);
    
      // Make 3-7 http requests to the /single endpoint.
      return Flux.range(0, subRequests)
          .concatMap(
              i -> client.get().uri("http://localhost:8080/single").retrieve().bodyToMono(Void.class))
          .then(Mono.just("ok"));
    }
  2. /single

    このエンドポイントは、handleSingle 関数によって処理されます。少しの間スリープし、その後、文字列を返します。

    /**
     * handleSingle handles an http request by sleeping for 100-200 ms. It writes the number of
     * milliseconds slept as its response.
     *
     * <p>OpenTelemetry instrumentation requires no changes here. It will automatically generate a
     * span for the controller body.
     */
    @GetMapping("/single")
    public String handleSingle() throws InterruptedException {
      int sleepMillis = ThreadLocalRandom.current().nextInt(100, 200);
      logger.info("Going to sleep for {}", sleepMillis);
      Thread.sleep(sleepMillis);
      logger.info("Finishing the request");
      return String.format("slept %s\n", sleepMillis);
    }

アプリをダウンロードしてデプロイする

サンプルを実行するには、次の操作を行います。

  1. Google Cloud コンソールで、「Cloud Shell をアクティブにする」をクリックします。

    Cloud Shell をアクティブにする

    Google Cloud コンソールの下部で Cloud Shell セッションが開始し、コマンドライン プロンプトが表示されます。Cloud Shell はシェル環境です。Google Cloud CLI がすでにインストールされており、現在のプロジェクトの値もすでに設定されています。セッションが初期化されるまで数秒かかることがあります。

  2. リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/opentelemetry-operations-java
    
  3. サンプル ディレクトリに移動します。

    cd opentelemetry-operations-java/examples/instrumentation-quickstart
    
  4. サンプルをビルドして実行します。

    docker compose up --abort-on-container-exit
    

    Cloud Shell で実行していない場合は、認証情報ファイルを指す GOOGLE_APPLICATION_CREDENTIALS 環境変数を使用してアプリケーションを実行します。アプリケーションのデフォルト認証情報は、$HOME/.config/gcloud/application_default_credentials.json にある認証情報ファイルを提供します。

    # Set environment variables
    export GOOGLE_CLOUD_PROJECT="PROJECT_ID"
    export GOOGLE_APPLICATION_CREDENTIALS="$HOME/.config/gcloud/application_default_credentials.json"
    export USERID="$(id -u)"
    
    # Run
    docker compose -f docker-compose.yaml -f docker-compose.creds.yaml up --abort-on-container-exit
    

指標を表示する

サンプルアプリの OpenTelemetry 計測は、Metrics Explorer で表示可能な Prometheus 指標を生成します。

  • Prometheus/http_server_duration_milliseconds/histogram は、サーバー リクエストの所要時間を記録し、結果をヒストグラムに保存します。

  • Prometheus/http_client_duration_milliseconds/histogram は、クライアント リクエストの所要時間を記録し、結果をヒストグラムに保存します。

サンプルアプリによって生成された指標を表示する手順は次のとおりです。
  1. Google Cloud コンソールのナビゲーション パネルで [Monitoring] を選択し、次に [ Metrics Explorer] を選択します。

    Metrics Explorer に移動

  2. [指標] 要素の [指標を選択] メニューを展開してフィルタバーに「http_server」と入力し、サブメニューを使用して特定のリソースタイプと指標を選択します。
    1. [有効なリソース] メニューで、[Prometheus Target] を選択します。
    2. [有効な指標カテゴリ] メニューで、[Http] を選択します。
    3. [ACTIVE METRICS] メニューで指標を選択します。
    4. [適用] をクリックします。
  3. データの表示方法を構成します。

    指標の測定値が累積の場合、Metrics Explorer はアライメント期間ごとに測定データを自動的に正規化し、グラフに率を表示します。詳細については、種類、タイプ、変換をご覧ください。

    2 つの counter 指標など、integer 値または double 値が測定されると、Metrics Explorer はすべての時系列を自動的に合計します。HTTP ルート /multi/single のデータを表示するには、[集計] エントリの最初のメニューを [なし] に設定します。

    グラフの構成の詳細については、Metrics Explorer 使用時の指標の選択をご覧ください。

トレースを表示する

トレースデータを表示するには、次の操作を行います。

  1. Google Cloud コンソールのナビゲーション パネルで [トレース] を選択し、次に [Trace エクスプローラ] を選択します。

    [Trace エクスプローラ] に移動

  2. 散布図で、URI が /multi のトレースを選択します。
  3. [トレースの詳細] パネルのガントチャートで、/multi というラベルのスパンを選択します。

    パネルが開き、HTTP リクエストに関する情報が表示されます。詳細には、メソッド、ステータス コード、バイト数、呼び出し元のユーザー エージェントが含まれます。

  4. このトレースに関連付けられているログを表示するには、[ログとイベント] タブを選択します。

    このタブには、個々のログが表示されます。ログエントリの詳細を表示するには、ログエントリを開きます。[ログを表示] をクリックし、ログ エクスプローラを使用してログを表示することもできます。

Cloud Trace エクスプローラの使用方法について詳しくは、トレースを検索して調査するをご覧ください。

ログを表示する

ログ エクスプローラではログを調査できます。また、関連するトレース(存在する場合)を確認することもできます。

  1. Google Cloud コンソールのナビゲーション パネルで、[ロギング] を選択してから、[ログ エクスプローラ] を選択します。

    [ログ エクスプローラ] に移動

  2. handle /multi request の説明を含むログを見つけます。

    ログの詳細を表示するには、ログエントリを開きます。

  3. 「handle /multi request」メッセージを含むログエントリの [ トレース] をクリックし、[トレースの詳細表示] を選択します。

    [トレースの詳細] パネルが開き、選択したトレースが表示されます。

ログ エクスプローラの使用方法については、ログ エクスプローラを使用してログを表示するをご覧ください。

次のステップ