-
Notifications
You must be signed in to change notification settings - Fork 0
/
logger.go
150 lines (124 loc) · 3.32 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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package logger
import (
"strings"
"time"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
type Logger struct {
zapLogger *zap.Logger
level *zap.AtomicLevel
}
type config struct {
zap.Config
callerSkip int
}
type option func(*config) error
var defaultLogger *Logger
func init() {
var err error
defaultLogger, err = NewLogger()
if err != nil {
panic(err)
}
}
// Initialize the logger with configuration options
// Follows the "Functional Options Pattern" for configuration. Described at:
// https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
func Initialize(options ...option) (err error) {
defaultLogger, err = NewLogger(options...)
if err != nil {
return err
}
return nil
}
func NewLogger(opts ...option) (*Logger, error) {
conf := &config{zap.NewProductionConfig(), 1} // default skip of 1
opts = append(opts, timestamp())
for _, opt := range opts {
err := opt(conf)
if err != nil {
return nil, err
}
}
zapLogger, err := conf.Build(
zap.AddStacktrace(zapcore.DPanicLevel), // Automatically add stack trace above this level
zap.AddCallerSkip(conf.callerSkip), // skip configured level to print the correct caller
)
if err != nil {
return nil, err
}
l := &Logger{
zapLogger: zapLogger,
level: &conf.Level,
}
return l, nil
}
// Formatter sets the log format to development friendly text or production friendly JSON
// based on the config value
// Allowed values: "text", "json"
func Formatter(format string) option {
return func(conf *config) error {
switch format {
case "text", "ascii", "terminal":
conf.Encoding = "console"
default:
conf.Encoding = "json"
}
return nil
}
}
// Level sets the logging level.
// Allowed values in decreasing order of verbosity - "debug", "info", "warning", "error", "fatal", "panic"
// Setting a higher logging level will ignore logs from lower levels in output
// Default: "info"
func Level(level string) option {
return func(conf *config) error {
lvl := parseLevelString(level)
conf.Level.SetLevel(lvl)
return nil
}
}
// CallerSkip add specified skip frames while reporting caller
// should be used to make caller to appropriate frame if this pkg
// is not used in vanilla form. Multiple calls are not additive.
func CallerSkip(skip int) option {
return func(conf *config) error {
conf.callerSkip = skip
return nil
}
}
// timestamp sets the time key name and format
func timestamp() option {
return func(conf *config) error {
conf.EncoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout(time.RFC3339Nano)
conf.EncoderConfig.TimeKey = "@timestamp"
return nil
}
}
// Sync flushes any buffered log entries
func Sync() error {
return defaultLogger.zapLogger.Sync()
}
// Sync flushes any buffered log entries
func (logger *Logger) Sync() error {
return logger.zapLogger.Sync()
}
func parseLevelString(level string) zapcore.Level {
switch strings.ToLower(level) {
case "debug":
return zapcore.DebugLevel
case "info":
return zapcore.InfoLevel
case "warn", "warning":
return zapcore.WarnLevel
case "error":
return zapcore.ErrorLevel
case "fatal":
return zapcore.FatalLevel
case "panic":
return zapcore.PanicLevel
default:
return zapcore.InfoLevel
}
}