The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.
このページを編集

OpenTracing から OpenTelemetry トレーシングへの移行

Quarkus 3.x で、アプリケーションを OpenTracing から OpenTelemetry tracing に移行します。

レガシーの OpenTracing フレームワークは非推奨となり、新しい OpenTelemetry トレーシングフレームワークが採用されました。 OpenTracing の非推奨化を 2022 年 11 月 に発表し、Quarkus コアリポジトリーからエクステンションを削除して、Quarkiverse Hub に移行しました。

まだアプリケーションを OpenTelemetry トレーシングに移行していない場合は、今すぐ移行しましょう。

Quarkus 2.16.x から移行する必要がある場合は、設定プロパティーが異なることに注意してください。 こちら から、古いバージョンの Quarkus OpenTelemetry ガイドを確認する必要があります。

要件

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

  • 約15分

  • IDE

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

  • Apache Maven 3.9.9

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

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

概要

デモには 5 つの部分があります。概要を読んでから、ユースケースに最も適したセクションに進んでください。

1 - *開始点*では、OpenTracing を使用するクイックスタートアプリケーションを紹介します。

2 - 最初の部分は、OpenTracing を ビッグバン方式で変更 し、手動の計装が一切ない場合に適しています。

3 - これは、手動でコードを計装した場合の OpenTracing の ビッグバン方式の置換 です。OpenTracing と OpenTelemetry の主な違いを説明しています。

4 - 最後の部分では、OpenTracing シム を使用します。これは、手動で計装されたコードを含む大規模なアプリケーションがある場合に便利です。新しい OpenTelemetry API 上でレガシーの OpenTracing API を使用できるため、移行を段階的に実行するのに役立ちます。

5 - 結論と関連情報

以下に説明するタスクは 3 つのカテゴリーに分類されます。

  • 依存関係

  • Configuration (設定)

  • コード

開始点

このチュートリアルは、 opentracing-quickstart レガシープロジェクトをベースに構築されています。

レガシープロジェクトを生成する

次のコマンドを実行してレガシープロジェクトを作成します。

コマンドラインインタフェース
quarkus create app org.acme:opentracing-quickstart \
    --extension='rest,quarkus-smallrye-opentracing'
cd opentracing-quickstart

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

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

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.19.2:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=opentracing-quickstart \
    -Dextensions='rest,quarkus-smallrye-opentracing'
cd opentracing-quickstart

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

Windowsユーザーの場合:

  • cmdを使用する場合、(バックスラッシュ \ を使用せず、すべてを同じ行に書かないでください)。

  • Powershellを使用する場合は、 -D パラメータを二重引用符で囲んでください。例: "-DprojectArtifactId=opentracing-quickstart"

このコマンドは Maven プロジェクトを生成し、OpenTracing のサポートとデフォルトの Jaeger トレーサーを含む smallrye-opentracing エクステンションをインポートします。

既存のレガシープロジェクトを確認する

便宜上、チュートリアルのすべての手順を含むプロジェクトが github にあります。以下のコマンドでこれをクローンできます。

git clone git@github.com:quarkusio/opentracing-quickstart-migration.git

便宜上、移行するアプリケーションを含む リポジトリー には、このチュートリアルで説明した移行手順を模倣したコミットを含むいくつかのブランチが含まれています。 main ブランチを確認して、最初から開始できます。

アプリケーション

Quarkus プロジェクトには単一のエンドポイントがあり、関連するクラスは次のようになります。

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/hello")
public class GreetingResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "Hello from Quarkus REST";
    }
}

生成されたプロジェクトには OpenTracing 固有のコードはありませんが、 smallrye-opentracing エクステンションが存在し、デフォルトで有効になっているため、コードが自動的にインストルメント化されます。

Jaeger-all-in-one Docker イメージを起動して、キャプチャーされたトレースを取得して確認してみましょう。

docker run -e COLLECTOR_OTLP_ENABLED=true -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778 -p 16686:16686 -p 4317:4317 -p 4318:4318 -p 14250:14250 -p 14268:14268 -p 14269:14269 -p 9411:9411 jaegertracing/all-in-one:latest

