Comment logger en go
Quelles sont les différentes stratégies de log en golang? Le langage go en natif, des frameworks tles que logrus, zerolog ou bien le slog le dernier né. Exemples de logs en Go...
Petit rappel évident mais il faut bien garder en tête à quoi servent les logs. Généralement, il s'agit de traces techniques qui vous serviront à cerner plus rapidement un problème (fonctionnel, technique, de performance...) de votre service ou application. Il ne faut pas logger d'informations fonctionnelles ni personnelles.
En natif en go
Par défaut le langages offre au moins 2 possibilités pour ajouter des logs :
- utiliser le package "fmt" et printX comme par exemple
fmt.Printf("erreur de chargement de %s", maVariable)
Il est évident que cela n'est pas tenable sur le long terme au fur et à mesure que la base de code augmente, mais qui ne l'a jamais fait... ;-) - utiliser le package "log" et printX. Le package log natif est déjà très riche comme beaucoup d'autres packages natifs et évitent de se charger en dépendances externes.
package main
import (
"fmt"
"log"
)
func main() {
fmt.Printf("Exemple pour logger :\n")
log.Printf("mon premier log")
}
Le package log vous permet également de spécifier la sortie avec la méthode SetOutput(w io.Writer)
et vous pouvez définir aussi votre propre logger avec func New(out io.Writer, prefix string, flag int) *Logger
.
et le fichier logs.txt :
2022/06/20 12:06:51 mon premier log dans le fichier
INFO : 2022/06/20 12:06:51.716196 main.go:21: un log personnalisé
Vous pouvez aussi ajouter l'initialisation de votre système de log dans un répertoire utils et une fonction init()
par exemple :
package logging
import (
"log"
"os"
)
var (
Info *log.Logger
Warning *log.Logger
Error *log.Logger
Critical *log.Logger
)
func init() {
Info = log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
Warning = log.New(os.Stdout, "WARNING: ", log.Ldate|log.Ltime|log.Lshortfile)
Error = log.New(os.Stderr, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
Critical = log.New(os.Stderr, "CRITICAL: ", log.Ldate|log.Ltime|log.Lshortfile)
}
Cela reste intéressant pour des petits services ou utilitaires mais très vite il va manquer une rotation des fichiers, de la distribution pour un usage multi services...
Avec des librairies externes
Une des plus connues est certainement logrus. Seulement elle est passée en mode maintenance. Cela n'empêche pas de l'utiliser ni qu'elle soit utilisée dans de gros projets tel que Docker :
ou encore si vous utilisez datadog, ils privilégient logrus.
glog n'est également plus vraiment maintenue. C'est pourquoi les équipes de Kubernetees ont fait un fork pour leur projet :
Dans un projet interne, j'ai implémenté zerolog. Cela permet de bien structurer ses logs mais on arrive très vite à beaucoup de code et de verbosité. IMHO, il devient intéressant à utiliser dans des projets de monitoring et donc couplé à des outils de visualisation de logs (Grafana, Kibana...)
Il y a beaucoup d'autres librairies mais le point important est de bien déterminer ce que l'on veut de ses logs...
Note du 28/12/2022 :
Un nouveau package est en cours et fera peut être son entrée dans une version future de go:
https://pkg.go.dev/golang.org/x/exp/slog
Avec ce package, vous pouvez directement écrire un :
slog.Info("une info en stdout")
# ou bien en declarant un text handler ou json handler :
textHandler := slog.NewTextHandler(os.Stdout)
logger := slog.New(textHandler)
logger.Info("une info supplémentaire", slog.Int("compteur", 10))
et il semble que les perfs soient bonnes (mais non vérifié).