-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdecorate.go
110 lines (96 loc) · 3.19 KB
/
decorate.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
package golog
import (
"runtime"
"strconv"
"strings"
"time"
)
var (
// DefaultTimestampKeyName is default log key for timestamp.
DefaultTimestampKeyName = "ts"
// DefaultTimestampFormat is default format for timestamp.
DefaultTimestampFormat = "2006-01-02T15:04:05.000Z07:00"
// DefaultTimestampNowFunc is default function for get current timestamp.
DefaultTimestampNowFunc = time.Now
// DefaultCallerKeyName is default log key for caller information.
DefaultCallerKeyName = "caller"
// DefaultCallerDepth is default depth to skip while get stack information.
DefaultCallerDepth = 2
// DefaultCallerWithFullPath control whether if recording the full path of log source file.
DefaultCallerWithFullPath = false
// HandlerDefaultTimestamp is default timestamp handler with default settings.
HandlerDefaultTimestamp = HandlerTimestamp(DefaultTimestampKeyName, DefaultTimestampFormat, DefaultTimestampNowFunc)
// HandlerDefaultCaller is default caller handler with default settings.
HandlerDefaultCaller = HandlerCaller(DefaultCallerKeyName, DefaultCallerDepth, DefaultCallerWithFullPath)
)
// Filter discard log with condition.
type Filter func(level Level, kvs []interface{}) bool
// Handler modify log with anything.
type Handler func(level Level, kvs []interface{}) []interface{}
type decoratedLogger struct {
logger Logger
filter []Filter
handler []Handler
}
func (l *decoratedLogger) Log(level Level, kvs ...interface{}) {
for _, f := range l.filter {
if f(level, kvs) {
return
}
}
for _, f := range l.handler {
kvs = f(level, kvs)
}
l.logger.Log(level, kvs...)
}
// WithFilter decorate logger with filters
func WithFilter(logger Logger, filter ...Filter) Logger {
if l, ok := logger.(*decoratedLogger); ok {
return &decoratedLogger{
logger: l.logger,
filter: append(l.filter, filter...),
handler: l.handler,
}
}
return &decoratedLogger{logger: logger, filter: filter}
}
// WithHandler decorate logger with handlers
func WithHandler(logger Logger, handler ...Handler) Logger {
if l, ok := logger.(*decoratedLogger); ok {
return &decoratedLogger{
logger: l.logger,
filter: l.filter,
handler: append(l.handler, handler...),
}
}
return &decoratedLogger{logger: logger, handler: handler}
}
// FilterLevel filter log level less than specific level.
func FilterLevel(l Level) Filter {
return func(level Level, kvs []interface{}) bool {
return level < l
}
}
// HandlerTimestamp append timestamp information into log.
func HandlerTimestamp(keyName, valueFormat string, nowFunc func() time.Time) Handler {
return func(level Level, kvs []interface{}) []interface{} {
return append(kvs, keyName, nowFunc().Format(valueFormat))
}
}
// HandlerCaller append caller information into log.
func HandlerCaller(keyName string, depth int, withFullPath bool) Handler {
return func(level Level, kvs []interface{}) []interface{} {
_, file, line, _ := runtime.Caller(depth)
// skip caller in file helper.go
for strings.HasSuffix(file, "/helper.go") {
depth++
_, file, line, _ = runtime.Caller(depth)
}
if !withFullPath {
index := strings.LastIndexByte(file, '/')
file = file[index+1:]
}
value := file + ":" + strconv.Itoa(line)
return append(kvs, keyName, value)
}
}