-
Notifications
You must be signed in to change notification settings - Fork 1
/
global.go
214 lines (185 loc) · 6.39 KB
/
global.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
package zlog
import (
"fmt"
"sync/atomic"
"go.uber.org/zap"
"github.com/jxskiss/gopkg/v2/internal/logfilter"
)
var globals struct {
Default, Skip1 struct {
L *zap.Logger
S *zap.SugaredLogger
}
Props *Properties
// Level is a copy of Props.level for fast path accessing.
Level atomic.Int32
}
func init() {
ReplaceGlobals(mustNewGlobalLogger(&Config{}))
}
// Properties holds some information about the global config and logger.
type Properties struct {
cfg GlobalConfig
disableCaller bool
level zap.AtomicLevel
traceFilter *logfilter.FileNameFilter
closers []func()
}
// CloseWriters close all writers associated with this Properties object.
func (p *Properties) CloseWriters() {
runClosers(p.closers)
}
func (p *Properties) setupGlobals() func() {
if p.cfg.MethodNameKey == "" {
p.cfg.MethodNameKey = defaultMethodNameKey
}
var resetStdLog = func() {}
if p.cfg.RedirectStdLog {
resetStdLog = redirectStdLog(L().Logger, p.disableCaller)
}
p.compileTraceFilter()
globals.Level.Store(int32(p.level.Level()))
return func() {
resetStdLog()
}
}
// ReplaceGlobals replaces the global Logger and SugaredLogger,
// and returns a function to restore the original values.
//
// It is meant to be called at program startup, library code shall not call
// this function.
func ReplaceGlobals(logger *zap.Logger, props *Properties) func() {
oldL, oldP := globals.Default.L, globals.Props
globals.Default.L = logger
globals.Default.S = logger.Sugar()
globals.Skip1.L = logger.WithOptions(zap.AddCallerSkip(1))
globals.Skip1.S = globals.Skip1.L.Sugar()
globals.Props = props
resetProps := props.setupGlobals()
zap.ReplaceGlobals(logger)
return func() {
resetProps()
ReplaceGlobals(oldL, oldP)
}
}
// SetDevelopment is a shortcut of SetupGlobals with default configuration
// for development. It sets the global logger in development mode,
// and redirects output from the standard log library's package-global
// logger to the global logger in this package.
//
// It is meant to be called at program startup, when you run in development
// mode, for production mode, please check SetupGlobals and ReplaceGlobals.
func SetDevelopment() {
cfg := &Config{}
cfg.Development = true
cfg.RedirectStdLog = true
ReplaceGlobals(mustNewGlobalLogger(cfg))
}
// SetupGlobals setups the global loggers in this package and zap library.
// By default, global loggers are set with default configuration with info
// level and json format, you may use this function to change the default
// loggers.
//
// See Config and GlobalConfig for available configurations.
//
// It is meant to be called at program startup, library code shall not call
// this function.
func SetupGlobals(cfg *Config, opts ...zap.Option) {
ReplaceGlobals(mustNewGlobalLogger(cfg, opts...))
}
func mustNewGlobalLogger(cfg *Config, opts ...zap.Option) (*zap.Logger, *Properties) {
logger, props, err := New(cfg, opts...)
if err != nil {
panic("zlog: invalid config to initialize logger: " + err.Error())
}
return logger, props
}
// CloseWriters close all writers opened by the global logger.
func CloseWriters() {
globals.Props.CloseWriters()
}
// GetLevel gets the global logging level.
func GetLevel() Level { return globals.Props.level.Level() }
// SetLevel modifies the global logging level on the fly.
// It's safe for concurrent use.
func SetLevel(lvl Level) {
globals.Props.level.SetLevel(lvl)
globals.Level.Store(int32(lvl))
}
// L returns the global Logger, which can be reconfigured with
// SetupGlobals and ReplaceGlobals.
func L() Logger { return Logger{Logger: globals.Default.L} }
// S returns the global SugaredLogger, which can be reconfigured with
// SetupGlobals and ReplaceGlobals.
func S() SugaredLogger { return SugaredLogger{SugaredLogger: globals.Default.S} }
// Sync flushes any buffered log entries.
func Sync() error {
// Since all global loggers share a same underlying core,
// calling L().Sync() is enough to flush all pending log messages.
return L().Sync()
}
// -------- global logging functions -------- //
func _l() Logger { return Logger{Logger: globals.Skip1.L} }
func _s() SugaredLogger { return SugaredLogger{SugaredLogger: globals.Skip1.S} }
func Debug(msg string, fields ...zap.Field) { _l().Debug(msg, fields...) }
func Info(msg string, fields ...zap.Field) { _l().Info(msg, fields...) }
func Warn(msg string, fields ...zap.Field) { _l().Warn(msg, fields...) }
func Error(msg string, fields ...zap.Field) { _l().Error(msg, fields...) }
func DPanic(msg string, fields ...zap.Field) { _l().DPanic(msg, fields...) }
func Panic(msg string, fields ...zap.Field) { _l().Panic(msg, fields...) }
func Fatal(msg string, fields ...zap.Field) { _l().Fatal(msg, fields...) }
func Debugf(format string, args ...any) { _s().Debugf(format, args...) }
func Infof(format string, args ...any) { _s().Infof(format, args...) }
func Warnf(format string, args ...any) { _s().Warnf(format, args...) }
func Errorf(format string, args ...any) { _s().Errorf(format, args...) }
func DPanicf(format string, args ...any) { _s().DPanicf(format, args...) }
func Panicf(format string, args ...any) { _s().Panicf(format, args...) }
func Fatalf(format string, args ...any) { _s().Fatalf(format, args...) }
// Print uses fmt.Sprint to log a message at InfoLevel if it's enabled.
//
// It has same signature with log.Print, which helps to migrate from the
// standard library to this package.
func Print(args ...any) {
if len(args) > 0 {
s, _ := args[0].(string)
if lvl, ok := detectLevel(s); ok {
if GetLevel().Enabled(lvl) {
msg := formatMessage("", args)
_l().Log(lvl, msg)
}
return
}
}
_s().Info(args...)
}
// Printf logs a message at InfoLevel if it's enabled.
//
// It has same signature with log.Printf, which helps to migrate from the
// standard library to this package.
func Printf(format string, args ...any) {
if lvl, ok := detectLevel(format); ok {
if GetLevel().Enabled(lvl) {
msg := formatMessage(format, args)
_l().Log(lvl, msg)
}
return
}
_s().Infof(format, args...)
}
// Println logs a message at InfoLevel if it's enabled.
//
// It has same signature with log.Println, which helps to migrate from the
// standard library to this package.
func Println(args ...any) {
if len(args) > 0 {
s, _ := args[0].(string)
if lvl, ok := detectLevel(s); ok {
if GetLevel().Enabled(lvl) {
msg := fmt.Sprintln(args...)
_l().Log(lvl, msg[:len(msg)-1])
}
return
}
}
_s().Infoln(args...)
}