14.9. MicroProfile OpenTracing

14.9.1. 概要

MicroProfile OpenTracing では、OpenTracing (https://opentracing.io/) のトレーサー実装を利用した、分散トレース機能を提供します。 本機能を有効化することにより、ソースコードに手を入れることなく、MicroProfile Rest Client アプリケーションや、JAX-RS アプリケーションに対するリクエストのトレース情報を採取することが可能です。 また、ソースコード上で、@Traced アノテーションや、OpenTracing API を利用することにより、トレース情報のカスタマイズが可能となります。

なお、本バージョンでサポートするトレーサー実装は、Jaeger (https://www.jaegertracing.io/) です。 Jaeger の詳細については、後述する [ Jaeger との連携 ] を参照してください。

Caution
トレース対象の JAX-RS アプリケーションには、web.xml を含めておく必要があります。

14.9.1.1. OpenTracing の概要

OpenTracing は、分散トレースのためのベンダ非依存の API とライブラリを提供する OSS です。 Java をはじめ、さまざまなプログラミング言語のライブラリが提供されており、WebOTX では、Java 言語用のライブラリを同梱しています。

OpenTracing を使った分散トレースでは、トレース (Trace) と、スパン (Span) という用語が使われます。それぞれの意味と、そのイメージは、次の通りです。

用語 説明
Trace 分散システムを通して実行されるひとつのトランザクション
Span 分散システム内で実行される、名前付きの作業単位

14.9.1.2. トレース情報採取のための準備

トレース情報を採取するためには、事前に、トレーサー実装である Jaeger のインストールや起動、WebOTX の MicroProfile OpenTracing 機能の有効化が必要となります。 事前準備の概要は、次の通りです。詳細は、各項目にリンクしている箇所をご覧ください。

  1. Jaeger のインストールと起動
    Jaeger の構成を決め、環境に適した形態の Jaeger をインストールします。詳細は、[ Jaeger との連携 > Jaeger の構成 ]、 [ Jaeger との連携 > Jaeger のインストール ] を参照してください。

    Memo
    Jaeger が起動していない場合、アプリケーション処理でエラーは発生しませんが、トレース情報の採取はできません。


  2. Jaeger Client ライブラリのインストール
    フルプロファイル環境の場合、次のスクリプトを実行することにより、Jaeger Client関連のライブラリをインストールします。 本手順は、WebOTX を停止した状態で実行してください。 WebOTX Uber JAR の場合は、[ Uber JAR への Jaeger Client ライブラリのインストール ] を参照してください。

    Memo
    フルプロファイル環境で、Jaeger Client ライブラリをアンインストールする場合は、WebOTX を停止した上で、引数に uninstall を指定してスクリプトを実行します。
    • Windowsの場合
      cd ${AS_INSTALL}/bin
      jaeger-tool.bat uninstall
      
    • Linuxの場合
      cd ${AS_INSTALL}/bin
      ./jaeger-tool.sh uninstall
      

  3. MicroProfile OpenTracing 機能の有効化

    Java VM システムプロパティ、あるいは、環境変数で、MicroProfile OpenTracing 機能の有効化のためのプロパティを設定します。

  4. Jaeger Client の設定
    WebOTX で、Jaeger Client に対する設定を行います。WebOTX とは別のホストで Jaeger を動作させている場合は、JAEGER_AGENT_HOST 等の設定が必要です。 また、トレース情報の採取は、性能にも影響します。どの程度の割合でトレース情報を採取するか、目的に応じたサンプラーの設定も必要となります。 設定項目の詳細は、[ Jaeger との連携 > Jaeger Client の設定項目 ] を参照してください。

  5. WebOTX の再起動
    上記設定の動作への反映のため、WebOTX を再起動します。

14.9.2. 設定情報

MicroProfile OpenTracing の設定項目は、[ リファレンス > 設定 > マイクロサービスアプリケーション > MicroProfile OpenTracing > MicroProfile OpenTracing 設定項目一覧 ] を参照してください。

14.9.3. 提供機能

MicroProfile OpenTracing 機能の有効化により、MicroProfile Rest Client アプリケーションや、JAX-RS アプリケーションに対するリクエスト単位でのトレース情報は、自動で採取可能になりますが、ここで説明する API を使うことによって、メソッド単位でのトレース有無の指定や、独自ログの追加等、トレース情報のカスタマイズが可能となります。

14.9.3.1. アノテーション

MicroProfile OpenTracing では、次のアノテーションを提供します。

名称 説明 アノテーション名
Traced トレース対象のクラス、または、メソッドを指定します。 @Traced
Traced

@Tracedアノテーションは、トレース対象のクラス、または、メソッドに対して指定します。 クラスに指定された場合、当該クラスのすべてのメソッドがトレース対象となります。 クラスとメソッドの両方に指定された場合は、メソッドに指定された方が優先されます。

@Tracedアノテーションで指定可能なパラメータは、次の通りです。

パラメータ 説明 既定値
value クラスレベルで false を指定した場合、クラス内のすべてのメソッドがトレース対象外となります。 メソッドレベルで false を指定した場合、そのメソッドはトレースから除外されます。 true
operationName スパンの名前を指定します。値が指定されていない場合、JAX-RS のエンドポイントに対しては、 <HTTP method>:<package name>.<class name>.<method name>、それ以外のメソッドの場合は、 <package name>.<class name>.<method name> の形式の名前となります。 クラスレベルで指定された場合は、メソッドレベルで個別の operationName が指定されていない限り、当該クラスの全てのメソッドに同じ名前が適用されます。 ""
14.9.3.2. MicroProfile OpenTracing API

MicroProfile OpenTracing では、アウトバウンドリクエストのトレース情報を採取するために、次の API を提供します。 使用例は、[ MicroProfile OpenTracing API の使用例 ] を、API の詳細は、MicroProfile Opentracing API 2.0 API を参照してください。

org.eclipse.microprofile.opentracing
クラス ClientTracingRegistrar
java.lang.Object
  └ org.eclipse.microprofile.opentracing.ClientTracingRegistrar

メソッドの概要
static javax.ws.rs.client.ClientBuilder configure(javax.ws.rs.client.ClientBuilder clientBuilder)
    トレースコンポーネントを ClientBuilder インスタンスに登録します。
static javax.ws.rs.client.ClientBuilder configure(javax.ws.rs.client.ClientBuilder clientBuilder, java.util.concurrent.ExecutorService executorService)
    クライアントに追加する ExecutorService を指定して、トレースコンポーネントを ClientBuilder インスタンスに登録します。
14.9.3.3. OpenTracing API

MicroProfile OpenTracing では、OpenTracing で提供されている API の利用が可能です。 この API を利用することで、任意のタイミングでのスパンの作成や、スパンへの情報追加が可能となり、さらに詳細な情報を採取することが可能です。 使用例は、[ OpenTracing API の使用例 ] を、各 API の詳細は、OpenTracing API 0.33.0 API を参照してください。

Memo
Maven でビルドする場合は、pom.xml に、次の依存関係の定義を追加してください。

  <dependency>
      <groupId>io.opentracing</groupId>
      <artifactId>opentracing-api</artifactId>
      <version>0.33.0</version>
   </dependency>

なお、OpenTracing API のバージョンは、動作環境の OpenTracing のバージョンに合わせてください。 本製品に含まれる OpenTracing のバージョンは、[ 注意制限事項 > 機能ごとの注意制限事項 > マイクロサービス > MicroProfile OpenTracing > 注意事項 > 同梱するOSSのバージョンについて ] を参照してください。


14.9.4. 記述例

ここでは、MicroProfile OpenTracing API や、OpenTracing API の使用例を示します。

14.9.4.1. @Tracer の使用例
import javax.ws.rs.Path;
import org.eclipse.microprofile.opentracing.Traced;

@Path("/foo")
@Traced // クラス内の全メソッドをトレース対象にする
public class Foo {
    public void foo() { // トレース対象
        ...
    }
    @Traced(value=false)
    public void bar() { // このメソッドはトレース対象外
        ...
    }
    @Traced(operationName="operationName.baz")
    public void baz() { // トレース対象で、スパンの名前を指定
        ...
    }
        ...
}
14.9.4.2. MicroProfile OpenTracing API の使用例

ここでは、ClientTracingRegistrar#configure() の使用例を示します。

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;

public class UserClient {
        :
    private static void addUser() {
                :
        Client client = ClientTracingRegistrar.configure(ClientBuilder.newBuilder()).build();
                :
    }
}
14.9.4.3. OpenTracing API の使用例

ここでは、OpenTracing API の使用例を示します。

使用例 1) 新たにスパンを生成して情報を採取する場合

例えば、メソッド内の一部の処理に対して、新たにスパンを生成することで、当該スパンの処理時間等を確認することが可能となります。

import javax.inject.Inject;
import io.opentracing.Span;
import io.opentracing.Tracer;

public class ServiceA {
    @Inject
    Tracer tracer;
    public void processA() {
            :
        // スパンの生成
        Span span = tracer.buildSpan("selectDB").start();
            :
        selectDB(); // DBアクセス(業務処理の一部分)
            :
        // スパンの終了
        span.finish();
            :
    }
}
使用例 2) 既にアクティブなスパンに対してログやタグを追加する場合
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import org.eclipse.microprofile.opentracing.Traced;
import io.opentracing.Tracer;

