The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

OpenTelemetryの使用

このガイドでは、Quarkusアプリケーションが OpenTelemetryを利用して、インタラクティブなウェブアプリケーションに分散トレーシングを提供する方法を説明します。

前提条件

このガイドを完成させるには、以下が必要です:

  • 約15分

  • IDE

  • JDK 11+ がインストールされ、 JAVA_HOME が適切に設定されていること

  • Apache Maven 3.8.6

  • Docker と Docker Compose、または Podman 、および Docker Compose

  • 使用したい場合は、 Quarkus CLI

  • ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること

アーキテクチャ

このガイドでは、分散トレースを実証するための簡単なRESTアプリケーションを作成します。

ソリューション

次の章で紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。ただし、すぐに完成した例に飛んでも構いません。

Gitレポジトリをクローンするか git clone https://github.com/quarkusio/quarkus-quickstarts.gitアーカイブ をダウンロードします。

このソリューションは、 opentelemetry-quickstart ディレクトリにあります。

Mavenプロジェクトの作成

まず、新しいプロジェクトが必要です。以下のコマンドで新規プロジェクトを作成します。

コマンドラインインタフェース
quarkus create app org.acme:opentelemetry-quickstart \
    --stream=2.16 \
    --extension='resteasy-reactive,quarkus-opentelemetry' \
    --no-code
cd opentelemetry-quickstart

Gradleプロジェクトを作成するには、 --gradle または --gradle-kotlin-dsl オプションを追加します。

Quarkus CLIのインストール方法や使用方法については、 Quarkus CLIガイド を参照してください。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:2.16.12.Final:create \
    -DplatformVersion=2.16 \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=opentelemetry-quickstart \
    -Dextensions='resteasy-reactive,quarkus-opentelemetry' \
    -DnoCode
cd opentelemetry-quickstart

Gradleプロジェクトを作成するには、 -DbuildTool=gradle または -DbuildTool=gradle-kotlin-dsl オプションを追加します。

このコマンドはMavenプロジェクトを生成し、 quarkus-opentelemetry エクステンションをインポートします。このエクステンションには、デフォルトのOpenTelemetryサポートと、 OTLPのgRPC spanエクスポーターが含まれています。

Quarkusプロジェクトがすでに設定されている場合、プロジェクトのベースディレクトリで次のコマンドを実行することで、 quarkus-opentelemetry エクステンションをプロジェクトに追加できます:

コマンドラインインタフェース
quarkus extension add 'opentelemetry'
Maven
./mvnw quarkus:add-extension -Dextensions='opentelemetry'
Gradle
./gradlew addExtension --extensions='opentelemetry'

これにより、 pom.xml に以下が追加されます:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-opentelemetry</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-opentelemetry")

JAX-RSのリソース調査

src/main/java/org/acme/opentelemetry/TracedResource.java のファイルを開くと、以下の内容が表示されます。

package org.acme.opentelemetry;

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");
        return "hello";
    }
}

このアプリケーションには、トレースのためのコードが含まれていないことに注意してください。デフォルトでは、このエンドポイントに送信されたリクエストは、コードの変更を必要とせずにトレースされます。

コンフィグレーションの作成

アプリケーション内でOTLP gRPC エクスポーターを設定するには2つの方法があります。

最初のアプローチは、 src/main/resources/application.properties ファイル内でプロパティーを提供することです。

quarkus.application.name=myservice (1)
quarkus.opentelemetry.enabled=true (2)
quarkus.opentelemetry.tracer.exporter.otlp.endpoint=http://localhost:4317 (3)

quarkus.opentelemetry.tracer.exporter.otlp.headers=Authorization=Bearer my_secret (4)

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  (5)

