slog.Logger.With în Go

Returnează un logger nou care adaugă automat atributele date la fiecare mesaj.

Sintaxă
func (l *Logger) With(args ...any) *Logger

Ce face slog.Logger.With

logger.With("componenta", "plati", "versiune", "2.3") creează un logger derivat: fiecare mesaj scris prin el conține aceste atribute, fără să le repeți. Logger-ul original rămâne neschimbat.

Folosește-l ca să adaugi context o singură dată: numele componentei, ID-ul cererii HTTP, ID-ul utilizatorului. Handler-ele standard formatează atributele din With o singură dată, deci este și mai rapid decât să le dai la fiecare apel.

Parametri

Parametru Descriere
args Perechi cheie, valoare sau slog.Attr.

Ce returnează

Un *slog.Logger nou.

Exemple

Exemplul 1: Context pentru o cerere

package main

import (
    "log/slog"
    "os"
)

func faraTimp(groups []string, a slog.Attr) slog.Attr {
    if a.Key == slog.TimeKey && len(groups) == 0 {
        return slog.Attr{} // un atribut gol nu este afișat
    }
    return a
}

func main() {
    baza := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ReplaceAttr: faraTimp}))
    app := baza.With("app", "magazin", "versiune", "2.3")

    cerere := app.With("cerere", "req-81c2", "utilizator", 7)
    cerere.Info("coș deschis")
    cerere.Info("produs adăugat", "produs", "cafea")
    app.Info("statistici trimise") // fără atributele cererii
}

Rezultat

level=INFO msg="coș deschis" app=magazin versiune=2.3 cerere=req-81c2 utilizator=7
level=INFO msg="produs adăugat" app=magazin versiune=2.3 cerere=req-81c2 utilizator=7 produs=cafea
level=INFO msg="statistici trimise" app=magazin versiune=2.3

Exemplul 2: Originalul nu se schimbă

package main

import (
    "log/slog"
    "os"
)

func faraTimp(groups []string, a slog.Attr) slog.Attr {
    if a.Key == slog.TimeKey && len(groups) == 0 {
        return slog.Attr{} // un atribut gol nu este afișat
    }
    return a
}

func main() {
    a := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ReplaceAttr: faraTimp}))
    b := a.With("oras", "Iași")
    c := b.With("magazin", 3)

    a.Info("din a")
    b.Info("din b")
    c.Info("din c")
}

Rezultat

{"level":"INFO","msg":"din a"}
{"level":"INFO","msg":"din b","oras":"Iași"}
{"level":"INFO","msg":"din c","oras":"Iași","magazin":3}

Greșeli frecvente

  • Apelezi logger.With(...) și ignori rezultatul, apoi te miri că atributele nu apar. With nu modifică logger-ul; folosește valoarea returnată.
  • Adaugi aceeași cheie în With și în apel. Ambele apar în rând (de exemplu două id=), ceea ce încurcă filtrele.

Comenzi înrudite

  • slog.Logger.WithGroup: Returnează un logger nou care pune toate atributele următoare într-un grup cu numele dat.
  • slog.Logger: Tipul jurnalului structurat: are metodele Debug, Info, Warn, Error, Log și creează loggeri derivați cu With.
  • slog.Group: Grupează mai multe atribute sub un nume comun: în text devin grup.cheie=…, în JSON un obiect.