@Path("/foo")
@Traced
public class SomeResource {
    @Inject
    Tracer tracer;
    @GET
    public void foo() {
        tracer.activeSpan().setTag("tag", "foo"); // スパンに独自のタグを追加
        tracer.activeSpan().log("foo start.");    // スパンに独自のログを追加
            :
        tracer.activeSpan().log("foo end.");
    }
}

14.9.5. Jaeger との連携

ここでは、本バージョンでサポートしている OpenTracing のトレーサー実装である、Jaeger の概要と、その連携方法について説明します。

14.9.5.1. Jaeger の構成

一般的な Jaeger の構成は次の図の通りで、トレース情報の収集と解析を行うには、アプリケーション側に jaeger-client が必要となり、 さらに、jaeger-agent、jaeger-collector、jaeger-query のコンポーネントを動作させておく必要があります。

詳細な構成図は、Jaeger documentation - Components を参照してください。

各コンポーネントの概要は、次の通りです。

コンポーネント 説明
jaeger-client API を使用して、UDP 経由で jaeger-agent にスパン情報を送信します。jaeger-client は、プログラミング言語毎に提供されており、WebOTX では、Java 用のライブラリを同梱しています。
jaeger-agent すべてのホストにデプロイされ、jaeger-client から受信したスパン情報を jaeger-collector に送信するネットワークデーモンです。
jaeger-collector jaeger-agent から受信したデータの検証や、インデックス付与、変換等を行って、ストレージに保存します。 ストレージとしては、Cassandra、Elasticsearch、Kafka をサポートしています。 詳細は、Jaeger documentation - Storage Backends を参照してください。
jaeger-query ストレージからトレース情報を取得して、UI に表示します。

