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
// Prehooks are also available. It's called just before "level" is added to a log.
86
86
// `msg` always gets empty in `Run()`:
87
87
//
88
- // // Use as prehook:
89
- // var h SeverityHook
90
- // log := zerolog.New(os.Stdout).Prehook(h)
91
- // log.Warn().Msg("")
92
- // // Output: {"severity":"warn", "level":"warn"}
88
+ // // Use as prehook:
89
+ // var h SeverityHook
90
+ // log := zerolog.New(os.Stdout).Prehook(h)
91
+ // log.Warn().Msg("")
92
+ // // Output: {"severity":"warn", "level":"warn"}
93
93
//
94
- //
95
- // Caveats
94
+ // # Caveats
96
95
//
97
96
// There is no fields deduplication out-of-the-box.
98
97
// Using the same key multiple times creates new key in final JSON each time.
99
98
//
100
- // logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
101
- // logger.Info().
102
- // Timestamp().
103
- // Msg("dup")
104
- // // Output: {"level":"info","time":1494567715,"time":1494567715,"message":"dup"}
99
+ // logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
100
+ // logger.Info().
101
+ // Timestamp().
102
+ // Msg("dup")
103
+ // // Output: {"level":"info","time":1494567715,"time":1494567715,"message":"dup"}
105
104
//
106
105
// In this case, many consumers will take the last value,
107
106
// but this is not guaranteed; check yours if in doubt.
110
109
//
111
110
// Be careful when calling UpdateContext. It is not concurrency safe. Use the With method to create a child logger:
112
111
//
113
- // func handler(w http.ResponseWriter, r *http.Request) {
114
- // // Create a child logger for concurrency safety
115
- // logger := log.Logger.With().Logger()
112
+ // func handler(w http.ResponseWriter, r *http.Request) {
113
+ // // Create a child logger for concurrency safety
114
+ // logger := log.Logger.With().Logger()
116
115
//
117
- // // Add context fields, for example User-Agent from HTTP headers
118
- // logger.UpdateContext(func(c zerolog.Context) zerolog.Context {
119
- // ...
120
- // })
121
- // }
116
+ // // Add context fields, for example User-Agent from HTTP headers
117
+ // logger.UpdateContext(func(c zerolog.Context) zerolog.Context {
118
+ // ...
119
+ // })
120
+ // }
122
121
package zerolog
123
122
124
123
import (
@@ -236,16 +235,19 @@ func (l Level) MarshalText() ([]byte, error) {
236
235
// serialization to the Writer. If your Writer is not thread safe,
237
236
// you may consider a sync wrapper.
238
237
type Logger struct {
239
- w LevelWriter
240
- level Level
241
- sampler Sampler
242
- context []byte
243
- hooks []Hook
244
- prehooks []Hook
245
- stack bool
246
- ctx context.Context
238
+ w LevelWriter
239
+ level Level
240
+ sampler Sampler
241
+ context []byte
242
+ hooks []Hook
243
+ prehooks []Hook
244
+ stack bool
245
+ fatalFunc func (string )
246
+ ctx context.Context
247
247
}
248
248
249
+ var defaultFatalFunc = func (msg string ) { os .Exit (1 ) }
250
+
249
251
// New creates a root logger with given output writer. If the output writer implements
250
252
// the LevelWriter interface, the WriteLevel method will be called instead of the Write
251
253
// one.
@@ -261,7 +263,7 @@ func New(w io.Writer) Logger {
261
263
if ! ok {
262
264
lw = LevelWriterAdapter {w }
263
265
}
264
- return Logger {w : lw , level : TraceLevel }
266
+ return Logger {w : lw , level : TraceLevel , fatalFunc : defaultFatalFunc }
265
267
}
266
268
267
269
// Nop returns a disabled logger for which all operation are no-op.
@@ -352,6 +354,15 @@ func (l Logger) Prehook(h Hook) Logger {
352
354
return l
353
355
}
354
356
357
+ // FatalFunc returns a logger with the f FatalFunc. This func will be called
358
+ // when a message is logged at the fatal level. By default, this calls
359
+ // `os.Exit(1)`, but you can override this to do something else, particularly
360
+ // for testing.
361
+ func (l Logger ) FatalFunc (f func (string )) Logger {
362
+ l .fatalFunc = f
363
+ return l
364
+ }
365
+
355
366
// Trace starts a new message with trace level.
356
367
//
357
368
// You must call Msg on the returned event in order to send the event.
@@ -404,7 +415,7 @@ func (l *Logger) Err(err error) *Event {
404
415
//
405
416
// You must call Msg on the returned event in order to send the event.
406
417
func (l * Logger ) Fatal () * Event {
407
- return l .newEvent (FatalLevel , func ( msg string ) { os . Exit ( 1 ) } )
418
+ return l .newEvent (FatalLevel , l . fatalFunc )
408
419
}
409
420
410
421
// Panic starts a new message with panic level. The panic() function
0 commit comments