OpenTracingの使用
このガイドでは、QuarkusアプリケーションがOpenTracingを利用してインタラクティブなウェブアプリケーションのための分散トレースを提供する方法について説明します。
前提条件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 11+ がインストールされ、
JAVA_HOME
が適切に設定されていること -
Apache Maven 3.8.1+
-
動作するコンテナランタイム(Docker, Podman)
-
使用したい場合、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
ソリューション
次のセクションで紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。ただし、すぐに完成した例に飛んでも構いません。
Gitレポジトリをクローンするか git clone https://github.com/quarkusio/quarkus-quickstarts.git
、 アーカイブ をダウンロードします。
ソリューションは opentracing-quickstart
ディレクトリ にあります。
Mavenプロジェクトの作成
まず、新しいプロジェクトが必要です。以下のコマンドで新規プロジェクトを作成します:
このコマンドはMaven プロジェクトを生成し、OpenTracingのサポートとデフォルトの Jaeger トレーサーを含む smallrye-opentracing
エクステンションをインポートします。
すでにQuarkusプロジェクトを設定されている場合は、プロジェクトのベースディレクトリーで以下のコマンドを実行することで、プロジェクトに smallrye-opentracing
エクステンションを追加することができます:
quarkus extension add 'smallrye-opentracing'
./mvnw quarkus:add-extension -Dextensions="smallrye-opentracing"
./gradlew addExtension --extensions="smallrye-opentracing"
これにより、ビルドファイルに以下の内容が追加されます:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-opentracing</artifactId>
</dependency>
implementation("io.quarkus:quarkus-smallrye-opentracing")
JAX-RSリソースの調査
以下の内容で src/main/java/org/acme/opentracing/TracedResource.java
ファイルを作成します:
package org.acme.opentracing;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jboss.logging.Logger;
@Path("/hello")
public class TracedResource {
private static final Logger LOG = Logger.getLogger(TracedResource.class);
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
LOG.info("hello"); (1)
return "hello";
}
}
1 | ログイベントは OpenTracing の情報も含んでいます。OpenTracingの情報をコンソール出力するためには、必要なOpenTracingイベントのキーを持つコンソールログハンドラを application.properties ファイルで定義する必要があります。 |
このアプリケーションにはトレース用のコードが含まれていないことに注意してください。デフォルトでは、このエンドポイントに送信されたリクエストは、コードを変更することなくトレースされます。トレース情報を拡張することも可能です。これは、 MicroProfile OpenTracing の実装である SmallRye OpenTracing で実現できます。
設定の作成
アプリケーション内でJaeger トレーサーを設定するには、2つの方法があります。
最初のアプローチは、 src/main/resources/application.properties
ファイル内でプロパティーを設定することです:
quarkus.jaeger.service-name=myservice (1)
quarkus.jaeger.sampler-type=const (2)
quarkus.jaeger.sampler-param=1 (3)
quarkus.log.console.format=%d{HH:mm:ss} %-5p traceId=%X{traceId}, parentId=%X{parentId}, spanId=%X{spanId}, sampled=%X{sampled} [%c{2.}] (%t) %s%e%n (4)
1 | quarkus.jaeger.service-name プロパティー (または JAEGER_SERVICE_NAME 環境変数) を指定しなかった場合は、"no-op" トレーサーが設定され、バックエンドにトレースデータは報告されなくなります。 |
2 | 定数サンプリングを行うサンプラーを設定します。 |
3 | すべてのリクエストをサンプリングします。すべてのリクエストをサンプリングしたくない場合は、sampler-param をに0から1の間の値を設定します (例: 0.50)。 |
4 | ログメッセージにトレースIDを追加します。 |
2つ目の方法は、プロパティを 環境変数 として指定する方法です。これらは、次のセクションに示すように jvm.args
として指定できます。
アプリケーションの実行
まず、トレースシステムを起動し、キャプチャしたトレースを収集・表示します:
docker run -p 5775:5775/udp -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 -p 16686:16686 -p 14268:14268 jaegertracing/all-in-one:latest
これでアプリケーションを実行する準備が整いました。もし、トレーサーの設定に application.properties
を使っている場合は次のようにします:
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
または、環境変数でトレーサーを設定する場合:
quarkus dev -Djvm.args="-DJAEGER_SERVICE_NAME=myservice -DJAEGER_SAMPLER_TYPE=const -DJAEGER_SAMPLER_PARAM=1"
./mvnw quarkus:dev -Djvm.args="-DJAEGER_SERVICE_NAME=myservice -DJAEGER_SAMPLER_TYPE=const -DJAEGER_SAMPLER_PARAM=1"
./gradlew --console=plain quarkusDev -Djvm.args="-DJAEGER_SERVICE_NAME=myservice -DJAEGER_SAMPLER_TYPE=const -DJAEGER_SAMPLER_PARAM=1"
アプリケーションとトレースシステムの両方が起動したら、提供されたエンドポイントにリクエストを行うことができます:
$ curl http://localhost:8080/hello
hello
最初のリクエストが送信されると、アプリ内のJaegerトレーサーが初期化されます:
2019-10-16 09:35:23,464 INFO [io.jae.Configuration] (executor-thread-1) Initialized tracer=JaegerTracer(version=Java-0.34.0, serviceName=myservice, reporter=RemoteReporter(sender=UdpSender(), closeEnqueueTimeout=1000), sampler=ConstSampler(decision=true, tags={sampler.type=const, sampler.param=true}), tags={hostname=localhost.localdomain, jaeger.version=Java-0.34.0, ip=127.0.0.1}, zipkinSharedRpcSpan=false, expandExceptionLogs=false, useTraceId128Bit=false)
13:20:11 INFO traceId=1336b2b0a76a96a3, parentId=0, spanId=1336b2b0a76a96a3, sampled=true [or.ac.qu.TracedResource] (executor-thread-63) hello
その後、 Jaeger UI にアクセスしてトレース情報を確認します。
CTRL+C
を押して、アプリケーションを停止します。
追加メソッドのトレース
REST エンドポイントは自動的にトレースされます。追加でメソッドをトレースする必要がある場合は、CDI beanのクラスや非privateのメソッドに org.eclipse.microprofile.opentracing.Traced
アノテーションを追加することができます。
これは、非RESTコール(メッセージからのリクエストなど)からの着信リクエストをトレースしたり、トレース内にスパンを作成したりするのに便利です。
ここでは、メソッドがトレースされている FrancophoneService
の例を示します。
import javax.enterprise.context.ApplicationScoped;
import org.eclipse.microprofile.opentracing.Traced;
@Traced
@ApplicationScoped
public class FrancophoneService {
public String bonjour() {
return "bonjour";
}
}
OpenTracingの機能をリアクティブなメッセージングベースのアプリケーションに追加する最良の方法は、すべての受信メソッドに Traced アノテーションを追加することです。
|
追加のInstrumentation
OpenTracing API Contributionsプロジェクト では、様々な技術/コンポーネントにトレースを追加するための追加の計器 (Instrumentation) を提供しています。
このセクションで説明されているInstrumentationは、Quarkusでテストされており、標準モードとネイティブモードの両方で動作します。
JDBC
JDBC Instrumentation は 、アプリケーションが実行するJDBCクエリごとにスパンを追加します。これを有効にするには、ビルドファイルに次の依存関係を追加します:
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-jdbc</artifactId>
</dependency>
implementation("io.opentracing.contrib:opentracing-jdbc")
Then, you need to enable it in the configuration:
quarkus.datasource.jdbc.tracing=true
quarkus.datasource.jdbc.tracing
is a build time configuration property: it makes sure all the tracing infrastructure is included in your application.
This is especially important when building a native executable as we need to make sure the OpenTracing JDBC driver has been registered for reflection, together with the underlying JDBC driver. |
The Agroal extension will take care of adjusting the JDBC URL with the tracing
prefix when tracing is enabled, so you do not have to adjust the JDBC URL yourself.
By default, when quarkus.datasource.jdbc.tracing
is true, tracing is enabled at runtime but you can explicitly disable it by setting the following property:
quarkus.datasource.jdbc.tracing.enabled=false
This way, you can have your Quarkus application ready for tracing and toggle JDBC tracing at runtime.
Kafka
Kafka instrumentation は、Kafka トピックとの間で送受信されるメッセージごとにスパンを追加します。これを有効にするには、ビルドファイルに以下の依存関係を追加します:
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-kafka-client</artifactId>
</dependency>
implementation("io.opentracing.contrib:opentracing-kafka-client")
KafkaのProducerとConsumerに登録する必要があるOpenTracingのインターセプターが含まれています。
Kafkaのガイド に従った場合、以下のように generated-price
と prices
のチャンネルにインターセプターを追加することができます:
# Configure the Kafka sink (we write to it)
mp.messaging.outgoing.generated-price.connector=smallrye-kafka
mp.messaging.outgoing.generated-price.topic=prices
mp.messaging.outgoing.generated-price.value.serializer=org.apache.kafka.common.serialization.IntegerSerializer
mp.messaging.outgoing.generated-price.interceptor.classes=io.opentracing.contrib.kafka.TracingProducerInterceptor
# Configure the Kafka source (we read from it)
mp.messaging.incoming.prices.connector=smallrye-kafka
mp.messaging.incoming.prices.value.deserializer=org.apache.kafka.common.serialization.IntegerDeserializer
mp.messaging.incoming.prices.interceptor.classes=io.opentracing.contrib.kafka.TracingConsumerInterceptor
interceptor.classes はカンマで区切られたクラスのリストを指定できます。
|
MongoDBクライアント
Mongo Driver instrumentation は 、アプリケーションが実行するコマンドごとにスパンを追加します。これを有効にするには、ビルドファイルに次の依存関係を追加します:
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-mongo-common</artifactId>
</dependency>
implementation("io.opentracing.contrib:opentracing-mongo-common")
これには、mongoクライアントの設定に登録されるOpenTracing CommandListenerが含まれています。 MongoDBのガイド に従い、以下のようにconfigプロパティを定義してコマンドリスナーを登録します:
# Enable tracing commands in mongodb client
quarkus.mongodb.tracing.enabled=true
Zipkin互換モード
これを有効にするには、ビルドファイルに以下の依存関係を追加します:
<dependency>
<groupId>io.jaegertracing</groupId>
<artifactId>jaeger-zipkin</artifactId>
</dependency>
implementation("io.jaegertracing:jaeger-zipkin")
これはリクエストを zipkin フォーマットに変換するための依存関係を含んでいます。 zipkin 互換モードは、以下のように config プロパティを定義した後に有効になります:
# Enable zipkin compatibility mode
quarkus.jaeger.zipkin.compatibility-mode=true
Jaeger構成リファレンス
ビルド時に固定される設定プロパティ - それ以外の設定プロパティは実行時に上書き可能
タイプ |
デフォルト |
|
---|---|---|
Defines if the Jaeger extension is enabled. Environment variable: |
boolean |
|
Whether metrics are published in case a metrics extension is present. Environment variable: |
boolean |
|
The traces endpoint, in case the client should connect directly to the Collector, like http://jaeger-collector:14268/api/traces Environment variable: |
||
Authentication Token to send as "Bearer" to the endpoint Environment variable: |
string |
|
Username to send as part of "Basic" authentication to the endpoint Environment variable: |
string |
|
Password to send as part of "Basic" authentication to the endpoint Environment variable: |
string |
|
The hostname and port for communicating with agent via UDP Environment variable: |
host:port |
|
Whether the reporter should also log the spans Environment variable: |
boolean |
|
The reporter’s maximum queue size Environment variable: |
int |
|
The reporter’s flush interval Environment variable: |
||
The sampler type (const, probabilistic, ratelimiting or remote) Environment variable: |
string |
|
The sampler parameter (number) Environment variable: |
||
The host name and port when using the remote controlled sampler Environment variable: |
host:port |
|
The service name Environment variable: |
string |
|
A comma separated list of name = value tracer level tags, which get added to all reported spans. The value can also refer to an environment variable using the format ${envVarName:default}, where the :default is optional, and identifies a value to be used if the environment variable cannot be found Environment variable: |
string |
|
Comma separated list of formats to use for propagating the trace context. Defaults to the standard Jaeger format. Valid values are jaeger and b3 Environment variable: |
string |
|
The sender factory class name Environment variable: |
string |
|
Whether the trace context should be logged. Environment variable: |
boolean |
|
Whether the registration of tracer as the global tracer should be disabled. This setting should only be turned on in tests that need to install a mock tracer. Environment variable: |
boolean |
|
Whether jaeger should run in zipkin compatibility mode Environment variable: |
boolean |
|
期間フォーマットについて
期間のフォーマットは標準の 数値で始まる期間の値を指定することもできます。この場合、値が数値のみで構成されている場合、コンバーターは値を秒として扱います。そうでない場合は、 |