Pourquoi votre application Go se tait-elle, et comment y remédier ?
\nVous avez écrit un microservice Go parfait. Il réussit tous les tests, démarre rapidement et consomme peu de mémoire. Vous le déployez en production — et une heure plus tard, les utilisateurs se plaignent de ralentissements. Vous vous connectez au serveur, regardez le terminal vide et réalisez : l'application se tait. Pas de logs, pas de métriques, aucune idée de ce qui a mal tourné.
\nUne situation familière ? Bienvenue dans le monde de l'observability (observabilité) des applications Go. Sans surveillance et journalisation, votre code est une boîte noire. Aujourd'hui, nous allons voir comment le transformer en un système transparent, où chaque latence et chaque erreur sont visibles comme en plein jour.
\nJe vais vous montrer trois outils fonctionnels, des exemples de code Go réels et vous donner une liste de contrôle qui sauvera votre production. C'est parti !
\n\n1. Journalisation structurée : comment arrêter d'écrire dans la console et commencer à vivre
\nLe naïf fmt.Println("Erreur :", err) appartient au passé. Dans la journalisation Go moderne, il faut de l'ordre : format JSON, niveaux (debug, info, warn, error), champs pour la recherche. Voici le roi — la bibliothèque zap d'Uber.
Pourquoi zap ?
\n- \n
- Vitesse : il est 10 à 100 fois plus rapide que le
logstandard sous forte charge. \n - Structure : vous ajoutez des clés et des valeurs, au lieu de concaténer des chaînes. \n
- Flexibilité : vous pouvez écrire dans un fichier, dans stdout, dans Elasticsearch — n'importe où. \n
Installation et exemple de base
\ngo get -u go.uber.org/zap\n\nCode d'un logger simple :
\npackage main\n\nimport (\n "go.uber.org/zap"\n)\n\nfunc main() {\n logger, _ := zap.NewProduction()\n defer logger.Sync() // vide le tampon avant de sortir\n\n logger.Info("Service démarré",\n zap.String("env", "production"),\n zap.Int("port", 8080),\n )\n\n // Exemple avec erreur\n err := someFunction()\n if err != nil {\n logger.Error("Impossible d'effectuer l'opération",\n zap.Error(err),\n zap.String("module", "database"),\n )\n }\n}\n\nEn sortie, vous obtenez un JSON propre :
\n{"level":"info","ts":1700000000.123,"msg":"Service démarré","env":"production","port":8080}\n\nDésormais, tout outil comme Kibana ou Grafana Loki peut analyser ces logs par champs. Vous voulez trouver toutes les erreurs du module "database" de la dernière heure ? Un clic.
\n\nConseil : ne journalisez pas les secrets et les données personnelles
\nAjoutez une vérification : si un champ contient un mot de passe ou un email — masquez-le. Utilisez zap.String("user", "***") pour les données sensibles.
2. Métriques et surveillance : transformez votre code en tableau de bord
\nLes logs, c'est bien, mais ils parlent du passé. Les métriques, c'est le pouls de votre application en temps réel. Pour la surveillance des applications Go, la norme de facto est Prometheus + sa bibliothèque cliente.
\n\nQue mesurer ?
\n- \n
- RPS (requêtes par seconde) — la charge sur le service. \n
- Latence (p50, p95, p99) — le temps de réponse. \n
- Taux d'erreur — le pourcentage d'erreurs. \n
- Goroutines — les fuites de goroutines. \n
- Mémoire / CPU — les ressources. \n
Exemple : ajout de métriques pour un serveur HTTP
\npackage main\n\nimport (\n "net/http"\n "github.com/prometheus/client_golang/prometheus"\n "github.com/prometheus/client_golang/prometheus/promhttp"\n)\n\nvar (\n requestCount = prometheus.NewCounterVec(\n prometheus.CounterOpts{\n Name: "http_requests_total",\n Help: "Total number of HTTP requests",\n },\n []string{"method", "endpoint", "status"},\n )\n requestDuration = prometheus.NewHistogramVec(\n prometheus.HistogramOpts{\n Name: "http_request