この時点で、Quarkus 開発モードでアプリケーションを実行できます。

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

/hello エンドポイント を呼び出すと、関連するトレースを次のアドレスの Jaeger UI で取得できます: http://localhost:16686/

以下のようになります。

OpenTracing span

OpenTracing から OpenTelemetry へのビッグバン方式の変更

これは最も幸せなパスです。この場合、手動の計装はありません。副次的な影響を受けることなく、OpenTracing から OpenTelemetry へビッグバン方式で変更できます。

依存関係を変更する

2 つのフレームワーク間で移行するには、ビルドファイルで古い quarkus-smallrye-opentracing エクステンションを削除し、それを quarkus-opentelemetry エクステンションに置き換える必要があります。

レガシーエクステンションがプロジェクトから削除されます。

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

新しいものが追加されました。

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

Application properties

次の例のように、 application.properties ファイルから quarkus.jaeger.* から始まる古い OpenTracing プロパティーを削除する必要があります。

#Legacy OpenTracing properties to be removed
quarkus.jaeger.service-name=legume
quarkus.jaeger.sampler-type=const
quarkus.jaeger.sampler-param=1
quarkus.jaeger.endpoint=http://localhost:14268/api/traces
quarkus.jaeger.log-trace-context=true

OpenTelemetry プロパティーでデフォルト値を使用する場合、 application.properties ファイルに何かを含める必要はありません。

移行する一般的なプロパティーは次のとおりです。

レガシー OpenTracing プロパティー 新しい OpenTelemetry プロパティー

quarkus.jaeger.service-name=legume

quarkus.application.name=legume

quarkus.jaeger.endpoint=http://localhost:14268/api/traces

quarkus.otel.exporter.otlp.traces.endpoint=http://localhost:4317

quarkus.jaeger.auth-token

quarkus.otel.exporter.otlp.traces.headers

quarkus.jaeger.sampler-type

quarkus.otel.traces.sampler

quarkus.jaeger.sampler-param

quarkus.otel.traces.sampler.arg

quarkus.jaeger.tags

quarkus.otel.resource.attributes

quarkus.jaeger.propagation

quarkus.otel.propagators

エクステンションを有効化および無効化する方法は大きく異なります。OpenTelemetry エクステンションはデフォルトで有効になっており、tOpenTelemetry ガイドのこちらのセクション をチェックすることで、エクステンションのすべてまたは一部を無効にすることができます。

すべての OpenTelemetry プロパティーとそのデフォルトについては、OpenTelemetry 設定リファレンス を参照してください。

アプリケーションの実行

Quarkus を再起動する必要はありません。auto-reload が開始され、 /hello エンドポイント を呼び出して、Jaeger UI でトレースを表示できます: http://localhost:16686/

ただし、OpenTracing ではなく OpenTelemetry の自動計装によって生成されたスパンが表示されるようになりました。

OpenTelemetry span

独自の手動計装がない場合は、これで完了です。

手動計装がある場合のビッグバン方式の置換

上記の GreetingResource クラスの代わりに、もっと複雑なものがあるとします。開始点 からの変更に加えて、追加の作業が必要になります。

このクラスは @Traced アノテーションを使用し、「手動」のプログラムスパンを作成します。

クイックスタートプロジェクトの GreetingResource クラスのコードをコピーして貼り付けます。

OpenTracing の手動計装を使用した GreetingsResource

package org.acme;

import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.tag.Tags;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.opentracing.Traced;

@Path("/hello")
@ApplicationScoped
public class GreetingResource {

