@@ -22,6 +22,7 @@ package zapcore
2222
2323import (
2424 "fmt"
25+ "hash/crc32"
2526 "runtime"
2627 "strings"
2728 "sync"
@@ -154,18 +155,30 @@ type Entry struct {
154155
155156// CheckWriteAction indicates what action to take after a log entry is
156157// processed. Actions are ordered in increasing severity.
157- type CheckWriteAction uint8
158+ type CheckWriteAction func ( * CheckedEntry , [] Field )
158159
159- const (
160+ var (
160161 // WriteThenNoop indicates that nothing special needs to be done. It's the
161162 // default behavior.
162- WriteThenNoop CheckWriteAction = iota
163+ WriteThenNoop CheckWriteAction
163164 // WriteThenGoexit runs runtime.Goexit after Write.
164- WriteThenGoexit
165+ WriteThenGoexit CheckWriteAction = func (ce * CheckedEntry , fields []Field ) {
166+ runtime .Goexit ()
167+ }
165168 // WriteThenPanic causes a panic after Write.
166- WriteThenPanic
167- // WriteThenFatal causes a fatal os.Exit after Write.
168- WriteThenFatal
169+ WriteThenPanic CheckWriteAction = func (ce * CheckedEntry , fields []Field ) {
170+ panic (ce .Message )
171+ }
172+ // WriteThenFatal causes a fatal os.Exit(1) after Write.
173+ WriteThenFatal CheckWriteAction = func (ce * CheckedEntry , fields []Field ) {
174+ exit .ExitWith (1 )
175+ }
176+ // WriteThenExitCode causes an os.Exit(code) after Write. The code is
177+ // calculated deterministically from the message, or from attached error
178+ // Field.
179+ WriteThenExitCode CheckWriteAction = func (ce * CheckedEntry , fields []Field ) {
180+ exit .ExitWith (retcode (ce , fields ))
181+ }
169182)
170183
171184// CheckedEntry is an Entry together with a collection of Cores that have
@@ -186,7 +199,9 @@ func (ce *CheckedEntry) reset() {
186199 ce .Entry = Entry {}
187200 ce .ErrorOutput = nil
188201 ce .dirty = false
189- ce .should = WriteThenNoop
202+ if ce .should != nil {
203+ ce .should = WriteThenNoop
204+ }
190205 for i := range ce .cores {
191206 // don't keep references to cores
192207 ce .cores [i ] = nil
@@ -224,16 +239,11 @@ func (ce *CheckedEntry) Write(fields ...Field) {
224239 ce .ErrorOutput .Sync ()
225240 }
226241
227- should , msg := ce .should , ce .Message
228242 putCheckedEntry (ce )
229243
230- switch should {
231- case WriteThenPanic :
232- panic (msg )
233- case WriteThenFatal :
234- exit .Exit ()
235- case WriteThenGoexit :
236- runtime .Goexit ()
244+ // Terminal operation
245+ if ce .should != nil {
246+ ce .should (ce , fields )
237247 }
238248}
239249
@@ -260,3 +270,14 @@ func (ce *CheckedEntry) Should(ent Entry, should CheckWriteAction) *CheckedEntry
260270 ce .should = should
261271 return ce
262272}
273+
274+ func retcode (ce * CheckedEntry , fields []Field ) int {
275+ msg := ce .Message
276+ for _ , field := range fields {
277+ if field .Type == ErrorType {
278+ msg = field .Interface .(error ).Error ()
279+ break
280+ }
281+ }
282+ return int (crc32 .ChecksumIEEE ([]byte (msg )))% 254 + 1
283+ }
0 commit comments