# Alternative to the console log
quarkus.http.access-log.pattern="...traceId=%{X,traceId} spanId=%{X,spanId}" (6)
1 このアプリケーションから作成されたすべてのスパンには、そのスパンが myservice アプリケーションによって作成されたことを示す OpenTelemetry Resource が含まれます。設定されていない場合は、デフォルトでアーティファクトIDが設定されます。
2 OpenTelemetryを有効にするかどうか。デフォルトは true ですが、ここでは無効にできることを示しています。
3 スパンを送信するためのgRPCエンドポイント
4 認証によく使われるオプションのgRPCヘッダー
5 ログメッセージにトレース情報を追加します。
6 また、アクセスログにのみトレース情報を記載することもできます。この場合、コンソールログ形式の情報を省略する必要があります。

アプリケーションの実行

最初のステップは、テレメトリデータを受信して処理し、キャプチャしたトレースを表示する Jaegerにエクスポートするための OpenTelemetry Collectorの設定と起動です。

Jaegerはバージョン1.35以降、OTelプロトコルをサポートしています。この場合、コレクターをインストールする必要はなく、トレースデータを直接Jaegerに送ることができます(OTLPレシーバーを有効にした後、この ブログエントリ を参照してください)。

otel-collector-config.yaml ファイルを作成して OpenTelemetry Collector を設定します。

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: otel-collector:4317

exporters:
  jaeger:
    endpoint: jaeger-all-in-one:14250
    tls:
      insecure: true

processors:
  batch:

extensions:
  health_check:

service:
  extensions: [health_check]
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [jaeger]

docker-compose up -d OpenTelemetry CollectorとJaegerシステムを、以下の docker-compose.yml ファイルを介して起動します。

version: "2"
services:

  # Jaeger
  jaeger-all-in-one:
    image: jaegertracing/all-in-one:latest
    ports:
      - "16686:16686"
      - "14268:14268"
      - "14250:14250"
  # Collector
  otel-collector:
    image: otel/opentelemetry-collector:latest
    command: ["--config=/etc/otel-collector-config.yaml"]
    volumes:
      - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml:Z
    ports:
      - "13133:13133" # Health_check extension
      - "4317:4317"   # OTLP gRPC receiver
    depends_on:
      - jaeger-all-in-one

これでアプリケーションを実行する準備が整いました。トレーサーの設定に application.properties を使用している場合:

コマンドラインインタフェース
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

または、JVM引数でOTLP gRPCエンドポイントを設定する場合:

コマンドラインインタフェース
quarkus dev -Djvm.args="-Dquarkus.opentelemetry.tracer.exporter.otlp.endpoint=http://localhost:4317"
Maven
./mvnw quarkus:dev -Djvm.args="-Dquarkus.opentelemetry.tracer.exporter.otlp.endpoint=http://localhost:4317"
Gradle
./gradlew --console=plain quarkusDev -Djvm.args="-Dquarkus.opentelemetry.tracer.exporter.otlp.endpoint=http://localhost:4317"

OpenTelemetry Collector、Jaegerシステム、アプリケーションが動作している状態で、提供されているエンドポイントにリクエストを出すことができます。

$ curl http://localhost:8080/hello
hello

最初のリクエストが送信された時点で、ログにトレース情報が表示されるようになります:

10:49:02 INFO  traceId=, parentId=, spanId=, sampled= [io.quarkus] (main) Installed features: [cdi, opentelemetry, rest-client, resteasy, smallrye-context-propagation, vertx]
10:49:03 INFO  traceId=17ceb8429b9f25b0b879fa1503259456, parentId=3125c8bee75b7ad6, spanId=58ce77c86dd23457, sampled=true [or.ac.op.TracedResource] (executor-thread-1) hello
10:49:03 INFO  traceId=ad23acd6d9a4ed3d1de07866a52fa2df, parentId=, spanId=df13f5b45cf4d1e2, sampled=true [or.ac.op.TracedResource] (executor-thread-0) hello

その後、 Jaeger UI にアクセスしてトレース情報を確認します。

CTRL+C を叩いてアプリケーションを停止させます。