    @Inject
    io.opentracing.Tracer legacyTracer; (1)

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Traced(operationName = "Not needed, will change the current span name") (2)
    public String hello() {
        // Add a tag to the active span
        legacyTracer.activeSpan().setTag(Tags.COMPONENT, "GreetingResource"); (3)

        // Create a manual inner span
        Span innerSpan = legacyTracer.buildSpan("Count response chars").start();

        try (Scope dbScope = legacyTracer.scopeManager().activate(innerSpan)) {
            String response = "Hello from Quarkus REST";
            innerSpan.setTag("response-chars-count", response.length());
            return response;
        } catch (Exception e) {
            innerSpan.setTag("error", true); (4)
            innerSpan.setTag("error.message", e.getMessage());
            throw e;
        } finally {
            innerSpan.finish();
        }
    }
}
1 レガシーの OpenTracing トレーサーは、新しい OpenTelemetry トレーシングに置き換える必要があります。
2 @Traced アノテーションは @WithSpan アノテーションに置き換えられましたが、この新しいアノテーションは常に新しい Span を作成することに注意してください。JAX-RS エンドポイントはすでに計装されているため、使用しないでください。
3 Tag クラスは Attribute クラスに置き換えられました。 TagsSemanticAttributes クラスに置き換えられました。これは、属性名を仕様と一貫性のある状態に保つために、可能な限り使用する必要があります。
4 OpenTelemetry でエラーを処理するための新しいメソッドがあります。

OpenTelemetry トレーサーは OpenTracing API と互換性がありません。主な変更点を以下の表にまとめています。

注記 MicroProfile OpenTracing v3 OpenTelemetry

1

@Inject io.opentracing.Tracer legacyTracer;

@Inject io.opentelemetry.api.trace.Tracer otelTracer;

2

@Traced

@WithSpan

3

Tag

属性

3

タグ

SemanticAttributes

4

innerSpan.setTag("error", true); innerSpan.setTag("error.message", e.getMessage());

innerSpan.setStatus(ERROR); innerSpan.recordException(e);

-

Span 内の SpanContext によって運ばれる Baggage

Baggage は、OTel コンテキストと並行して伝播される独立した信号であり、その一部ではありません。

依存関係が更新されると、クイックスタートプロジェクトが OpenTelemetry で実行されているため、上記のクラスはビルドを中断します。以下のようなエラーがログに表示されます。

2023-10-27 16:11:12,454 ERROR [io.qua.dep.dev.IsolatedDevModeMain] (main) Failed to start quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
        [error]: Build step io.quarkus.arc.deployment.ArcProcessor#validate threw an exception: jakarta.enterprise.inject.spi.DeploymentException: jakarta.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type io.opentracing.Tracer and qualifiers [@Default]
...

代わりに新しい OpenTelemetry API を使用する必要があります。これはコードを移行する 1 つの方法です。

OpenTelemetry 手動計装による GreetingsResource

package org.acme;

import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.annotations.WithSpan;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

import static io.opentelemetry.api.trace.StatusCode.*;

@Path("/hello")
@ApplicationScoped
public class GreetingResource {

    @Inject
    io.opentelemetry.api.trace.Tracer otelTracer;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @WithSpan(value = "Not needed, will create a new span, child of the automatic JAX-RS span")
    public String hello() {
        // Add a tag to the active span
        Span incomingSpan = Span.current();
        incomingSpan.setAttribute(SemanticAttributes.CODE_NAMESPACE, "GreetingResource");

        // Create a manual inner span
        Span innerSpan = otelTracer.spanBuilder("Count response chars").startSpan();
        try (Scope scope = innerSpan.makeCurrent()) {
            final String response = "Hello from Quarkus REST";
            innerSpan.setAttribute("response-chars-count", response.length());
            return response;
        } catch (Exception e) {
            innerSpan.setStatus(ERROR);
            innerSpan.recordException(e);
            throw e;
        } finally {
            innerSpan.end();
        }
    }
}

OpenTracing の依存関係をすべて削除すると、コードがビルドされます。トレースに適切なスパンが含まれているか忘れずに再確認してください。これらは Jaeger UI で確認できます: http://localhost:16686/。

OpenTracing シム

このセクションでは、レガシーの OpenTracing API へのアクセスを提供することで移行をスムーズにする OpenTelemetry ライブラリーを紹介します。これは、多くの手動計装ポイントを持つ大規模なアプリケーションの移行に役立ちます。

このセクションを続行するには、コードプロジェクトが 開始点 である必要があります。前のセクションに関連する変更がある場合は、それらを元に戻すか、開始点 の手順に従っ、プロジェクトを再生成してから進めてください。

