Documentation ¶
Overview ¶
Package slogutil contains extensions and utilities for package log/slog from the standard library.
Index ¶
- Constants
- func New(c *Config) (l *slog.Logger)
- func NewDiscardLogger() (l *slog.Logger)
- func PrintStack(ctx context.Context, l *slog.Logger, lvl slog.Level)
- func RecoverAndLog(ctx context.Context, l *slog.Logger)
- func RemoveTime(groups []string, a slog.Attr) (res slog.Attr)
- type AdGuardLegacyHandler
- func (h *AdGuardLegacyHandler) Enabled(ctx context.Context, lvl slog.Level) (ok bool)
- func (h *AdGuardLegacyHandler) Handle(ctx context.Context, r slog.Record) (err error)
- func (h *AdGuardLegacyHandler) WithAttrs(attrs []slog.Attr) (res slog.Handler)
- func (h *AdGuardLegacyHandler) WithGroup(g string) (res slog.Handler)
- type BadFormatError
- type Config
- type DiscardHandler
- type Format
- type JSONHybridHandler
- func (h *JSONHybridHandler) Enabled(ctx context.Context, level slog.Level) (ok bool)
- func (h *JSONHybridHandler) Handle(ctx context.Context, r slog.Record) (err error)
- func (h *JSONHybridHandler) WithAttrs(attrs []slog.Attr) (res slog.Handler)
- func (h *JSONHybridHandler) WithGroup(g string) (res slog.Handler)
- type LevelHandler
- func (h *LevelHandler) Enabled(_ context.Context, level slog.Level) (ok bool)
- func (h *LevelHandler) Handle(ctx context.Context, r slog.Record) (err error)
- func (h *LevelHandler) Handler() (unwrapped slog.Handler)
- func (h *LevelHandler) WithAttrs(attrs []slog.Attr) (res slog.Handler)
- func (h *LevelHandler) WithGroup(name string) (res slog.Handler)
Examples ¶
Constants ¶
const ( FormatAdGuardLegacy = "adguard_legacy" FormatDefault = "default" FormatJSON = "json" FormatJSONHybrid = "jsonhybrid" FormatText = "text" )
Valid formats.
const ( KeyPrefix = "prefix" KeyError = "err" )
Additional key constants.
Variables ¶
This section is empty.
Functions ¶
func New ¶
New creates a slog logger with the given parameters. If c is nil, the defaults are used.
NOTE: If c.Format is FormatAdGuardLegacy, the legacy logger parameters, such as output, should be set separately.
Example (Default) ¶
package main import ( "github.com/AdguardTeam/golibs/logutil/slogutil" ) func main() { l := slogutil.New(&slogutil.Config{ Verbose: true, }) l.Info("test info") l.Debug("test debug") }
Output: INFO test info DEBUG test debug
Example (Json) ¶
package main import ( "github.com/AdguardTeam/golibs/logutil/slogutil" ) func main() { l := slogutil.New(&slogutil.Config{ Format: slogutil.FormatJSON, Verbose: true, }) l.Info("test info") l.Debug("test debug") l.WithGroup("test_group").Info("group test info", "time", "too late") l.WithGroup("test_group").Debug("group test debug", "time", "too late") }
Output: {"level":"INFO","msg":"test info"} {"level":"DEBUG","msg":"test debug"} {"level":"INFO","msg":"group test info","test_group":{"time":"too late"}} {"level":"DEBUG","msg":"group test debug","test_group":{"time":"too late"}}
Example (Text) ¶
package main import ( "github.com/AdguardTeam/golibs/logutil/slogutil" ) func main() { l := slogutil.New(&slogutil.Config{ Format: slogutil.FormatText, Verbose: true, }) l.Info("test info") l.Debug("test debug") l.WithGroup("test_group").Info("group test info", "time", "too late") l.WithGroup("test_group").Debug("group test debug", "time", "too late") }
Output: level=INFO msg="test info" level=DEBUG msg="test debug" level=INFO msg="group test info" test_group.time="too late" level=DEBUG msg="group test debug" test_group.time="too late"
func NewDiscardLogger ¶ added in v0.17.3
NewDiscardLogger returns a new logger that uses DiscardHandler.
func PrintStack ¶ added in v0.17.3
PrintStack logs the stacktrace into l on the given level.
func RecoverAndLog ¶ added in v0.17.3
RecoverAndLog is a deferred helper that recovers from a panic and logs the panic value into l along with the stacktrace.
func RemoveTime ¶
RemoveTime is a function for slog.HandlerOptions.ReplaceAttr that removes the "time" attribute.
Types ¶
type AdGuardLegacyHandler ¶ added in v0.20.0
type AdGuardLegacyHandler struct {
// contains filtered or unexported fields
}
AdGuardLegacyHandler is a text slog.Handler that uses package github.com/AdguardTeam/golibs/log for output. It is a legacy handler that will be removed in a future version.
The attribute with the name KeyPrefix is handled separately. Like in the legacy logging conventions, it is prepended to the message. There should only be one such attribute between the logger and the message.
Example of output:
12#34 [debug] debug with no attributes 12#34 [info] hdlr: info with prefix and attrs number=123
Example ¶
package main import ( "bytes" "fmt" "log/slog" "strings" aglog "github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/logutil/slogutil" ) func main() { // Use a buffer to remove the PID#GID prefix. output := &bytes.Buffer{} aglog.SetOutput(output) aglog.SetFlags(0) aglog.SetLevel(aglog.DEBUG) h := slogutil.NewAdGuardLegacyHandler(slog.LevelDebug) l := slog.New(h) l.Debug("debug with no attributes") l.Debug("debug with attributes", "number", 123) l.Info("info with no attributes") l.Info("info with attributes", "number", 123) l = l.With(slogutil.KeyPrefix, "hdlr") l.Info("info with prefix") l.Warn("warning with two prefixes (bad!)", slogutil.KeyPrefix, "bad") // Remove the PID#GID prefix for a reproducible example. for _, line := range strings.Split(output.String(), "\n") { _, line, _ = strings.Cut(line, " ") fmt.Println(line) } }
Output: [debug] debug with no attributes [debug] debug with attributes number=123 [info] info with no attributes [info] info with attributes number=123 [info] hdlr: info with prefix [debug] legacy logger: got prefix "bad" in record for logger with prefix "hdlr" [info] hdlr: warning: warning with two prefixes (bad!)
func NewAdGuardLegacyHandler ¶ added in v0.20.0
func NewAdGuardLegacyHandler(lvl slog.Leveler) (h *AdGuardLegacyHandler)
NewAdGuardLegacyHandler creates a new properly initialized *AdGuardLegacyHandler. Output, level, and other flags should be set in the legacy logging package. lvl is used for AdGuardLegacyHandler.Enabled.
func (*AdGuardLegacyHandler) Enabled ¶ added in v0.20.0
Enabled implements the slog.Handler interface for *AdGuardLegacyHandler.
func (*AdGuardLegacyHandler) Handle ¶ added in v0.20.0
Handle implements the slog.Handler interface for *AdGuardLegacyHandler.
func (*AdGuardLegacyHandler) WithAttrs ¶ added in v0.20.0
func (h *AdGuardLegacyHandler) WithAttrs(attrs []slog.Attr) (res slog.Handler)
WithAttrs implements the slog.Handler interface for *AdGuardLegacyHandler.
func (*AdGuardLegacyHandler) WithGroup ¶ added in v0.20.0
func (h *AdGuardLegacyHandler) WithGroup(g string) (res slog.Handler)
WithGroup implements the slog.Handler interface for *AdGuardLegacyHandler.
NOTE: It is currently not supported and panics.
TODO(a.garipov): Support groups, see https://github.com/golang/example/blob/master/slog-handler-guide/README.md.
type BadFormatError ¶
type BadFormatError struct {
Format string
}
BadFormatError is an error about a bad logging format.
func (*BadFormatError) Error ¶
func (err *BadFormatError) Error() (msg string)
Error implements the [error] interface for *BadFormatError.
type Config ¶
type Config struct { // Output is the output destination. If not set, [os.Stdout] is used. Output io.Writer // Format is the format for the logs. If not set, [FormatDefault] is used. // If set, it must be valid. Format Format // AddTimestamp, if true, adds a timestamp to every record. AddTimestamp bool // Verbose, if true, enables verbose logging. Verbose bool }
Config contains the configuration for a logger.
type DiscardHandler ¶ added in v0.17.3
type DiscardHandler struct{}
DiscardHandler ignores all messages.
func (DiscardHandler) Enabled ¶ added in v0.17.3
Enabled implements the slog.Handler interface for DiscardHandler. It always returns false.
func (DiscardHandler) Handle ¶ added in v0.17.3
Handle implements the slog.Handler interface for DiscardHandler. It always returns nil.
func (DiscardHandler) WithAttrs ¶ added in v0.17.3
func (h DiscardHandler) WithAttrs(_ []slog.Attr) (res slog.Handler)
WithAttrs implements the slog.Handler interface for DiscardHandler. It always returns h.
func (DiscardHandler) WithGroup ¶ added in v0.17.3
func (h DiscardHandler) WithGroup(_ string) (res slog.Handler)
WithGroup implements the slog.Handler interface for DiscardHandler. It always returns h.
type JSONHybridHandler ¶ added in v0.18.2
type JSONHybridHandler struct {
// contains filtered or unexported fields
}
JSONHybridHandler is a hybrid JSON-and-text slog.Handler more suitable for stricter environments. It guarantees that the only properties present in the resulting objects are "level", "msg", "time", and "source", depending on the options. All other attributes are packed into the "msg" property using the same format as slogutil.TextHandler.
NOTE: JSONHybridHandler.WithGroup is not currently supported and panics.
Example of output:
{"time":"2023-12-01T12:34:56.789Z","level":"INFO","msg":"listening; attrs: prefix=websvc url=http://127.0.0.1:8080"}
Example ¶
package main import ( "log/slog" "os" "github.com/AdguardTeam/golibs/logutil/slogutil" ) func main() { h := slogutil.NewJSONHybridHandler(os.Stdout, &slog.HandlerOptions{ AddSource: false, Level: slog.LevelDebug, // Use slogutil.RemoveTime to make the example reproducible. ReplaceAttr: slogutil.RemoveTime, }) l := slog.New(h) l.Debug("debug with no attributes") l.Debug("debug with attributes", "number", 123) l.Info("info with no attributes") l.Info("info with attributes", "number", 123) l = l.With("attr", "abc") l.Info("new info with no attributes") l.Info("new info with attributes", "number", 123) }
Output: {"level":"DEBUG","msg":"debug with no attributes"} {"level":"DEBUG","msg":"debug with attributes; attrs: number=123"} {"level":"INFO","msg":"info with no attributes"} {"level":"INFO","msg":"info with attributes; attrs: number=123"} {"level":"INFO","msg":"new info with no attributes; attrs: attr=abc"} {"level":"INFO","msg":"new info with attributes; attrs: attr=abc number=123"}
func NewJSONHybridHandler ¶ added in v0.18.2
func NewJSONHybridHandler(w io.Writer, opts *slog.HandlerOptions) (h *JSONHybridHandler)
NewJSONHybridHandler creates a new properly initialized *JSONHybridHandler. opts are used for the underlying JSON handler.
func (*JSONHybridHandler) Enabled ¶ added in v0.18.2
Enabled implements the slog.Handler interface for *JSONHybridHandler.
func (*JSONHybridHandler) Handle ¶ added in v0.18.2
Handle implements the slog.Handler interface for *JSONHybridHandler.
func (*JSONHybridHandler) WithAttrs ¶ added in v0.18.2
func (h *JSONHybridHandler) WithAttrs(attrs []slog.Attr) (res slog.Handler)
WithAttrs implements the slog.Handler interface for *JSONHybridHandler.
func (*JSONHybridHandler) WithGroup ¶ added in v0.18.2
func (h *JSONHybridHandler) WithGroup(g string) (res slog.Handler)
WithGroup implements the slog.Handler interface for *JSONHybridHandler.
NOTE: It is currently not supported and panics.
TODO(a.garipov): Support groups, see https://github.com/golang/example/blob/master/slog-handler-guide/README.md.
type LevelHandler ¶
type LevelHandler struct {
// contains filtered or unexported fields
}
A LevelHandler wraps a Handler with an Enabled method that returns false for levels below a minimum.
See https://cs.opensource.google/go/x/exp/+/master:slog/example_level_handler_test.go.
func NewLevelHandler ¶
func NewLevelHandler(level slog.Leveler, h slog.Handler) (lh *LevelHandler)
NewLevelHandler returns a LevelHandler with the given level. All methods except Enabled delegate to h.
func (*LevelHandler) Enabled ¶
Enabled implements the slog.Handler interface for *LevelHandler. It reports whether level is as high as h's level.
func (*LevelHandler) Handle ¶
Handle implements the slog.Handler interface for *LevelHandler.
func (*LevelHandler) Handler ¶
func (h *LevelHandler) Handler() (unwrapped slog.Handler)
Handler returns the slog.Handler wrapped by h.
func (*LevelHandler) WithAttrs ¶
func (h *LevelHandler) WithAttrs(attrs []slog.Attr) (res slog.Handler)
WithAttrs implements the slog.Handler interface for *LevelHandler.
func (*LevelHandler) WithGroup ¶
func (h *LevelHandler) WithGroup(name string) (res slog.Handler)
WithGroup implements the slog.Handler interface for *LevelHandler.