Client HTTP en Java : faire des requêtes correctement de A à Z

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Pourquoi l'observabilité est indispensable pour les applications Kotlin

\n\n

Imaginez : votre application Kotlin tourne en production, et soudainement, les utilisateurs se plaignent que les requêtes prennent 10 secondes. Vous consultez les logs — silence. Les métriques montrent 100% du CPU, mais ne vous disent pas quel endpoint spécifique ralentit. Cela vous semble familier ?

\n\n

Bienvenue dans le monde où l'observabilité n'est pas une option, mais une nécessité. Contrairement à la surveillance traditionnelle, qui répond simplement "oui/non" à la question "le système est-il vivant ?", l'observabilité vous permet de poser des questions dont vous ne connaissiez même pas l'existence. Et Kotlin, avec sa concision et son écosystème puissant, est idéalement adapté pour implémenter cette culture.

\n\n

Dans cet article, nous allons détailler les trois piliers de l'observabilité — le tracing, les métriques et les logs — et montrer comment les intégrer avec Kotlin. Pas de blabla, seulement des exemples de code concrets.

\n\n

Tracing : Le parcours d'une requête à travers les microservices

\n\n

Le tracing distribué est comme un GPS pour votre requête. Vous pouvez voir par quels services la requête est passée, combien de temps chaque étape a pris, et où le délai s'est produit. Pour Kotlin, le meilleur allié pour cela est OpenTelemetry (OTel).

\n\n

Configuration d'OpenTelemetry dans Kotlin

\n\n

Ajoutez les dépendances dans 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

Créons maintenant un traceur simple :

\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() fermera automatiquement le span\n            try {\n                // Simuler le travail\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) // Simuler la validation\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) // Simuler le paiement\n        }\n    }\n}
\n\n

Remarquez span.use — c'est une fonction d'extension de opentelemetry-extension-kotlin qui ferme automatiquement le span après l'exécution du bloc. La beauté de Kotlin en action !

\n\n

Propagation de contexte via les coroutines

\n\n

Dans Kotlin, nous utilisons activement les coroutines. OpenTelemetry s'intègre parfaitement avec elles grâce au mécanisme de Contexte :

\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        // Votre logique asynchrone\n    }\n}
\n\n

Le tracing révèle l'image complète : vous pouvez voir que 80% du temps est consacré au paiement

Blogs

Book Recommendations