Skip to content
Server Plugin

KtorサーバーでのOpenTelemetryによる分散トレース

必要な依存関係: io.opentelemetry.instrumentation:opentelemetry-ktor-3.0

コード例: opentelemetry

KtorはOpenTelemetryと統合されています。OpenTelemetryは、トレース、メトリクス、ログなどのテレメトリーデータを収集するためのオープンソースの可観測性フレームワークです。アプリケーションを計測し、データをGrafanaやJaegerなどの監視および可観測性ツールにエクスポートするための標準的な方法を提供します。

KtorServerTelemetryプラグインは、Ktorサーバーアプリケーションにおける受信HTTPリクエストの分散トレースを可能にします。このプラグインは、ルート、HTTPメソッド、ステータスコード情報を含むspansを自動的に作成し、受信リクエストヘッダーから既存のトレースコンテキストを抽出し、スパン名、属性、スパンの種類をカスタマイズできるようにします。

クライアント側では、OpenTelemetryはKtorClientTelemetryプラグインを提供しており、これは外部サービスへの送信HTTP呼び出しのトレースを収集します。

依存関係の追加

KtorServerTelemetryを使用するには、ビルドスクリプトにopentelemetry-ktor-3.0アーティファクトを含める必要があります。

Kotlin
Groovy
XML

OpenTelemetryの構成

KtorアプリケーションにKtorServerTelemetryプラグインをインストールする前に、OpenTelemetryインスタンスを構成および初期化する必要があります。このインスタンスは、トレースやメトリクスを含むテレメトリーデータの管理を担当します。

自動構成

OpenTelemetryを構成する一般的な方法は、AutoConfiguredOpenTelemetrySdkを使用することです。これにより、システムプロパティと環境変数に基づいてエクスポーターとリソースが自動的に構成され、セットアップが簡素化されます。

自動検出された構成は、例えばservice.nameリソース属性を追加するなどして、引き続きカスタマイズできます。

kotlin
package com.example

import io.opentelemetry.api.OpenTelemetry
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk
import io.opentelemetry.semconv.ServiceAttributes

fun getOpenTelemetry(serviceName: String): OpenTelemetry {

    return AutoConfiguredOpenTelemetrySdk.builder().addResourceCustomizer { oldResource, _ ->
        oldResource.toBuilder()
            .putAll(oldResource.attributes)
            .put(ServiceAttributes.SERVICE_NAME, serviceName)
            .build()
    }.build().openTelemetrySdk
}

プログラムによる構成

環境ベースの構成に依存する代わりに、コードでエクスポーター、プロセッサー、およびプロパゲーターを定義するには、OpenTelemetrySdkを使用できます。

次の例は、OTLPエクスポーター、スパンプロセッサー、およびトレースコンテキストプロパゲーターを使用してOpenTelemetryをプログラムで構成する方法を示しています。

kotlin
import io.opentelemetry.api.OpenTelemetry
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator
import io.opentelemetry.context.propagation.ContextPropagators
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter
import io.opentelemetry.sdk.OpenTelemetrySdk
import io.opentelemetry.sdk.trace.SdkTracerProvider
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor

fun configureOpenTelemetry(): OpenTelemetry {
    val spanExporter = OtlpGrpcSpanExporter.builder()
        .setEndpoint("http://localhost:4317")
        .build()

    val tracerProvider = SdkTracerProvider.builder()
        .addSpanProcessor(BatchSpanProcessor.builder(spanExporter).build())
        .build()

    return OpenTelemetrySdk.builder()
        .setTracerProvider(tracerProvider)
        .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
        .buildAndRegisterGlobal()
}

このアプローチは、テレメトリーのセットアップを完全に制御する必要がある場合、またはデプロイ環境が自動構成に依存できない場合に使用します。

詳細については、OpenTelemetry SDKコンポーネントのドキュメントを参照してください。

KtorServerTelemetryのインストール

アプリケーションにKtorServerTelemetryプラグインをインストールするには、指定されたモジュールinstall関数に渡し、構成済みのOpenTelemetryインスタンスを設定します。

kotlin
    import io.ktor.server.engine.*
    import io.ktor.server.netty.*
    import io.ktor.server.application.*
    import io.opentelemetry.instrumentation.*

    fun main() {
        embeddedServer(Netty, port = 8080) {
            val openTelemetry = getOpenTelemetry(serviceName = "opentelemetry-ktor-sample-server")

            install(KtorServerTelemetry){
                setOpenTelemetry(openTelemetry)
            }
            // ...
        }.start(wait = true)
    }
kotlin

    import io.ktor.server.application.*
    import io.opentelemetry.instrumentation.*
    // ...

    fun Application.module() {
        val openTelemetry = getOpenTelemetry(serviceName = "opentelemetry-ktor-sample-server")

        install(KtorServerTelemetry){
            setOpenTelemetry(openTelemetry)
        }
        // ...
    }

