Skip to content

Commit 07a4d35

Browse files
committed
move ExitFunc from globals to Logger struct
address review feedback from @ccoVeille
1 parent 455a81f commit 07a4d35

File tree

3 files changed

+82
-76
lines changed

3 files changed

+82
-76
lines changed

globals.go

-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package zerolog
33
import (
44
"bytes"
55
"encoding/json"
6-
"os"
76
"strconv"
87
"sync/atomic"
98
"time"
@@ -121,9 +120,6 @@ var (
121120
// be thread safe and non-blocking.
122121
ErrorHandler func(err error)
123122

124-
// ExitFunc is the fucntion called to exit the application, defaults to `os.Exit()`
125-
ExitFunc exitFunc = os.Exit
126-
127123
// DefaultContextLogger is returned from Ctx() if there is no logger associated
128124
// with the context.
129125
DefaultContextLogger *Logger
@@ -167,8 +163,6 @@ var (
167163
disableSampling = new(int32)
168164
)
169165

170-
type exitFunc func(int)
171-
172166
// SetGlobalLevel sets the global override for log level. If this
173167
// values is raised, all Loggers will use at least this value.
174168
//

log.go

+81-68
Original file line numberDiff line numberDiff line change
@@ -2,85 +2,85 @@
22
//
33
// A global Logger can be use for simple logging:
44
//
5-
// import "github.com/rs/zerolog/log"
5+
// import "github.com/rs/zerolog/log"
66
//
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"}
99
//
1010
// NOTE: To import the global logger, import the "log" subpackage "github.com/rs/zerolog/log".
1111
//
1212
// Fields can be added to log messages:
1313
//
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"}
1616
//
1717
// Create logger instance to manage different outputs:
1818
//
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"}
2424
//
2525
// Sub-loggers let you chain loggers with additional context:
2626
//
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"}
3030
//
3131
// Level logging
3232
//
33-
// zerolog.SetGlobalLevel(zerolog.InfoLevel)
33+
// zerolog.SetGlobalLevel(zerolog.InfoLevel)
3434
//
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")
3737
//
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"}
4444
//
4545
// Customize automatic field names:
4646
//
47-
// log.TimestampFieldName = "t"
48-
// log.LevelFieldName = "p"
49-
// log.MessageFieldName = "m"
47+
// log.TimestampFieldName = "t"
48+
// log.LevelFieldName = "p"
49+
// log.MessageFieldName = "m"
5050
//
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"}
5353
//
5454
// Log with no level and message:
5555
//
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"}
5858
//
5959
// Add contextual fields to global Logger:
6060
//
61-
// log.Logger = log.With().Str("foo", "bar").Logger()
61+
// log.Logger = log.With().Str("foo", "bar").Logger()
6262
//
6363
// Sample logs:
6464
//
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")
6767
//
6868
// Log with contextual hooks:
6969
//
70-
// // Create the hook:
71-
// type SeverityHook struct{}
70+
// // Create the hook:
71+
// type SeverityHook struct{}
7272
//
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+
// }
7878
//
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"}
8484
//
8585
// # Caveats
8686
//
@@ -89,11 +89,11 @@
8989
// There is no fields deduplication out-of-the-box.
9090
// Using the same key multiple times creates new key in final JSON each time.
9191
//
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"}
9797
//
9898
// In this case, many consumers will take the last value,
9999
// but this is not guaranteed; check yours if in doubt.
@@ -102,15 +102,15 @@
102102
//
103103
// Be careful when calling UpdateContext. It is not concurrency safe. Use the With method to create a child logger:
104104
//
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()
108108
//
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+
// }
114114
package zerolog
115115

116116
import (
@@ -221,19 +221,25 @@ func (l Level) MarshalText() ([]byte, error) {
221221
return []byte(LevelFieldMarshalFunc(l)), nil
222222
}
223223

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+
224229
// A Logger represents an active logging object that generates lines
225230
// of JSON output to an io.Writer. Each logging operation makes a single
226231
// call to the Writer's Write method. There is no guarantee on access
227232
// serialization to the Writer. If your Writer is not thread safe,
228233
// you may consider a sync wrapper.
229234
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
237243
}
238244

239245
// 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 {
335341
return l
336342
}
337343

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+
338350
// Trace starts a new message with trace level.
339351
//
340352
// 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 {
383395
}
384396

385397
// 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
387399
// program immediately.
388400
//
389401
// You must call Msg on the returned event in order to send the event.
@@ -394,10 +406,11 @@ func (l *Logger) Fatal() *Event {
394406
// will be lost as ExitFunc() (os.Exit by default) terminates the program immediately.
395407
closer.Close()
396408
}
397-
if ExitFunc == nil {
398-
ExitFunc = os.Exit
409+
exitFunc := l.exitFunc
410+
if exitFunc == nil {
411+
exitFunc = os.Exit
399412
}
400-
ExitFunc(1)
413+
exitFunc(1)
401414
})
402415
}
403416

log_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,7 @@ func TestFatal(t *testing.T) {
115115

116116
t.Run("should not exit", func(t *testing.T) {
117117
out := &bytes.Buffer{}
118-
ExitFunc = func(code int) {} // dummy exit func
119-
log := New(out)
118+
log := New(out).ExitFunc(func(_ int) {})
120119
log.Fatal().Msg("")
121120
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"fatal"}`+"\n"; got != want {
122121
t.Errorf("invalid log output:\n got: %v\nwant: %v", got, want)

0 commit comments

Comments
 (0)