Kotlin 可观测性:实践中的追踪、指标和日志

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

为什么可观测性是 Kotlin 应用的必备品

\n\n

想象一下:您的 Kotlin 应用在生产环境中运行,突然用户抱怨请求需要 10 秒才能完成。您查看日志——一片寂静。指标显示 CPU 使用率 100%,但没有说明是哪个端点导致了延迟。熟悉吗?

\n\n

欢迎来到这样一个世界,在这里 可观测性 不是可选项,而是必需品。与仅回答系统“是否存活”的传统监控不同,可观测性允许您提出以前从未想过的问题。而 Kotlin,凭借其简洁性和强大的生态系统,非常适合引入这种文化。

\n\n

在本文中,我们将探讨可观测性的三大支柱——追踪、指标和日志——并展示如何将它们与 Kotlin 结合。没有废话,只有真实的代码示例。

\n\n

追踪:请求在微服务中的旅程

\n\n

分布式追踪就像您请求的 GPS。您可以看到请求经过了哪些服务,每一步花费了多长时间,以及延迟发生在哪里。对于 Kotlin 来说,最好的伙伴是 OpenTelemetry (OTel)。

\n\n

在 Kotlin 中配置 OpenTelemetry

\n\n

在 build.gradle.kts 中添加依赖项:

\n\n
dependencies {\n    implementation("io.opentelemetry:opentelemetry-api:1.36.0")\n    implementation("io.opentelemetry:opentelemetry-sdk:1.36.0")\n    implementation("io.opentelemetry:opentelemetry-exporter-otlp:1.36.0")\n    implementation("io.opentelemetry:opentelemetry-extension-kotlin:1.36.0")\n}
\n\n

现在创建一个简单的追踪器:

\n\n
import io.opentelemetry.api.GlobalOpenTelemetry\nimport io.opentelemetry.api.trace.Span\nimport io.opentelemetry.api.trace.Tracer\nimport io.opentelemetry.context.Scope\n\nclass OrderService(private val tracer: Tracer = GlobalOpenTelemetry.getTracer("order-service")) {\n\n    fun processOrder(orderId: String) {\n        val span: Span = tracer.spanBuilder("processOrder")\n            .setAttribute("order.id", orderId)\n            .startSpan()\n\n        span.use { // use() 会自动关闭 span\n            try {\n                // 模拟工作\n                Thread.sleep(100)\n                validateOrder(orderId)\n                chargePayment(orderId)\n            } catch (e: Exception) {\n                span.recordException(e)\n                span.setStatus(StatusCode.ERROR, "Order processing failed")\n                throw e\n            }\n        }\n    }\n\n    private fun validateOrder(orderId: String) {\n        val span: Span = tracer.spanBuilder("validateOrder")\n            .setAttribute("order.id", orderId)\n            .startSpan()\n\n        span.use {\n            Thread.sleep(50) // 模拟验证\n        }\n    }\n\n    private fun chargePayment(orderId: String) {\n        val span: Span = tracer.spanBuilder("chargePayment")\n            .setAttribute("order.id", orderId)\n            .startSpan()\n\n        span.use {\n            Thread.sleep(150) // 模拟支付\n        }\n    }\n}
\n\n

请注意 span.use——这是来自 opentelemetry-extension-kotlin 的扩展函数,它会在块执行后自动关闭 span。Kotlin 之美尽显于此!

\n\n

通过协程进行上下文传递

\n\n

在 Kotlin 中,我们广泛使用协程。OpenTelemetry 通过 Context 机制与协程完美配合:

\n\n
import kotlinx.coroutines.withContext\nimport io.opentelemetry.api.trace.Span\nimport io.opentelemetry.context.Context\n\nsuspend fun processOrderAsync(orderId: String) = withContext(Context.current()) {\n    val span = tracer.spanBuilder("processOrderAsync").startSpan()\n    span.use {\n        // 您的异步逻辑\n    }\n}
\n\n

追踪揭示了全貌:您会看到 80% 的时间花费在支付上

博客

书籍推荐