Pourquoi Logging et monitoring Go ?
Le logging et le monitoring sont des aspects essentiels de la qualité et de l'assurance de votre application Go. Ils permettent aux développeurs d'identifier les problèmes, de comprendre le comportement de l'application et de s'assurer qu'elle fonctionne correctement en production. Un contexte réel est que vous travaillez sur un microservice qui gère la gestion des commandes pour une e-commerce. Vous avez besoin de savoir quand une commande est traitée avec succès, quand elle rencontre un problème et comment résoudre ces problèmes.
Un cas d'usage concret serait : le logging pourrait aider à identifier les erreurs lors du traitement des paiements. Le monitoring permettrait de suivre l'utilisation des ressources et de détecter les anomalies comme une augmentation excessive de la charge sur le système.
Prerequis
- Connaissance de base de Go
- Compréhension des structures de données (maps, slices, etc.)
- Familiarité avec les concepts de gestion des erreurs en Go
- Installation d'Go 1.19 ou version ultérieure
- Un éditeur de code comme Visual Studio Code
Concepts fondamentaux
Logging
Le logging est le processus de stockage et de visualisation des informations générées par une application. Cela permet aux développeurs de suivre le comportement de l'application en temps réel et de déboguer les problèmes.
package main
import (
"log"
)
func main() {
log.Println("Application started")
defer log.Println("Application ended")
// Simulate some operations
for i := 0; i < 10; i++ {
if i == 5 {
log.Println("Operation failed at step", i)
}
log.Println("Operation successful at step", i)
}
}
Middleware
Un middleware est une fonction qui reçoit une requête HTTP, effectue certaines opérations et passe la requête au prochain middleware ou à la gestionnaire de requêtes.
package main
import (
"fmt"
"net/http"
)
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Request received")
next.ServeHTTP(w, r)
fmt.Println("Response sent")
})
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", helloHandler)
middleware := loggingMiddleware(mux)
http.ListenAndServe(":8080", middleware)
}
Monitoring
Le monitoring est le processus d'observation et de mesure des indicateurs clés de performance (KPI) d'une application. Cela permet aux développeurs de suivre l'utilisation des ressources, la latence, les taux d'erreur, etc.
package main
import (
"fmt"
"net/http"
"time"
)
func monitoringMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
duration := time.Since(start)
fmt.Printf("Request took %s\n", duration)
})
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", helloHandler)
middleware := monitoringMiddleware(mux)
http.ListenAndServe(":8080", middleware)
}
Mise en pratique : projet fil rouge
Nous allons créer un simple API de blog qui permet aux utilisateurs d'ajouter des articles et de les récupérer. Nous utiliserons le logging pour suivre les opérations et le monitoring pour suivre la latence.
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"time"
)
type Article struct {
ID string `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
}
var articles = []Article{
{ID: "1", Title: "First Post", Content: "This is the first post."},
}
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("Request received")
next.ServeHTTP(w, r)
log.Println("Response sent")
})
}
func monitoringMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
duration := time.Since(start)
fmt.Printf("Request took %s\n", duration)
})
}
func articlesHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(articles)
case "POST":
var newArticle Article
err := json.NewDecoder(r.Body).Decode(&newArticle)
if err != nil {
log.Println("Error decoding request body:", err)
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}
articles = append(articles, newArticle)
fmt.Fprintf(w, "Article added successfully")
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/articles", articlesHandler)
middleware := loggingMiddleware(monitoringMiddleware(mux))
log.Println("Starting server on :8080")
if err := http.ListenAndServe(":8080", middleware); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
}
Erreurs frequentes et debugging
1. Erreur de décodage du corps de la requête
## ❌ Mauvais
var newArticle Article
err := json.NewDecoder(r.Body).Decode(&newArticle)
## ✅ Correct
var newArticle Article
err := json.NewDecoder(r.Body).Decode(&newArticle)
if err != nil {
log.Println("Error decoding request body:", err)
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}
2. Erreur de logging
## ❌ Mauvais
log.Println("Operation failed at step", i)
## ✅ Correct
if i == 5 {
log.Printf("Operation failed at step %d", i)
}
3. Erreur de monitoring
## ❌ Mauvais
fmt.Printf("Request took %s\n", duration)
## ✅ Correct
log.Printf("Request took %s\n", duration)
Pour aller plus loin
- Utilisation de Logrus : Un logger Go avec des niveaux de log flexibles et des fonctionnalités avancées.
- Prometheus : Un système de monitoring open source pour mesurer les KPIs d'une application.
- Grafana : Un outil de visualisation de données qui peut être utilisé avec Prometheus.
Défi pratique
Implémentez un système de logging et de monitoring pour une API RESTful en utilisant des librairies tierces comme Logrus ou Zap, et Prometheus pour le monitoring. Assurez-vous que votre API gère les erreurs correctement et que vous pouvez suivre la latence des requêtes.
Cela conclut ce tutoriel approfondi sur le logging et le monitoring en Go. En suivant ces étapes et en pratiquant régulièrement, vous serez bien équipé pour développer des applications robustes et fiables.