KtorServerTelemetryは、他のロギングまたはテレメトリー関連のプラグインよりも前にインストールされていることを確認してください。

トレースの構成

KtorサーバーがOpenTelemetryスパンを記録およびエクスポートする方法をカスタマイズできます。以下のオプションを使用すると、どのリクエストがトレースされるか、スパンがどのように命名されるか、含まれる属性、およびスパンの種類の決定方法を調整できます。

これらの概念の詳細については、OpenTelemetryトレースドキュメントを参照してください。

追加のHTTPメソッドをトレースする

デフォルトでは、このプラグインは標準のHTTPメソッド(GETPOSTPUTなど)をトレースします。追加またはカスタムのメソッドをトレースするには、knownMethodsプロパティを構成します。

kotlin
install(KtorServerTelemetry) {
    // ...
    knownMethods(HttpMethod.DefaultMethods + CUSTOM_METHOD)
}

ヘッダーをキャプチャする

特定のリクエストヘッダーをスパン属性として含めるには、capturedRequestHeadersプロパティを使用します。

kotlin
install(KtorServerTelemetry) {
    // ...
    capturedRequestHeaders(HttpHeaders.UserAgent)
}

スパンの種類の選択

リクエストの特性に基づいてスパンの種類(SERVERCLIENTPRODUCERCONSUMERなど)をオーバーライドするには、spanKindExtractorプロパティを使用します。

kotlin
install(KtorServerTelemetry) {
    // ...
    spanKindExtractor {
        if (httpMethod == HttpMethod.Post) {
            SpanKind.PRODUCER
        } else {
            SpanKind.CLIENT
        }
    }
}

カスタム属性の追加

スパンの開始時または終了時にカスタム属性をアタッチするには、attributesExtractorプロパティを使用します。

kotlin
install(KtorServerTelemetry) {
    // ...
    attributesExtractor {
        onStart {
            attributes.put("start-time", System.currentTimeMillis())
        }
        onEnd {
            attributes.put("end-time", Instant.now().toEpochMilli())
        }
    }
}

その他のプロパティ

アプリケーション全体のトレース動作を細かく調整するために、プロパゲーター、属性制限、計測の有効化/無効化など、追加のOpenTelemetryプロパティも構成できます。詳細については、OpenTelemetry Java構成ガイドを参照してください。

Grafana LGTMでテレメトリーデータを検証する

テレメトリーデータを視覚化および検証するために、トレース、メトリクス、ログをGrafanaなどの分散トレースバックエンドにエクスポートできます。grafana/otel-lgtmオールインワンイメージには、GrafanaTempo(トレース)、Loki(ログ)、およびMimir(メトリクス)がバンドルされています。

Docker Composeの使用

以下の内容でdocker-compose.ymlファイルを作成します。

yaml
services:
  grafana-lgtm:
    image: grafana/otel-lgtm:latest
    ports:
      - "4317:4317"   # OTLP gRPC receiver (traces, metrics, logs)
      - "4318:4318"   # OTLP HTTP receiver
      - "3000:3000"   # Grafana UI
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=admin
    restart: unless-stopped

Grafana LGTMオールインワンコンテナを起動するには、次のコマンドを実行します。

shell
docker compose up -d

Docker CLIの使用

あるいは、Dockerコマンドラインを使用してGrafanaを直接実行することもできます。

shell
docker run -d --name grafana_lgtm \
    -p 4317:4317 \   # OTLP gRPC receiver (traces, metrics, logs)
    -p 4318:4318 \   # OTLP HTTP receiver
    -p 3000:3000 \   # Grafana UI
    -e GF_SECURITY_ADMIN_USER=admin \
    -e GF_SECURITY_ADMIN_PASSWORD=admin \
    grafana/otel-lgtm:latest

アプリケーションエクスポート構成

KtorアプリケーションからOTLPエンドポイントにテレメトリーを送信するには、OpenTelemetry SDKがgRPCプロトコルを使用するように構成します。これらの値は、SDKをビルドする前に環境変数で設定できます。

shell
export OTEL_TRACES_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317

または、JVMフラグを使用します。

text
-Dotel.traces.exporter=otlp -Dotel.exporter.otlp.protocol=grpc -Dotel.exporter.otlp.endpoint=http://localhost:4317

Grafana UIへのアクセス

実行されると、Grafana UIはhttp://localhost:3000/で利用可能になります。

  1. Grafana UIをhttp://localhost:3000/で開きます。
  2. 以下のデフォルトの認証情報でログインします。
    • ユーザー:admin
    • パスワード:admin
  3. 左側のナビゲーションメニューで、ドリルダウン → トレースに移動します。 Grafana UI Drilldown traces viewトレースビューでは、次のことができます。
    • レート、エラー、または期間のメトリクスを選択します。
    • サービス名やスパン名などでスパンフィルターを適用して、データを絞り込みます。
    • トレースを表示し、詳細を検査し、スパンのタイムラインを操作します。