-
Notifications
You must be signed in to change notification settings - Fork 46
Expand file tree
/
Copy pathquickstart_test.go
More file actions
287 lines (238 loc) · 6.73 KB
/
Copy pathquickstart_test.go
File metadata and controls
287 lines (238 loc) · 6.73 KB
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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
package zap
import (
"encoding/json"
"io"
"log"
"testing"
"time"
"gopkg.in/natefinch/lumberjack.v2"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func TestSugar(t *testing.T) {
logger, _ := zap.NewProduction()
defer func(logger *zap.Logger) {
_ = logger.Sync()
}(logger) // flushes buffer, if any
url := "https://www.uber.com"
sugar := logger.Sugar()
sugar.Infow("failed to fetch URL",
// Structured context as loosely typed key-value pairs.
"url", url,
"attempt", 3,
"backoff", time.Second,
)
sugar.Infof("Failed to fetch URL: %s", url)
}
func TestLogger(t *testing.T) {
logger, _ := zap.NewProduction()
defer func(logger *zap.Logger) {
_ = logger.Sync()
}(logger)
url := "https://www.uber.com"
logger.Info("failed to fetch URL",
// Structured context as strongly typed Field values.
zap.String("url", url),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
}
func TestNamespace(t *testing.T) {
logger, _ := zap.NewProduction()
defer func(logger *zap.Logger) {
_ = logger.Sync()
}(logger)
logger.Info("tracked some metrics",
zap.Namespace("metrics"),
zap.Int("counter", 1),
)
logger2 := logger.With(
zap.Namespace("metrics"),
zap.Int("counter", 2),
)
logger2.Info("tracked some metrics")
}
func TestUseConfig(t *testing.T) {
rawJSON := `
{
"level": "debug",
"encoding": "json",
"outputPaths": ["stdout", "server.log"],
"errorOutputPaths": ["stderr"],
"initialFields": {"name": "Go"},
"encoderConfig": {
"messageKey": "message",
"levelKey": "level",
"levelEncoder": "lowercase"
}
}
`
var cfg zap.Config
if err := json.Unmarshal([]byte(rawJSON), &cfg); err != nil {
t.Fatal(err)
}
logger, err := cfg.Build()
if err != nil {
t.Fatal(err)
}
defer func(logger *zap.Logger) {
_ = logger.Sync()
}(logger)
logger.Info("server start work successfully!")
}
func output(msg string, fields ...zap.Field) {
zap.L().Info(msg, fields...)
}
func TestAddCallerSkip(t *testing.T) {
// 有时稍微封装了一下记录日志的方法,但是希望输出的文件名和行号是调用封装函数的位置。
// 可以使用 zap.AddCallerSkip(skip int) 向上跳 1 层:
logger, _ := zap.NewProduction(zap.AddCaller(), zap.AddCallerSkip(1))
defer func(logger *zap.Logger) {
_ = logger.Sync()
}(logger)
zap.ReplaceGlobals(logger)
output("hello world")
}
func f1() {
f2("hello world")
}
func f2(msg string, fields ...zap.Field) {
zap.L().Warn(msg, fields...)
}
func TestAddStackTrace(t *testing.T) {
logger, _ := zap.NewProduction(zap.AddStacktrace(zapcore.WarnLevel))
defer func(logger *zap.Logger) {
_ = logger.Sync()
}(logger)
zap.ReplaceGlobals(logger)
f1()
}
func TestReplaceGlobals(t *testing.T) {
// 为了方便使用,zap提供了两个全局的Logger,一个是*zap.Logger,可调用zap.L()获得;另一个是*zap.SugaredLogger,
// 可调用zap.S()获得。需要注意的是,全局的 Logger 默认并不会记录日志
// 输出
// gt -run='TestReplaceGlobals'
// === RUN TestReplaceGlobals
// {"level":"info","msg":"global Logger after"}
// {"level":"info","msg":"global SugaredLogger after"}
// 调用ReplaceGlobals之前记录的日志并没有输出
zap.L().Info("global Logger before")
zap.S().Info("global SugaredLogger before")
logger := zap.NewExample()
defer func(logger *zap.Logger) {
_ = logger.Sync()
}(logger)
zap.ReplaceGlobals(logger)
zap.L().Info("global Logger after")
zap.S().Info("global SugaredLogger after")
}
func TestCommonFields(t *testing.T) {
// 如果每条日志都要记录一些共用的字段,那么使用 zap.Fields(fs ...Field)创建的选项。
// 例如在服务器日志中记录可能都需要记录 serverId 和 serverName
logger, _ := zap.NewProduction(zap.Fields(
zap.Int("serverId", 1024),
zap.String("serverName", "user_orders"),
))
logger.Info("hello world")
logger.Info("hello world")
logger.Info("hello world")
}
func TestWithNativeLog(t *testing.T) {
// 如果项目一开始使用的是标准日志库log,后面想转为zap。
// 不必修改之前的文件,可以调用zap.NewStdLog(l *Logger) *log.Logger返回一个标准的log.Logger,
// 内部实际上写入的还是 zap.Logger
logger, _ := zap.NewProduction()
defer func(logger *zap.Logger) {
_ = logger.Sync()
}(logger)
std := zap.NewStdLog(logger)
std.Print("standard logger wrapper")
undo := zap.RedirectStdLog(logger)
log.Print("redirected standard library")
undo()
log.Print("restored standard library")
}
func TestRotateWithLumberjack(t *testing.T) {
lumberJackLogger := &lumberjack.Logger{
Filename: "server.log",
MaxSize: 1, // 单个文件最大100M
MaxBackups: 100, // 多于 100 个日志文件后,清理较旧的日志
MaxAge: 1, // 一天一切割
Compress: true,
}
writeSyncer := zapcore.AddSync(lumberJackLogger)
encoder := zapcore.NewJSONEncoder(zapcore.EncoderConfig{
LevelKey: "L",
TimeKey: "T",
MessageKey: "M",
NameKey: "N",
CallerKey: "C",
FunctionKey: "F",
StacktraceKey: "S",
LineEnding: "\r\n",
EncodeTime: zapcore.ISO8601TimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
})
core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)
logger := zap.New(core, zap.AddStacktrace(zap.DebugLevel))
defer func(logger *zap.Logger) {
_ = logger.Sync()
}(logger)
for i := 0; i < 10240; i++ {
logger.Debug("hello world")
}
}
// go test -v -bench 'BenchmarkNativeLog' -run ^$
/*
goos: linux
goarch: amd64
pkg: Golang-Patterns/zap
cpu: Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
BenchmarkNativeLog
BenchmarkNativeLog-8 6890528 177.1 ns/op 336 B/op 2 allocs/op
*/
func BenchmarkNativeLog(b *testing.B) {
b.ReportAllocs()
b.StopTimer()
log.SetOutput(io.Discard)
b.StartTimer()
for i := 0; i < b.N; i++ {
log.Printf("failed to fetch URL %+v", map[string]interface{}{
"url": "https://www.google.com",
"attempt": 3,
"backoff": 1,
})
}
}
/*
goos: linux
goarch: amd64
pkg: Golang-Patterns/zap
cpu: Intel(R) Core(TM) i5-8300H CPU @ 2.30GHz
BenchmarkZap
BenchmarkZap-8 625761 1848 ns/op 192 B/op 1 allocs/op
*/
func BenchmarkZap(b *testing.B) {
b.ReportAllocs()
b.StopTimer()
cfg := zap.NewProductionConfig()
core := zapcore.NewCore(
zapcore.NewJSONEncoder(cfg.EncoderConfig),
zapcore.AddSync(io.Discard),
zapcore.InfoLevel,
)
logger := zap.New(core)
defer func(logger *zap.Logger) {
_ = logger.Sync()
}(logger)
b.StartTimer()
for i := 0; i < b.N; i++ {
logger.Info("failed to fetch URL",
zap.String("url", "https://www.google.com"),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
}
}