JDBC

JDBCインスツルメンテーションは、アプリケーションによって実行される各JDBCクエリのためにスパンを追加します。これを有効にするには、次の依存関係をビルドファイルに追加します。

pom.xml
<dependency>
    <groupId>io.opentelemetry.instrumentation</groupId>
    <artifactId>opentelemetry-jdbc</artifactId>
</dependency>
build.gradle
implementation("io.opentelemetry.instrumentation:opentelemetry-jdbc")

専用のJDBCドライバを使用するため、データソースとHibernate ORMがそれを使用するように設定する必要があります。

quarkus.datasource.db-kind=postgresql
# add ':otel' to your database URL
quarkus.datasource.jdbc.url=jdbc:otel:postgresql://localhost:5432/mydatabase
# use the 'OpenTelemetryDriver' instead of the one for your database
quarkus.datasource.jdbc.driver=io.opentelemetry.instrumentation.jdbc.OpenTelemetryDriver

追加設定

一部のユースケースでは、OpenTelemetryのカスタム設定が必要になります。 これらのセクションでは、適切に構成するために必要なものについて概説します。

IDジェネレーター

OpenTelemetry エクステンションでは、トレースおよびスパンの識別子を作成する際に、デフォルトでランダムな ID ジェネレーターを使用します。

ベンダー固有のプロトコルの中には、カスタム ID ジェネレーターを必要とするものがありますが、プロデューサーを作成することで、デフォルトの ID ジェネレーターを上書きすることができます。OpenTelemetryエクステンションは、 IdGenerator CDI Beanを検出し、トレーサープロデューサーを構成する際にそれを使用します。

@Singleton
public class CustomConfiguration {

    /** Creates a custom IdGenerator for OpenTelemetry */
    @Produces
    @Singleton
    public IdGenerator idGenerator() {
        return AwsXrayIdGenerator.getInstance();
    }
}

プロパゲーター

OpenTelemetry は、 プロパゲーター を介して分野横断的な関心事を伝播し、状態を保存するための基になる"コンテキスト"を共有します 分散トランザクションの存続期間全体にわたってデータにアクセスします。

デフォルトでは、OpenTelemetryエクステンションは、 W3C Trace ContextW3C Baggageプロパゲータを有効にしていますが、 設定リファレンスで説明されている propagators 設定を設定することで、サポートされているOpenTelemetryプロパゲータのいずれかを選択することができます。

b3, b3multi, jaeger, ottrace のプロパゲータは、プロジェクトに trace-propagatorsエクステンションを依存関係として追加する必要があります。

pom.xml
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-extension-trace-propagators</artifactId>
</dependency>
build.gradle
implementation("io.opentelemetry:opentelemetry-extension-trace-propagators")

xray プロパゲータは、 awsエクステンションをプロジェクトに依存関係として追加する必要があります。

pom.xml
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-extension-aws</artifactId>
</dependency>
build.gradle
implementation("io.opentelemetry:opentelemetry-extension-aws")

リソース

リソースは、テレメトリを生成しているエンティティの表現であり、誰がトレースを生成しているかを特徴づけるために、エクスポートされたトレースに属性を追加します。

設定リファレンス に記述されている resource-attributes トレーサーの設定を行うことで属性を追加することができます。 このプロパティは実行時にオーバーライドできるので、OpenTelemetry 拡張は Quarkus 設定リファレンス に記述されている優先順位に従ってその値を取得します。

カスタムリソースや OpenTelemetry SDK Extensionsで提供されているリソースを使用する必要がある場合は、複数のリソースプロデューサーを作成することができます。OpenTelemetryエクステンションは、 Resource CDI Beanを検出し、トレーサー・プロデューサーを構成する際にそれらをマージします。

@ApplicationScoped
public class CustomConfiguration {

    @Produces
    @ApplicationScoped
    public Resource osResource() {
        return OsResource.get();
    }