WebOTX で同梱している jaeger-client と、関連 OSS のバージョンの詳細は、[ 注意制限事項 > 機能ごとの注意制限事項 > マイクロサービス > MicroProfile OpenTracing > 注意事項 > 同梱するOSSのバージョンについて ] を参照してください。

Caution
アプリケーションで、独自に、これらの OSS を利用する場合は、本製品に同梱しているものと同じバージョン利用してください。

14.9.5.2. Jaeger のインストールと起動

Jaeger は、jaeger-agent や、jaeger-collector といったコンポーネントごとに、実行形式のバイナリ、Docker イメージ、Jaeger Operator 等の形態で提供されています。 また、jaeger-agent、jaeger-collector、インメモリストレージ、jaeger-query、Jaeger UI が一つにまとめられた、all-in-one と呼ばれるタイプのものも、各形態で提供されています。
なお、OpenShift で Service Mesh をインストールする場合には、その中で、Red Hat が提供する、Jaeger Operator を使ってインストールする必要があります。 環境に応じて、適切な提供形態のものを使ってインストールしてください。

Memo
all-in-one は、ローカルテスト等、簡単な動作確認での利用が想定されたものです。本番環境では、jaeger-agent、jaeger-collector 等のコンポーネントを個別に起動し、また、採取したトレース情報を永続化するために、外部ストレージとの連携設定も必要になります。詳細については、Jaeger documentation - Deployment を参照してください。


ここでは、all-in-one の実行形式のバイナリ、および、Docker イメージを使った、Jaeger の起動方法を説明します。

