/
hierarchy.go
71 lines (58 loc) · 1.75 KB
/
hierarchy.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
package log
import (
"os"
"sync/atomic"
)
// DefaultLogger is a root hierarchy logger that other packages can point to. By default it logs to stderr
var DefaultLogger = NewHierarchy(NewLogfmtLogger(os.Stderr, Discard))
// LoggingEnv is the env variable that if exported to /dev/null can disable the default logger
const LoggingEnv = "GOLIB_LOG"
func init() {
DefaultLogger.setupFromEnv(os.Getenv)
}
// Hierarchy is a type of logger that an atomically point to another logger. It's primary usage is as a hierarchy of
// loggers where one defaults to another if not set.
type Hierarchy struct {
logger atomic.Value
}
type atomicStruct struct {
logger Logger
}
// NewHierarchy creates a Hierarchy type pointer pointing to defaultLogger
func NewHierarchy(defaultLogger Logger) *Hierarchy {
ret := &Hierarchy{}
ret.Set(defaultLogger)
return ret
}
func (l *Hierarchy) setupFromEnv(getEnv func(string) string) {
v := getEnv(LoggingEnv)
if v == "/dev/null" || v == os.DevNull {
l.Set(Discard)
return
}
}
// Log calls log of the wrapped logger
func (l *Hierarchy) Log(kvs ...interface{}) {
// Note: Log here messes up "caller" :/
if logger := l.loadLogger(); logger != nil {
logger.Log(kvs...)
}
}
// Disabled is true if the wrapped logger is disabled
func (l *Hierarchy) Disabled() bool {
return IsDisabled(l.loadLogger())
}
// CreateChild returns a logger that points to this one by default
func (l *Hierarchy) CreateChild() *Hierarchy {
return NewHierarchy(l)
}
func (l *Hierarchy) loadLogger() Logger {
if logger, ok := l.logger.Load().(atomicStruct); ok && logger.logger != nil {
return logger.logger
}
return nil
}
// Set atomically changes where this logger logs to
func (l *Hierarchy) Set(logger Logger) {
l.logger.Store(atomicStruct{logger})
}