    @Produces
    @ApplicationScoped
    public Resource ecsResource() {
        return EcsResource.get();
    }
}

サンプラー

サンプラーは、トレースをサンプリングしてエクスポートするかどうかを決定し、収集してコレクターに送信するトレースのサンプル数を減らすことで、ノイズやオーバーヘッドを制御します。

内蔵サンプラーの設定は、 [configuration-reference]に記載されている希望のサンプラー設定を設定するだけで可能です。

カスタムサンプラーを使用する必要がある場合や、 OpenTelemetry SDK Extensionsの1つが提供するサンプラーを使用する必要がある場合は、サンプラー・プロデューサーを作成することができます。OpenTelemetryエクステンションは、 Sampler CDI Beanを検出し、トレーサープロデューサーを構成する際にそれを使用します。

@Singleton
public class CustomConfiguration {

    /** Creates a custom sampler for OpenTelemetry */
    @Produces
    @Singleton
    public Sampler sampler() {
        return JaegerRemoteSampler.builder()
        .setServiceName("my-service")
        .build();
    }
}

追加の計器

Quarkusエクステンションの中には、トレースが後続の実行に伝搬されることを保証するために追加のコードを必要とするものがあります。これらのセクションでは、プロセスの境界を越えてトレースを伝搬するために必要なことを説明します。

このセクションで説明されている計器は、Quarkusでテストされており、標準モードとネイティブモードの両方で動作します。

CDI

CDI を意識した Bean のメソッドに io.opentelemetry.extension.annotations.WithSpan というアノテーションを付けると、新しい Span が作成され、現在の Trace コンテキストと必要な関係が確立されます。

メソッドパラメータには、 io.opentelemetry.extension.annotations.SpanAttribute アノテーションを付けて、どのメソッドパラメータが Trace の一部となるべきかを示すことができます。

例:

@ApplicationScoped
class SpanBean {
    @WithSpan
    void span() {

    }

    @WithSpan("name")
    void spanName() {

    }

    @WithSpan(kind = SERVER)
    void spanKind() {

    }

    @WithSpan
    void spanArgs(@SpanAttribute(value = "arg") String arg) {

    }
}

使用可能なOpenTelemetry CDI依存関係注入

MicroProfile Telemetry Tracingの仕様に基づき、Quarkusは以下のクラスのCDI依存関係注入をサポートしています。

  • io.opentelemetry.api.OpenTelemetry

  • io.opentelemetry.api.trace.Tracer

  • io.opentelemetry.api.trace.Span

  • io.opentelemetry.api.baggage.Baggage

これらのクラスは、CDIが有効なBeanに注入することができます。例えば、 Tracer は、カスタムスパンを開始するために特に有用です。

@Inject
Tracer tracer;

...

public void tracedWork() {
    Span span = tracer.spanBuilder("My custom span")
        .setAttribute("attr", "attr.value")
        .setParent(Context.current().with(Span.current()))
        .setSpanKind(SpanKind.INTERNAL)
        .startSpan();

    // traced work

    span.end();
}

SmallRye Reactive Messaging - Kafka

SmallRye Reactive Messaging extension for Kafkaを使用すると、スパンをKafka Recordに伝搬させることができます。

TracingMetadata tm = TracingMetadata.withPrevious(Context.current());
Message out = Message.of(...).withMetadata(tm);

上記は、生成されている Message に追加できる TracingMetadata オブジェクトを作成し、OpenTelemetry Context を取得して、伝播のために現在のスパンを抽出しています。

エクスポーター

Quarkus OpenTelemetryのデフォルトは、OpenTelemetryで定義されている標準的なOTLPエクスポーターです。

追加のエクスポーターは、Quarkiverseの quarkus-opentelemetry-exporter プロジェクトで利用できるようになる予定です。

OpenTelemetry 設定リファレンス

ビルド時に固定される設定プロパティ - 他のすべての設定プロパティは実行時にオーバーライド可能

