slog.HandlerOptions în Go

Opțiunile handler-elor text și JSON: nivelul minim, adăugarea fișierului sursă și modificarea oricărui atribut.

Sintaxă
type HandlerOptions struct {
    AddSource   bool
    Level       Leveler
    ReplaceAttr func(groups []string, a Attr) Attr
}

Ce face slog.HandlerOptions

slog.HandlerOptions se dă ca al doilea argument lui NewTextHandler și NewJSONHandler. Level este nivelul minim (o constantă ca slog.LevelDebug sau un *slog.LevelVar); lipsa lui înseamnă INFO. AddSource: true adaugă atributul source cu fișierul și linia apelului.

ReplaceAttr este apelată pentru fiecare atribut înainte de scriere și poate schimba cheia sau valoarea, ori îl poate elimina (returnând slog.Attr{}). Așa elimini ora (cheia slog.TimeKey), redenumești msg în message, ascunzi parole sau schimbi formatul nivelului. Argumentul groups arată în ce grup se află atributul (gol pentru cele de la nivelul de sus).

Parametri

Parametru Descriere
AddSource true = adaugă fișierul și linia de unde a fost scris mesajul.
Level Nivelul minim afișat.
ReplaceAttr Funcție care modifică sau elimină atribute.

Ce returnează

Nu se aplică (este o structură de opțiuni).

Exemple

Exemplul 1: Fără oră, cu chei redenumite și parola ascunsă

package main

import (
    "log/slog"
    "os"
    "strings"
)

func main() {
    opt := &slog.HandlerOptions{
        Level: slog.LevelDebug,
        ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
            switch {
            case a.Key == slog.TimeKey && len(groups) == 0:
                return slog.Attr{} // eliminăm ora
            case a.Key == slog.MessageKey:
                a.Key = "mesaj"
            case a.Key == slog.LevelKey:
                a.Key = "nivel"
                a.Value = slog.StringValue(strings.ToLower(a.Value.String()))
            case a.Key == "parola":
                a.Value = slog.StringValue("***")
            }
            return a
        },
    }
    logger := slog.New(slog.NewJSONHandler(os.Stdout, opt))
    logger.Debug("autentificare", "utilizator", "ana", "parola", "Secret!2025")
    logger.Info("profil actualizat", "utilizator", "ana")
}

Rezultat

{"nivel":"debug","mesaj":"autentificare","utilizator":"ana","parola":"***"}
{"nivel":"info","mesaj":"profil actualizat","utilizator":"ana"}

Exemplul 2: AddSource

Ca să nu depindem de calea directorului, păstrăm din source doar numele fișierului și linia.

package main

import (
    "fmt"
    "log/slog"
    "os"
    "path/filepath"
)

func main() {
    opt := &slog.HandlerOptions{
        AddSource: true,
        ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
            if a.Key == slog.TimeKey && len(groups) == 0 {
                return slog.Attr{}
            }
            if src, ok := a.Value.Any().(*slog.Source); ok {
                return slog.String(slog.SourceKey, fmt.Sprintf("%s:%d", filepath.Base(src.File), src.Line))
            }
            return a
        },
    }
    logger := slog.New(slog.NewTextHandler(os.Stdout, opt))
    logger.Warn("stoc mic", "produs", "cafea")
}

Rezultat

level=WARN source=main.go:24 msg="stoc mic" produs=cafea

Greșeli frecvente

  • Elimini cheia time fără să verifici len(groups) == 0. Un atribut al tău numit tot time, aflat într-un grup, ar dispărea și el.
  • Dai nil ca opțiuni și te aștepți la mesaje DEBUG. Nivelul implicit este INFO.

Comenzi înrudite

  • slog.Level: Tipul nivelului unui mesaj (DEBUG, INFO, WARN, ERROR); valorile mai mari înseamnă mesaje mai importante.
  • slog.NewTextHandler: Creează un handler care scrie fiecare mesaj ca un rând de perechi cheie=valoare (format logfmt).
  • slog.NewJSONHandler: Creează un handler care scrie fiecare mesaj ca un obiect JSON pe un rând, potrivit pentru servere și cloud.
  • slog.Debug: Scrie un mesaj de nivel DEBUG, cu detalii pentru depanare; implicit aceste mesaje nu sunt afișate.