-
-
Notifications
You must be signed in to change notification settings - Fork 23
/
logger.go
117 lines (95 loc) · 2.79 KB
/
logger.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package adapter
import (
"fmt"
"log"
"strings"
"sync"
)
// KeyError is the default key for error field
const KeyError = "error"
type (
// Field is the simple container for a single log field
Field struct {
Key string
Value any
}
// Logger declares base logging methods
Logger interface {
Debug(msg string, fields ...Field)
Info(msg string, fields ...Field)
Error(msg string, fields ...Field)
With(fields ...Field) Logger
}
// NoOpLogger implements Logger that does nothing, all logs are going to /dev/null
NoOpLogger struct{}
// StdLogger implements Logger that uses stdlib "log" as output
StdLogger struct {
fields *sync.Map
fLen int
}
)
// F returns value as field
func F(key string, value any) Field {
return Field{Key: key, Value: value}
}
// Err returns error as field
func Err(err error) Field {
return F(KeyError, err)
}
// Debug implements Logger.Debug for /dev/null logger
func (l NoOpLogger) Debug(string, ...Field) {}
// Info implements Logger.Debug for /dev/null logger
func (l NoOpLogger) Info(string, ...Field) {}
// Error implements Logger.Debug for /dev/null logger
func (l NoOpLogger) Error(string, ...Field) {}
// With implements nested logger for /dev/null logger
func (l NoOpLogger) With(...Field) Logger {
return l
}
// NewStdLogger instantiates new Logger using stdlib "log".
// Builder allows to set default set of fields for all the logs being written.
func NewStdLogger(fields ...Field) *StdLogger {
f := new(sync.Map)
for _, ff := range fields {
f.Store(ff.Key, ff.Value)
}
return &StdLogger{f, len(fields)}
}
// Debug implements Logger.Debug for stdlib "log" logger
func (l *StdLogger) Debug(msg string, fields ...Field) {
log.Printf("%s %s", msg, l.buildContext("debug", fields...))
}
// Info implements Logger.Debug for stdlib "log" logger
func (l *StdLogger) Info(msg string, fields ...Field) {
log.Printf("%s %s", msg, l.buildContext("info", fields...))
}
// Error implements Logger.Debug for stdlib "log" logger
func (l *StdLogger) Error(msg string, fields ...Field) {
log.Printf("%s %s", msg, l.buildContext("error", fields...))
}
// With implements nested logger for stdlib "log" logger
func (l *StdLogger) With(fields ...Field) Logger {
f := new(sync.Map)
fLen := len(fields)
l.fields.Range(func(key, value any) bool {
f.Store(key, value)
fLen++
return true
})
for _, ff := range fields {
f.Store(ff.Key, ff.Value)
}
return &StdLogger{f, fLen}
}
func (l *StdLogger) buildContext(level string, fields ...Field) string {
ctx := make([]string, 0, len(fields)+l.fLen+1)
ctx = append(ctx, "level="+level)
l.fields.Range(func(key, value any) bool {
ctx = append(ctx, fmt.Sprintf("%s=%v", key, value))
return true
})
for _, f := range fields {
ctx = append(ctx, fmt.Sprintf("%s=%v", f.Key, f.Value))
}
return strings.Join(ctx, " ")
}