-
Notifications
You must be signed in to change notification settings - Fork 45
/
logger.go
129 lines (106 loc) · 4.4 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
118
119
120
121
122
123
124
125
126
127
128
129
package utils
import (
"reflect"
"github.com/edaniels/golog"
"go.uber.org/zap"
)
// Logger is used various parts of the package for informational/debugging purposes.
var Logger = golog.Global()
// Debug is helpful to turn on when the library isn't working quite right.
var Debug = false
// ILogger is a basic logging interface for ContextualMain.
type ILogger interface {
Debug(...interface{})
Info(...interface{})
Warn(...interface{})
Fatal(...interface{})
}
// ZapCompatibleLogger is a basic logging interface for golog.Logger (alias for *zap.SugaredLogger) and RDK loggers.
type ZapCompatibleLogger interface {
Desugar() *zap.Logger
// Not defined: Named(name string) *zap.SugaredLogger
//
// Use `Sublogger(logger, "name")` instead of calling `Named` directly.
Debug(args ...interface{})
Debugf(template string, args ...interface{})
Debugw(msg string, keysAndValues ...interface{})
Info(args ...interface{})
Infof(template string, args ...interface{})
Infow(msg string, keysAndValues ...interface{})
Warn(args ...interface{})
Warnf(template string, args ...interface{})
Warnw(msg string, keysAndValues ...interface{})
Error(args ...interface{})
Errorf(template string, args ...interface{})
Errorw(msg string, keysAndValues ...interface{})
Fatal(args ...interface{})
Fatalf(template string, args ...interface{})
Fatalw(msg string, keysAndValues ...interface{})
}
// Sublogger creates a sublogger from the given ZapCompatibleLogger instance.
// This function uses reflection to dynamically create a sublogger from the provided logger by
// calling its `Sublogger` method if it is an RDK logger, or its `Named` method if it is a Zap logger.
// If neither method is available, it logs a debug message and returns the original logger.
func Sublogger(inp ZapCompatibleLogger, subname string) (loggerRet ZapCompatibleLogger) {
loggerRet = inp //nolint:wastedassign
// loggerRet is initialized to inp as a return value and is intentionally never re-assigned
// before calling functions that can panic so that defer + recover returns the original logger
defer func() {
if r := recover(); r != nil {
inp.Debugf("panic occurred while creating sublogger: %v, returning self", r)
}
}()
typ := reflect.TypeOf(inp)
sublogger, ok := typ.MethodByName("Sublogger")
if !ok {
sublogger, ok = typ.MethodByName("Named")
if !ok {
inp.Debugf("could not create sublogger from logger of type %s, returning self", typ.String())
return inp
}
}
// When using reflection to call receiver methods, the first argument must be the object.
// The remaining arguments are the actual function parameters.
ret := sublogger.Func.Call([]reflect.Value{reflect.ValueOf(inp), reflect.ValueOf(subname)})
loggerRet, ok = ret[0].Interface().(ZapCompatibleLogger)
if !ok {
inp.Debug("sublogger func returned an unexpected type, returning self")
return inp
}
return loggerRet
}
// AddFieldsToLogger attempts to add fields for logging to a given ZapCompatibleLogger instance.
// This function uses reflection to dynamically add fields to the provided logger by
// calling its `WithFields` method if it is an RDK logger. If the logger is not an RDK logger,
// it logs a debug message and returns the original logger.
// Args is expected to be a list of key-value pair(s).
func AddFieldsToLogger(inp ZapCompatibleLogger, args ...interface{}) (loggerRet ZapCompatibleLogger) {
loggerRet = inp //nolint:wastedassign
// loggerRet is initialized to inp as a return value and is intentionally never re-assigned
// before calling functions that can panic so that defer + recover returns the original logger
defer func() {
if r := recover(); r != nil {
inp.Debugf("panic occurred while adding fields to logger: %v, returning self", r)
}
}()
typ := reflect.TypeOf(inp)
with, ok := typ.MethodByName("WithFields")
if !ok {
inp.Debugf("could not add fields to logger of type %s, returning self", typ.String())
return inp
}
// When using reflection to call receiver methods, the first argument must be the object.
// The remaining arguments are the actual function parameters.
reflectArgs := make([]reflect.Value, len(args)+1)
reflectArgs[0] = reflect.ValueOf(inp)
for i, arg := range args {
reflectArgs[i+1] = reflect.ValueOf(arg)
}
ret := with.Func.Call(reflectArgs)
loggerRet, ok = ret[0].Interface().(ZapCompatibleLogger)
if !ok {
inp.Debug("with func returned an unexpected type, returning self")
return inp
}
return loggerRet
}