実行形式のバイナリを使った Jaeger の起動
  1. Jaeger のダウンロードページ (https://www.jaegertracing.io/download/) より、対象の環境に適したバイナリをダウンロードします。

  2. 次のコマンドで、Jaeger を起動します。指定可能なオプションは、jaeger-all-in-one --help で確認できます。
    jaeger-all-in-one
Docker イメージを使った Jaeger の起動

Docker Hub に公開されているイメージを使って起動します。引数のポート番号の詳細は、Jaeger documentation - Deployment を参照してください。

docker run -d --name jaeger \
  -p 5775:5775/udp \
  -p 6831:6831/udp \
  -p 6832:6832/udp \
  -p 5778:5778 \
  -p 16686:16686 \
  -p 14268:14268 \
  -p 14250:14250 \
  -p 9411:9411 \
  jaegertracing/all-in-one:1.31
14.9.5.3. Jaeger Client の設定項目
Jaeger Client の設定項目は、[ リファレンス > 設定 > マイクロサービスアプリケーション > MicroProfile OpenTracing > Jaeger Client 設定項目一覧 ] を参照してください。
14.9.5.4. Jaeger UI でのトレース情報の参照

ここでは、Jaeger UI を使ったトレース情報の参照方法について説明します。 Jaeger UI の設定等、詳細については、Jaeger documentation - Frontend/UI Configuration を参照してください。

MicroProfile OpenTracing 機能を有効にした状態で、アプリケーションへのリクエスト送信後、ブラウザから Jaeger UI にアクセスします。 例えば、[ 実行形式のバイナリを使った Jaeger の起動 ] に記載の方法で Jaeger を起動したホストにおいて、Jaeger UI にアクセスする場合の URL は、http://localhost:16686 となります。

「Service」欄で、サービス名を選択し、左下の「Find Traces」ボタンをクリックします。サービス名は、JAEGER_SERVICE_NAME に指定した値で、既定値は、jaegerservice です。

その時点で採取されているトレース情報が表示されます。この一覧では、リクエストの処理時間、スパンの数や、呼び出されたサービスを確認できます。

あるスパンを選択することで、その詳細が表示されます。スパンに設定されているタグや、ログ等を確認できます。

14.9.6. Uber JAR への Jaeger Client ライブラリのインストール

WebOTX Uber JAR で、MicroProfile OpenTracing 機能を有効化する際の、Jaeger Client ライブラリのインストール方法について説明します。

ここでは、[ マイクロサービスプロファイルを使用したWebOTX Uber JARの作成 ] の手順に従って作成されたMavenプロジェクト (WebOTXマイクロサービスMavenアーキタイプバージョン 11.1 以降) のpom.xmlあることを前提に説明しています。

  1. インストールメディアに含まれる次のファイルを、pom.xmlから参照可能な任意の場所に展開します。
  2. pom.xml の<jaeger-client-path>の記述を有効に (<!-- と --> を削除) して、"jaeger-client-1.4.0"の部分を、前の手順でファイルを展開したディレクトリに変更します。
    <jaeger-client-path>jaeger-client-1.4.0</jaeger-client-path>
    
  3. pom.xml の、ms-uberjar-maven-plugin の<configration>定義に記載されている、<deployFiles>の内容を有効に (<!-- と --> を削除) にします。
    この状態でビルドすることにより、WebOTX Uber JAR 内に Jaeger Client のライブラリが配置されます。
    <configuration>
        <deployFiles>
            <deployInfo>
              <src>${jaeger-client-path}/annotations-13.0.jar</src>
              <dst>WebOTX/lib/annotations-13.0.jar</dst>
            </deployInfo>
            <deployInfo>
              <src>${jaeger-client-path}/gson-2.8.6.jar</src>
              <dst>WebOTX/lib/gson-2.8.6.jar</dst>
            </deployInfo>
            <deployInfo>
              <src>${jaeger-client-path}/jaeger-client-1.4.0.jar</src>
              <dst>WebOTX/lib/jaeger-client-1.4.0.jar</dst>
            </deployInfo>
            <deployInfo>
              <src>${jaeger-client-path}/jaeger-core-1.4.0.jar</src>
              <dst>WebOTX/lib/jaeger-core-1.4.0.jar</dst>
            </deployInfo>
            <deployInfo>
              <src>${jaeger-client-path}/jaeger-thrift-1.4.0.jar</src>
              <dst>WebOTX/lib/jaeger-thrift-1.4.0.jar</dst>
            </deployInfo>
            <deployInfo>
              <src>${jaeger-client-path}/jaeger-tracerresolver-1.4.0.jar</src>
              <dst>WebOTX/lib/jaeger-tracerresolver-1.4.0.jar</dst>
            </deployInfo>
            <deployInfo>
              <src>${jaeger-client-path}/kotlin-stdlib-1.3.50.jar</src>
              <dst>WebOTX/lib/kotlin-stdlib-1.3.50.jar</dst>
            </deployInfo>
            <deployInfo>
              <src>${jaeger-client-path}/kotlin-stdlib-common-1.3.50.jar</src>
              <dst>WebOTX/lib/kotlin-stdlib-common-1.3.50.jar</dst>
            </deployInfo>
            <deployInfo>
              <src>${jaeger-client-path}/libthrift-0.13.0.jar</src>
              <dst>WebOTX/lib/libthrift-0.13.0.jar</dst>
            </deployInfo>
            <deployInfo>
              <src>${jaeger-client-path}/okhttp-4.2.2.jar</src>
              <dst>WebOTX/lib/okhttp-4.2.2.jar</dst>
            </deployInfo>
            <deployInfo>
              <src>${jaeger-client-path}/okio-2.2.2.jar</src>
              <dst>WebOTX/lib/okio-2.2.2.jar</dst>
            </deployInfo>
            <deployInfo>
              <src>${jaeger-client-path}/slf4j-api-1.7.28.jar</src>
              <dst>WebOTX/lib/slf4j-api-1.7.28.jar</dst>
            </deployInfo>
            <deployInfo>
              <src>${jaeger-client-path}/slf4j-simple-1.7.28.jar</src>
              <dst>WebOTX/lib/slf4j-simple-1.7.28.jar</dst>
            </deployInfo>
        </deployFiles>
    </configuration>
    

14.9.7. サンプルの実行

ここでは、MicroProfile OpenTracing のサンプルアプリケーションを実行し、そのトレース情報を確認する手順について説明します。
サンプルアプリケーションを実行する前に、[ Jaeger のインストールと起動 ] を参考に、Jaeger をインストールし、起動しておいてください。

(1) WebOTX Developer へのインポート
サンプルプロジェクトの zip ファイルを展開して、WebOTX Developer にインポートしてください。

(2) MicroProfile OpenTracing API / OpenTracing API を利用する JAX-RS アプリケーションの作成
OpenTracing 関連の API を利用して、JAX-RS アプリケーションを作成します。サンプルプロジェクトに含まれるクラスの概要は、次の通りです。

クラス名 処理概要
TracedTest @Traced アノテーションを利用して、トレース採取可否定や、スパン名の指定を行っています。後述の OpenTracingResource クラスから呼び出します。
UserClient MicroProfile OpenTracing API を利用して、アウトバウンドリクエストに対するトレース情報を採取できるようにします。 このクラスから、同じ war に含まれる、JAX-RS アプリケーション (/helloworld) へリクエストを送信します。
OpenTracingResource OpenTracing API を利用して、スパンの新規作成や、既存のスパンに対してログやタグの追加を行います。

(3) プロジェクトのビルド
WebOTX Developer のメニュー「プロジェクト」で「自動的にビルド」がチェックされていない場合は、「プロジェクトのビルド」を選択し、ビルドを行います。

(4) warファイルのエクスポート
プロジェクトを右クリックして、「エクスポート」−「WAR ファイル」を選択します。 「Destination」で出力先のパスを指定し、「終了」ボタンをクリックします。

(5) JAX-RS アプリケーションの配備
対象の環境に合わせて、アプリケーションを配備します。

コンテナ環境の場合は、[ 構築・運用 > コンテナ型仮想化 ] を参考に、本サンプルアプリケーションを含めたコンテナイメージを作成して、コンテナを起動してください。

コンテナ環境でない場合は、[ 配備 > アプリケーション配備 > 配備・再配備・置換 > 配備・再配備 ] を参考に、配備してください。
例) エージェントプロセス上に配備する場合

otxadmin> deploy OpenTracingSample.war
Memo

(6) JAX-RS アプリケーションの実行
ブラウザ等から、各サンプルに対するリクエストを送信します。接続先ホスト名、ポート番号は、環境に合わせて変更してください。

(7) トレース情報の参照
ブラウザから、Jaeger UI にアクセスし、トレース情報を確認します。Jaeger が動作しているホストでアクセスする場合の既定の URL は次の通りです。

http://localhost:16686

トレース情報の確認方法は、[ Jaeger UI でのトレース情報の参照 ] を参照してください。