2
2
//
3
3
// A global Logger can be use for simple logging:
4
4
//
5
- // import "github.com/rs/zerolog/log"
5
+ // import "github.com/rs/zerolog/log"
6
6
//
7
- // log.Info().Msg("hello world")
8
- // // Output: {"time":1494567715,"level":"info","message":"hello world"}
7
+ // log.Info().Msg("hello world")
8
+ // // Output: {"time":1494567715,"level":"info","message":"hello world"}
9
9
//
10
10
// NOTE: To import the global logger, import the "log" subpackage "github.com/rs/zerolog/log".
11
11
//
12
12
// Fields can be added to log messages:
13
13
//
14
- // log.Info().Str("foo", "bar").Msg("hello world")
15
- // // Output: {"time":1494567715,"level":"info","message":"hello world","foo":"bar"}
14
+ // log.Info().Str("foo", "bar").Msg("hello world")
15
+ // // Output: {"time":1494567715,"level":"info","message":"hello world","foo":"bar"}
16
16
//
17
17
// Create logger instance to manage different outputs:
18
18
//
19
- // logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
20
- // logger.Info().
21
- // Str("foo", "bar").
22
- // Msg("hello world")
23
- // // Output: {"time":1494567715,"level":"info","message":"hello world","foo":"bar"}
19
+ // logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
20
+ // logger.Info().
21
+ // Str("foo", "bar").
22
+ // Msg("hello world")
23
+ // // Output: {"time":1494567715,"level":"info","message":"hello world","foo":"bar"}
24
24
//
25
25
// Sub-loggers let you chain loggers with additional context:
26
26
//
27
- // sublogger := log.With().Str("component", "foo").Logger()
28
- // sublogger.Info().Msg("hello world")
29
- // // Output: {"time":1494567715,"level":"info","message":"hello world","component":"foo"}
27
+ // sublogger := log.With().Str("component", "foo").Logger()
28
+ // sublogger.Info().Msg("hello world")
29
+ // // Output: {"time":1494567715,"level":"info","message":"hello world","component":"foo"}
30
30
//
31
31
// Level logging
32
32
//
33
- // zerolog.SetGlobalLevel(zerolog.InfoLevel)
33
+ // zerolog.SetGlobalLevel(zerolog.InfoLevel)
34
34
//
35
- // log.Debug().Msg("filtered out message")
36
- // log.Info().Msg("routed message")
35
+ // log.Debug().Msg("filtered out message")
36
+ // log.Info().Msg("routed message")
37
37
//
38
- // if e := log.Debug(); e.Enabled() {
39
- // // Compute log output only if enabled.
40
- // value := compute()
41
- // e.Str("foo": value).Msg("some debug message")
42
- // }
43
- // // Output: {"level":"info","time":1494567715,"routed message"}
38
+ // if e := log.Debug(); e.Enabled() {
39
+ // // Compute log output only if enabled.
40
+ // value := compute()
41
+ // e.Str("foo": value).Msg("some debug message")
42
+ // }
43
+ // // Output: {"level":"info","time":1494567715,"routed message"}
44
44
//
45
45
// Customize automatic field names:
46
46
//
47
- // log.TimestampFieldName = "t"
48
- // log.LevelFieldName = "p"
49
- // log.MessageFieldName = "m"
47
+ // log.TimestampFieldName = "t"
48
+ // log.LevelFieldName = "p"
49
+ // log.MessageFieldName = "m"
50
50
//
51
- // log.Info().Msg("hello world")
52
- // // Output: {"t":1494567715,"p":"info","m":"hello world"}
51
+ // log.Info().Msg("hello world")
52
+ // // Output: {"t":1494567715,"p":"info","m":"hello world"}
53
53
//
54
54
// Log with no level and message:
55
55
//
56
- // log.Log().Str("foo","bar").Msg("")
57
- // // Output: {"time":1494567715,"foo":"bar"}
56
+ // log.Log().Str("foo","bar").Msg("")
57
+ // // Output: {"time":1494567715,"foo":"bar"}
58
58
//
59
59
// Add contextual fields to global Logger:
60
60
//
61
- // log.Logger = log.With().Str("foo", "bar").Logger()
61
+ // log.Logger = log.With().Str("foo", "bar").Logger()
62
62
//
63
63
// Sample logs:
64
64
//
65
- // sampled := log.Sample(&zerolog.BasicSampler{N: 10})
66
- // sampled.Info().Msg("will be logged every 10 messages")
65
+ // sampled := log.Sample(&zerolog.BasicSampler{N: 10})
66
+ // sampled.Info().Msg("will be logged every 10 messages")
67
67
//
68
68
// Log with contextual hooks:
69
69
//
70
- // // Create the hook:
71
- // type SeverityHook struct{}
70
+ // // Create the hook:
71
+ // type SeverityHook struct{}
72
72
//
73
- // func (h SeverityHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
74
- // if level != zerolog.NoLevel {
75
- // e.Str("severity", level.String())
76
- // }
77
- // }
73
+ // func (h SeverityHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
74
+ // if level != zerolog.NoLevel {
75
+ // e.Str("severity", level.String())
76
+ // }
77
+ // }
78
78
//
79
- // // And use it:
80
- // var h SeverityHook
81
- // log := zerolog.New(os.Stdout).Hook(h)
82
- // log.Warn().Msg("")
83
- // // Output: {"level":"warn","severity":"warn"}
79
+ // // And use it:
80
+ // var h SeverityHook
81
+ // log := zerolog.New(os.Stdout).Hook(h)
82
+ // log.Warn().Msg("")
83
+ // // Output: {"level":"warn","severity":"warn"}
84
84
//
85
85
// # Caveats
86
86
//
89
89
// There is no fields deduplication out-of-the-box.
90
90
// Using the same key multiple times creates new key in final JSON each time.
91
91
//
92
- // logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
93
- // logger.Info().
94
- // Timestamp().
95
- // Msg("dup")
96
- // // Output: {"level":"info","time":1494567715,"time":1494567715,"message":"dup"}
92
+ // logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
93
+ // logger.Info().
94
+ // Timestamp().
95
+ // Msg("dup")
96
+ // // Output: {"level":"info","time":1494567715,"time":1494567715,"message":"dup"}
97
97
//
98
98
// In this case, many consumers will take the last value,
99
99
// but this is not guaranteed; check yours if in doubt.
102
102
//
103
103
// Be careful when calling UpdateContext. It is not concurrency safe. Use the With method to create a child logger:
104
104
//
105
- // func handler(w http.ResponseWriter, r *http.Request) {
106
- // // Create a child logger for concurrency safety
107
- // logger := log.Logger.With().Logger()
105
+ // func handler(w http.ResponseWriter, r *http.Request) {
106
+ // // Create a child logger for concurrency safety
107
+ // logger := log.Logger.With().Logger()
108
108
//
109
- // // Add context fields, for example User-Agent from HTTP headers
110
- // logger.UpdateContext(func(c zerolog.Context) zerolog.Context {
111
- // ...
112
- // })
113
- // }
109
+ // // Add context fields, for example User-Agent from HTTP headers
110
+ // logger.UpdateContext(func(c zerolog.Context) zerolog.Context {
111
+ // ...
112
+ // })
113
+ // }
114
114
package zerolog
115
115
116
116
import (
@@ -221,19 +221,25 @@ func (l Level) MarshalText() ([]byte, error) {
221
221
return []byte (LevelFieldMarshalFunc (l )), nil
222
222
}
223
223
224
+ // ExitFunc is a function type that takes an integer exit code and terminates the program.
225
+ // By default, it is set to os.Exit, but it can be overridden to customize the behavior
226
+ // of program termination (for example, for graceful shutdown or testing purposes).
227
+ type ExitFunc func (int )
228
+
224
229
// A Logger represents an active logging object that generates lines
225
230
// of JSON output to an io.Writer. Each logging operation makes a single
226
231
// call to the Writer's Write method. There is no guarantee on access
227
232
// serialization to the Writer. If your Writer is not thread safe,
228
233
// you may consider a sync wrapper.
229
234
type Logger struct {
230
- w LevelWriter
231
- level Level
232
- sampler Sampler
233
- context []byte
234
- hooks []Hook
235
- stack bool
236
- ctx context.Context
235
+ w LevelWriter
236
+ level Level
237
+ sampler Sampler
238
+ context []byte
239
+ hooks []Hook
240
+ stack bool
241
+ ctx context.Context
242
+ exitFunc ExitFunc
237
243
}
238
244
239
245
// New creates a root logger with given output writer. If the output writer implements
@@ -335,6 +341,12 @@ func (l Logger) Hook(hooks ...Hook) Logger {
335
341
return l
336
342
}
337
343
344
+ // ExitFunc returns a logger with the e ExitFunc.
345
+ func (l Logger ) ExitFunc (e ExitFunc ) Logger {
346
+ l .exitFunc = e
347
+ return l
348
+ }
349
+
338
350
// Trace starts a new message with trace level.
339
351
//
340
352
// You must call Msg on the returned event in order to send the event.
@@ -383,7 +395,7 @@ func (l *Logger) Err(err error) *Event {
383
395
}
384
396
385
397
// Fatal starts a new message with fatal level. The ExitFunc(1) function
386
- // (os.Exit by default) is called by the Msg method, which terminates the
398
+ // (os.Exit by default) is called by the Msg method, which terminates the
387
399
// program immediately.
388
400
//
389
401
// You must call Msg on the returned event in order to send the event.
@@ -394,10 +406,11 @@ func (l *Logger) Fatal() *Event {
394
406
// will be lost as ExitFunc() (os.Exit by default) terminates the program immediately.
395
407
closer .Close ()
396
408
}
397
- if ExitFunc == nil {
398
- ExitFunc = os .Exit
409
+ exitFunc := l .exitFunc
410
+ if exitFunc == nil {
411
+ exitFunc = os .Exit
399
412
}
400
- ExitFunc (1 )
413
+ exitFunc (1 )
401
414
})
402
415
}
403
416
0 commit comments