在 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 構件:
配置 OpenTelemetry
在您的 Ktor 應用程式中安裝 KtorServerTelemetry 外掛程式之前,您需要配置並初始化一個 OpenTelemetry 執行個體。此執行個體負責管理遙測資料,包括追蹤和指標。
自動配置
配置 OpenTelemetry 的常見方式是使用 AutoConfiguredOpenTelemetrySdk。這可以透過根據系統屬性和環境變數自動配置匯出器 (exporter) 和資源 (resource),進而簡化設定。
您仍然可以自訂自動偵測到的配置 — 例如,透過新增 service.name 資源屬性:
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:
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 執行個體:
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)
}
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 方法 (GET、POST、PUT 等)。若要追蹤額外或自訂的方法,請配置 knownMethods 屬性:
install(KtorServerTelemetry) {
// ...
knownMethods(HttpMethod.DefaultMethods + CUSTOM_METHOD)
}擷取標頭
若要將特定的 HTTP 請求標頭作為 span 屬性包含在內,請使用 capturedRequestHeaders 屬性:
install(KtorServerTelemetry) {
// ...
capturedRequestHeaders(HttpHeaders.UserAgent)
}選擇 span 種類
若要根據請求特性覆寫 span 種類(例如 SERVER、CLIENT、PRODUCER、CONSUMER),請使用 spanKindExtractor 屬性:
install(KtorServerTelemetry) {
// ...
spanKindExtractor {
if (httpMethod == HttpMethod.Post) {
SpanKind.PRODUCER
} else {
SpanKind.CLIENT
}
}
}新增自訂屬性
若要在 span 的開始或結束時附加自訂屬性,請使用 attributesExtractor 屬性:
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 一體化映像封裝了 Grafana、Tempo(追蹤)、Loki(記錄)和 Mimir(指標)。
使用 Docker Compose
建立一個內容如下的 docker-compose.yml 檔案:
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 一體化容器:
docker compose up -d使用 Docker CLI
或者,您也可以直接使用 Docker 命令列執行 Grafana:
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 之前透過環境變數設定這些值:
export OTEL_TRACES_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317或使用 JVM 旗標:
-Dotel.traces.exporter=otlp -Dotel.exporter.otlp.protocol=grpc -Dotel.exporter.otlp.endpoint=http://localhost:4317存取 Grafana UI
啟動後,Grafana UI 網址為 http://localhost:3000/。
- 在瀏覽器開啟 Grafana UI:http://localhost:3000/。
- 使用預設憑據登入:
- User:
admin - Password:
admin
- User:
- 在左側導覽功能表中,前往 Drilldown → Traces:
在 Traces 檢視中,您可以: - 選擇 Rate (速率)、Errors (錯誤) 或 Duration (時長) 指標。
- 套用 span 篩選器(例如透過服務名稱或 span 名稱)來縮小資料範圍。
- 檢視追蹤、檢查詳細資訊,並與 span 時間軸互動。
