...
1 package logger
2
3 import (
4 "context"
5 "log/slog"
6 "os"
7 "strings"
8 "time"
9
10 "github.com/go-logr/logr"
11
12 "edge-infra.dev/pkg/lib/fog"
13 )
14
15 type opts struct {
16 logLvl slog.Level
17 }
18
19 type Option func(*opts)
20
21 const LevelTrace = slog.Level(-8)
22
23
24 var levels = map[slog.Level]int{
25 LevelTrace: -2,
26 slog.LevelDebug: fog.DEBUG,
27 slog.LevelInfo: fog.INFO,
28 slog.LevelWarn: fog.WARN,
29 slog.LevelError: fog.ERROR,
30 }
31
32
33 func WithLevel(lvl slog.Level) Option {
34 return func(o *opts) {
35 o.logLvl = lvl
36 }
37 }
38
39
40 func New(o ...Option) *slog.Logger {
41 options := &opts{}
42 for _, o := range o {
43 o(options)
44 }
45 return slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: options.logLvl, ReplaceAttr: replaceAttrs()})).With("severity", options.logLvl.String())
46 }
47
48
49 func IntoContext(ctx context.Context, log *slog.Logger) context.Context {
50 return logr.NewContextWithSlogLogger(ctx, log)
51 }
52
53
54 func FromContext(ctx context.Context) *slog.Logger {
55 newLog := logr.FromContextAsSlogLogger(ctx)
56 if newLog == nil {
57 return New()
58 }
59 return newLog
60 }
61
62
63 func ToLevel(logLevel string) slog.Level {
64 switch strings.ToLower(logLevel) {
65 case "trace":
66 return LevelTrace
67 case "debug":
68 return slog.LevelDebug
69 case "error":
70 return slog.LevelError
71 case "info":
72 return slog.LevelInfo
73 case "warn":
74 return slog.LevelWarn
75 default:
76 return slog.LevelInfo
77 }
78 }
79
80
81 func replaceAttrs() func(groups []string, a slog.Attr) slog.Attr {
82 return func(_ []string, attr slog.Attr) slog.Attr {
83 if attr.Key == slog.LevelKey {
84 level := attr.Value.Any().(slog.Level)
85 attr.Value = slog.IntValue(levels[level])
86 }
87 value := attr.Value
88 if value.Kind() != slog.KindTime {
89 return attr
90 }
91 attr.Value = slog.StringValue(value.Time().Format(time.RFC3339))
92 return attr
93 }
94 }
95
View as plain text