package rlog import ( "log/slog" "os" "github.com/rs/zerolog" slogmulti "github.com/samber/slog-multi" slogzerolog "github.com/samber/slog-zerolog" ) const errKey = "error" const labelGroupKey = "labelGroup" var zl = zerolog.New(&zerolog.ConsoleWriter{Out: os.Stderr}) var handlers = []slog.Handler{ slogzerolog.Option{Logger: &zl}.NewZerologHandler(), } var defaultLogger = slog.New(slogmulti.Fanout(handlers...)) func init() { slog.SetDefault(defaultLogger) } func AddHandler(nh slog.Handler) { handlers = append(handlers, nh) defaultLogger = slog.New(slogmulti.Fanout(handlers...)) slog.SetDefault(defaultLogger) } func ComponentLog(name string) *slog.Logger { return defaultLogger.With(slog.String("component", name)) } func ServiceLog(name string) *slog.Logger { return ComponentLog("service/" + name) } func FunctionLog(log *slog.Logger, name string) *slog.Logger { return log.With(slog.String("function", name)) } func EndpointLog(log *slog.Logger, name string) *slog.Logger { return log.With(slog.String("endpoint", name)) } func Err(err error) slog.Attr { return slog.Attr{Key: errKey, Value: fmtErr(err)} } func Label(args ...any) slog.Attr { return slog.Group(labelGroupKey, args...) } // fmtErr returns a slog.GroupValue with keys "msg" and "trace". If the error // does not implement interface { StackTrace() errors.StackTrace }, the "trace" // key is omitted. func fmtErr(err error) slog.Value { if err == nil { return slog.AnyValue(nil) } var groupValues []slog.Attr groupValues = append(groupValues, slog.String("msg", err.Error())) return slog.GroupValue(groupValues...) }