44 lines
1.7 KiB
Go
44 lines
1.7 KiB
Go
// Package logging builds the single *slog.Logger instance shared across the
|
|||
|
|
// whole application. Every log line the app writes goes through this
|
||
|
|
// logger, formatted as JSON to stdout.
|
||
|
|
//
|
||
|
|
// Why JSON to stdout specifically? This is the standard "12-factor app"
|
||
|
|
// approach to logging: the application doesn't know or care where its logs
|
||
|
|
// end up (a file, Loki, Elasticsearch, ...) - it just writes structured
|
||
|
|
// lines to stdout, and an external agent (in your case, Grafana Alloy)
|
||
|
|
// takes care of collecting, parsing, and shipping them. Because every line
|
||
|
|
// is valid JSON with consistent keys, Alloy/Loki can index and query on
|
||
|
|
// fields like "status", "path", or "request_id" without any custom parsing
|
||
|
|
// rules or regexes.
|
||
|
|
package logging
|
||
|
|
|
||
|
|
import (
|
||
|
|
"log/slog"
|
||
|
|
"os"
|
||
|
|
)
|
||
|
|
|
||
|
|
// New builds and returns the application's structured logger.
|
||
|
|
//
|
||
|
|
// The minimum log level is controlled by the LOG_LEVEL environment
|
||
|
|
// variable: set LOG_LEVEL=debug to see verbose Debug()-level output;
|
||
|
|
// anything else (or unset) defaults to Info level, which hides Debug logs.
|
||
|
|
func New() *slog.Logger {
|
||
|
|
level := slog.LevelInfo
|
||
|
|
if os.Getenv("LOG_LEVEL") == "debug" {
|
||
|
|
level = slog.LevelDebug
|
||
|
|
}
|
||
|
|
|
||
|
|
// slog.NewJSONHandler formats every log record as a single-line JSON
|
||
|
|
// object and writes it to the given io.Writer (here, os.Stdout).
|
||
|
|
// Swapping this for slog.NewTextHandler would switch to human-readable
|
||
|
|
// text output instead - useful for local dev if you ever want it - but
|
||
|
|
// every other part of the app that calls logger.Info/Error/etc would
|
||
|
|
// stay completely unchanged, since they only depend on *slog.Logger,
|
||
|
|
// not on which Handler is behind it.
|
||
|
|
handler := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
|
||
|
|
Level: level,
|
||
|
|
})
|
||
|
|
|
||
|
|
return slog.New(handler)
|
||
|
|
}
|