依存関係

quarkus-smallrye-opentracing エクステンションを削除し、 quarkus-opentelemetry エクステンションと opentelemetry-opentracing-shim ライブラリーをビルドファイルに追加します。

レガシーエクステンションがプロジェクトから削除されます。

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

新しいものが追加されました。

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-opentelemetry</artifactId>
</dependency>
<dependency>
  <groupId>io.opentelemetry</groupId>
  <artifactId>opentelemetry-opentracing-shim</artifactId>
  <!-- No need to declare the version -->
</dependency>
build.gradle
implementation("io.quarkus:quarkus-opentelemetry")
implementation("io.quarkus:opentelemetry-opentracing-shim")

コードの変更

OpenTracing の手動計装を使用した GreetingsResource における `GreetingResource`クラスの初期バージョンを思い出してください:

package org.acme;

import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.tag.Tags;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.opentracing.Traced;

@Path("/hello")
@ApplicationScoped
public class GreetingResource {

    @Inject
    io.opentracing.Tracer legacyTracer; (1)

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Traced(operationName = "Not needed, will change the current span name") (2)
    public String hello() {
        // Add a tag to the active span
        legacyTracer.activeSpan().setTag(Tags.COMPONENT, "GreetingResource"); (3)

        // Create a manual inner span
        Span innerSpan = legacyTracer.buildSpan("Count response chars").start();

        try (Scope dbScope = legacyTracer.scopeManager().activate(innerSpan)) {
            String response = "Hello from Quarkus REST";
            innerSpan.setTag("response-chars-count", response.length());
            return response;
        } catch (Exception e) {
            innerSpan.setTag("error", true);
            innerSpan.setTag("error.message", e.getMessage());
            throw e;
        } finally {
            innerSpan.finish();
        }
    }
}
1 `Tracer`アノテーションを削除し、代わりに OpenTelemetry SDK を注入する必要があります。これは、<3> で必要です。
2 @Traced アノテーションは @WithSpan アノテーションに置き換えられましたが、この新しいアノテーションは常に新しい Span を作成することに注意してください。JAX-RS エンドポイントでは使用しないでください。ここではデモ目的でのみ使用しています。
3 legacyTracer のインスタンスを取得する必要があります。シムには、この目的のためのユーティリティークラスが含まれています: Tracer legacyTracer = OpenTracingShim.createTracerShim(openTelemetry);

変更後、コードはコンパイルされ、OpenTracing および OpenTelemetry API の両方を同時に使用できるようになります。

package org.acme;

import io.opentelemetry.instrumentation.annotations.WithSpan;
import io.opentelemetry.opentracingshim.OpenTracingShim;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.Tracer;
import io.opentracing.tag.Tags;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/hello")
@ApplicationScoped
public class GreetingResource {

    @Inject
    io.opentelemetry.api.OpenTelemetry openTelemetry;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @WithSpan(value = "Not needed, will create a new span, child of the automatic JAX-RS span")
    public String hello() {
        // Add a tag to the active span
        Tracer legacyTracer = OpenTracingShim.createTracerShim(openTelemetry);
        legacyTracer.activeSpan().setTag(Tags.COMPONENT, "GreetingResource");

        // Create a manual inner span
        Span innerSpan = legacyTracer.buildSpan("Count response chars").start();

        try (Scope dbScope = legacyTracer.scopeManager().activate(innerSpan)) {
            String response = "Hello from Quarkus REST";
            innerSpan.setTag("response-chars-count", response.length());
            return response;
        } catch (Exception e) {
            innerSpan.setTag("error", true);
            innerSpan.setTag("error.message", e.getMessage());
            throw e;
        } finally {
            innerSpan.finish();
        }
    }
}

シムを永続的な解決策として使用するのではなく、移行をスムーズにするためのツールとしてのみ使用することを推奨します。

結論と関連情報

このチュートリアルでは、Quarkus 3.x でアプリケーションを OpenTracing から OpenTelemetry トレーシングに移行する方法を説明しました。

OpenTelemetry への移行に関する詳細は、以下を参照してください。

関連コンテンツ