Skip to content
Server Plugin

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

所需依賴項io.opentelemetry.instrumentation:opentelemetry-ktor-3.0

程式碼範例 opentelemetry

Ktor 與 OpenTelemetry 整合 — 這是一個開源的可觀測性框架,用於收集 遙測資料,例如追蹤 (traces)、指標 (metrics) 和日誌 (logs)。它提供了一種標準方式來儀器化應用程式並將資料 匯出到 Grafana 或 Jaeger 等監控和可觀測性工具。

KtorServerTelemetry 外掛程式在 Ktor 伺服器應用程式中啟用傳入 HTTP 請求的分散式追蹤。它 會自動建立包含路由、HTTP 方法和狀態碼資訊的 span,從傳入請求標頭中提取現有的追蹤上下文 (trace context),並允許 自訂 span 名稱、屬性 (attributes) 和 span 種類 (span kinds)。

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

新增依賴項

若要使用 KtorServerTelemetry,您需要在建置腳本中包含 opentelemetry-ktor-3.0 artifact:

Kotlin
Groovy
XML

配置 OpenTelemetry

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

自動配置

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

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

程式化配置

若要在程式碼中定義匯出器、處理器 (processors) 和傳播器 (propagators),而不是依賴基於環境的配置,您可以使用 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 使用者介面
    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 使用者介面
    -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. http://localhost:3000/ 開啟 Grafana UI。
  2. 使用預設憑證登入:
    • 使用者:admin
    • 密碼:admin
  3. 在左側導覽選單中,前往 鑽取 (Drilldown) → 追蹤 (Traces)Grafana UI Drilldown traces view 進入 追蹤 (Traces) 視圖後,您可以:
    • 選擇費率 (Rate)、錯誤 (Errors) 或持續時間 (Duration) 指標。
    • 應用 span 篩選器 (例如,依服務名稱或 span 名稱) 以縮小您的資料範圍。
    • 檢視追蹤、檢查詳細資訊並與 span 時間軸互動。