Skip to content
Server Plugin

在 Ktor Server 中使用 OpenTelemetry 進行分散式追蹤

必要的相依性io.opentelemetry.instrumentation:opentelemetry-ktor-3.0

程式碼範例 opentelemetry

Ktor 與 OpenTelemetry 整合 — 這是一個開源的觀測性架構,用於收集追蹤 (trace)、指標 (metric) 和記錄 (log) 等遙測資料。它提供了一種標準化的方式來檢測應用程式,並將資料匯出到 Grafana 或 Jaeger 等監控與觀測工具。

KtorServerTelemetry 外掛程式可以對 Ktor 伺服器應用程式中的傳入 HTTP 請求進行分散式追蹤。它會自動建立包含路徑 (route)、HTTP 方法和狀態碼資訊的 span,從傳入的請求標頭中提取現有的追蹤內容 (trace context),並允許自訂 span 名稱、屬性 (attribute) 和 span 種類 (span kind)。

在用戶端,OpenTelemetry 提供了 KtorClientTelemetry 外掛程式,用於收集對外部服務的傳出 HTTP 呼叫追蹤。

新增相依性

若要使用 KtorServerTelemetry,您需要在組建指令碼中包含 opentelemetry-ktor-3.0 構件:

Kotlin
Groovy
XML

配置 OpenTelemetry

在您的 Ktor 應用程式中安裝 KtorServerTelemetry 外掛程式之前,您需要配置並初始化一個 OpenTelemetry 執行個體。此執行個體負責管理遙測資料,包括追蹤和指標。

自動配置

配置 OpenTelemetry 的常見方式是使用 AutoConfiguredOpenTelemetrySdk。這可以透過根據系統屬性和環境變數自動配置匯出器 (exporter) 和資源 (resource),進而簡化設定。

您仍然可以自訂自動偵測到的配置 — 例如,透過新增 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
}

程式化配置

若要在程式碼中定義匯出器、處理器 (processor) 和傳播器 (propagator),而不是依賴基於環境的配置,您可以使用 OpenTelemetrySdk

以下範例顯示如何使用 OTLP 匯出器、span 處理器和追蹤內容傳播器以程式化方式配置 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 span 的方式。下列選項允許您調整要追蹤哪些請求、span 如何命名、它們包含哪些屬性,以及如何確定 span 種類。

關於這些概念的更多資訊,請參閱 OpenTelemetry 追蹤文件

追蹤額外的 HTTP 方法

預設情況下,此外掛程式會追蹤標準 HTTP 方法 (GETPOSTPUT 等)。若要追蹤額外或自訂的方法,請配置 knownMethods 屬性:

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

擷取標頭

若要將特定的 HTTP 請求標頭作為 span 屬性包含在內,請使用 capturedRequestHeaders 屬性:

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

選擇 span 種類

若要根據請求特性覆寫 span 種類(例如 SERVERCLIENTPRODUCERCONSUMER),請使用 spanKindExtractor 屬性:

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

新增自訂屬性

若要在 span 的開始或結束時附加自訂屬性,請使用 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 接收器 (追蹤、指標、記錄)
      - "4318:4318"   # OTLP HTTP 接收器
      - "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 接收器 (追蹤、指標、記錄)
    -p 4318:4318 \   # OTLP HTTP 接收器
    -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. 使用預設憑據登入:
    • User:admin
    • Password:admin
  3. 在左側導覽功能表中,前往 Drilldown → TracesGrafana UI Drilldown 追蹤檢視Traces 檢視中,您可以:
    • 選擇 Rate (速率)、Errors (錯誤) 或 Duration (時長) 指標。
    • 套用 span 篩選器(例如透過服務名稱或 span 名稱)來縮小資料範圍。
    • 檢視追蹤、檢查詳細資訊,並與 span 時間軸互動。