为什么可观测性是 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 中添加依赖项:
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\nimport 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在 Kotlin 中,我们广泛使用协程。OpenTelemetry 通过 Context 机制与协程完美配合:
\n\nimport 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% 的时间花费在支付上