Pourquoi une application Kotlin « silencieuse » est une bombe à retardement
\n\nImaginez : vous avez lancé un service en Kotlin, il fonctionne comme une horloge. Les utilisateurs sont satisfaits, les métriques sont vertes. Mais un beau jour, la charge augmente, la latence grimpe, et vous n'avez aucune idée de la raison. Sans journalisation ni surveillance, vous êtes un capitaine de navire sans carte ni radar. Dans cet article, nous allons voir comment transformer votre application d'une « boîte noire » en un système transparent où chaque panne est visible à l'œil nu.
\n\nNous ne copierons pas la documentation. À la place, nous proposons des cas réels, des extraits prêts à l'emploi et des solutions architecturales qui fonctionnent en production. C'est parti.
\n\nDivisons l'éléphant en morceaux : journalisation vs surveillance
\n\nAvant d'écrire du code, mettons-nous d'accord sur les termes. La journalisation est l'enregistrement d'événements (erreurs, avertissements, informations de débogage) sous forme structurée ou textuelle. La surveillance est la collecte de métriques (temps de réponse, nombre de requêtes, charge CPU) et leur visualisation. Idéalement, elles fonctionnent de concert : les logs sont nécessaires pour une analyse approfondie d'un incident, les métriques pour une détection rapide des anomalies.
\n\nConfiguration de la journalisation en Kotlin : du simple au complexe
\n\nChoisir une bibliothèque : SLF4J + Logback — le standard en or
\n\nKotlin s'entend très bien avec l'écosystème Java, donc SLF4J (façade) et Logback (implémentation) sont le choix numéro 1. Ils sont légers, performants et prennent en charge la journalisation asynchrone.
\n\nAjoutez dans build.gradle.kts :
implementation("ch.qos.logback:logback-classic:1.4.14")\nimplementation("io.github.microutils:kotlin-logging-jvm:3.0.5")\n\nkotlin-logging est une fine couche d'abstraction au-dessus de SLF4J qui rend le code plus propre. Comparez :
\n\nSans couche d'abstraction :
\nprivate val logger = LoggerFactory.getLogger(MyService::class.java)\nlogger.info("User {} logged in", userId)\n\nAvec kotlin-logging :
\nprivate val logger = KotlinLogging.logger {}\nlogger.info { "User $userId logged in" }\n\nL'évaluation paresseuse des chaînes est un bonus pour les performances : la chaîne n'est construite que si le niveau de journalisation est activé.
\n\nConfiguration de Logback : les logs structurés sont un must have
\n\nCréez logback.xml dans src/main/resources :
<configuration>\n <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">\n <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>\n </appender>\n\n <root level="INFO">\n <appender-ref ref="CONSOLE"/>\n </root>\n</configuration>\n\nNous utilisons LogstashEncoder — il transforme les logs en JSON. C'est crucial si vous envoyez les logs vers Elasticsearch, Loki ou tout autre agrégateur. Les logs JSON sont facilement analysés, filtrés et interprétés.
\n\nN'oubliez pas d'ajouter la dépendance :
\nimplementation("net.logstash.logback:logstash-logback-encoder:7.4")\n\nÉcrire des logs pertinents : le contexte est roi
\n\nLes logs du type « Erreur survenue » sont inutiles. Ajoutez le MDC (Mapped Diagnostic Context) — c'est comme des étiquettes pour vos logs.
import org.slf4j.MDC\n\nclass OrderService {\n private val logger = KotlinLogging.logger {}\n\n fun processOrder(orderId: String, userId: String) {\n MDC.put("orderId", orderId)\n MDC.put("userId", userId)\n try {\n logger.info { "Processing order" }\n // logique métier\n } catch (e: Exception) {\n logger.error(e) { "Order processing failed" }\n } finally {\n MDC.clear()\n }\n }\n}\n\nMaintenant, dans l'agrégateur de logs, vous pourrez trouver toutes les entrées concernant une commande ou un utilisateur spécifique en une seconde.
\n\n