Configuration property

タイプ

デフォルト

OpenTelemetry support. OpenTelemetry support is enabled by default.

Environment variable: QUARKUS_OPENTELEMETRY_ENABLED

Show more

boolean

true

Comma separated list of OpenTelemetry propagators which must be supported. Valid values are b3, b3multi, baggage, jaeger, ottrace, tracecontext, xray. Default value is traceContext,baggage.

Environment variable: QUARKUS_OPENTELEMETRY_PROPAGATORS

Show more

文字列のリスト

tracecontext,baggage

Support for tracing with OpenTelemetry. Support for tracing will be enabled if OpenTelemetry support is enabled and either this value is true, or this value is unset.

Environment variable: QUARKUS_OPENTELEMETRY_TRACER_ENABLED

Show more

boolean

A comma separated list of name=value resource attributes that represents the entity producing telemetry (eg. service.name=authservice).

Environment variable: QUARKUS_OPENTELEMETRY_TRACER_RESOURCE_ATTRIBUTES

Show more

文字列のリスト

The sampler to use for tracing. Valid values are off, on, ratio. Defaults to on.

Environment variable: QUARKUS_OPENTELEMETRY_TRACER_SAMPLER

Show more

string

on

Environment variable: QUARKUS_OPENTELEMETRY_TRACER_SAMPLER_RATIO

double

If the sampler to use for tracing is parent based. Valid values are true, false. Defaults to true.

Environment variable: QUARKUS_OPENTELEMETRY_TRACER_SAMPLER_PARENT_BASED

Show more

boolean

true

Suppress non-application uris from trace collection. This will suppress tracing of /q endpoints. Suppressing non-application uris is enabled by default.

Environment variable: QUARKUS_OPENTELEMETRY_TRACER_SUPPRESS_NON_APPLICATION_URIS

Show more

boolean

true

Include static resources from trace collection. Include static resources is disabled by default.

Environment variable: QUARKUS_OPENTELEMETRY_TRACER_INCLUDE_STATIC_RESOURCES

Show more

boolean

false

OTLP SpanExporter support. OTLP SpanExporter support is enabled by default.

Environment variable: QUARKUS_OPENTELEMETRY_TRACER_EXPORTER_OTLP_ENABLED

Show more

boolean

true

The OTLP endpoint to connect to. The endpoint must start with either http:// or https://.

Environment variable: QUARKUS_OPENTELEMETRY_TRACER_EXPORTER_OTLP_ENDPOINT

Show more

string

Key-value pairs to be used as headers associated with gRPC requests. The format is similar to the OTEL_EXPORTER_OTLP_HEADERS environment variable, a list of key-value pairs separated by the "=" character. See Specifying headers for more details.

Environment variable: QUARKUS_OPENTELEMETRY_TRACER_EXPORTER_OTLP_HEADERS

Show more

文字列のリスト

The maximum amount of time to wait for the collector to process exported spans before an exception is thrown. A value of 0 will disable the timeout: the exporter will continue waiting until either exported spans are processed, or the connection fails, or is closed for some other reason.

Environment variable: QUARKUS_OPENTELEMETRY_TRACER_EXPORTER_OTLP_EXPORT_TIMEOUT

Show more

Duration

10S

Compression method to be used by exporter to compress the payload. See Configuration Options for the supported compression methods.

Environment variable: QUARKUS_OPENTELEMETRY_TRACER_EXPORTER_OTLP_COMPRESSION

Show more

string

期間フォーマットについて

期間のフォーマットは標準の java.time.Duration フォーマットを使用します。詳細は Duration#parse() javadoc を参照してください。

数値で始まる期間の値を指定することもできます。この場合、値が数値のみで構成されている場合、コンバーターは値を秒として扱います。そうでない場合は、 PT が暗黙的に値の前に付加され、標準の java.time.Duration 形式が得られます。