@@ -78,8 +78,20 @@ func NewEntry(logger *Logger) *Entry {
78
78
}
79
79
}
80
80
81
+ func (entry * Entry ) Dup () * Entry {
82
+ data := make (Fields , len (entry .Data ))
83
+ for k , v := range entry .Data {
84
+ data [k ] = v
85
+ }
86
+ return & Entry {Logger : entry .Logger , Data : data , Time : entry .Time , Context : entry .Context , err : entry .err }
87
+ }
88
+
81
89
// Returns the bytes representation of this entry from the formatter.
82
90
func (entry * Entry ) Bytes () ([]byte , error ) {
91
+ return entry .bytes_nolock ()
92
+ }
93
+
94
+ func (entry * Entry ) bytes_nolock () ([]byte , error ) {
83
95
return entry .Logger .Formatter .Format (entry )
84
96
}
85
97
@@ -212,68 +224,68 @@ func (entry Entry) HasCaller() (has bool) {
212
224
213
225
// This function is not declared with a pointer value because otherwise
214
226
// race conditions will occur when using multiple goroutines
215
- func (entry Entry ) log (level Level , msg string ) {
227
+ func (entry * Entry ) log (level Level , msg string ) {
216
228
var buffer * bytes.Buffer
217
229
218
- // Default to now, but allow users to override if they want.
219
- //
220
- // We don't have to worry about polluting future calls to Entry#log()
221
- // with this assignment because this function is declared with a
222
- // non-pointer receiver.
223
- if entry .Time .IsZero () {
224
- entry .Time = time .Now ()
230
+ newEntry := entry .Dup ()
231
+
232
+ if newEntry .Time .IsZero () {
233
+ newEntry .Time = time .Now ()
225
234
}
226
235
227
- entry .Level = level
228
- entry .Message = msg
229
- entry .Logger .mu .Lock ()
230
- if entry .Logger .ReportCaller {
231
- entry .Caller = getCaller ()
236
+ newEntry .Level = level
237
+ newEntry .Message = msg
238
+
239
+ newEntry .Logger .mu .Lock ()
240
+ reportCaller := newEntry .Logger .ReportCaller
241
+ newEntry .Logger .mu .Unlock ()
242
+
243
+ if reportCaller {
244
+ newEntry .Caller = getCaller ()
232
245
}
233
- entry .Logger .mu .Unlock ()
234
246
235
- entry .fireHooks ()
247
+ newEntry .fireHooks ()
236
248
237
249
buffer = getBuffer ()
238
250
defer func () {
239
- entry .Buffer = nil
251
+ newEntry .Buffer = nil
240
252
putBuffer (buffer )
241
253
}()
242
254
buffer .Reset ()
243
- entry .Buffer = buffer
255
+ newEntry .Buffer = buffer
244
256
245
- entry .write ()
257
+ newEntry .write ()
246
258
247
- entry .Buffer = nil
259
+ newEntry .Buffer = nil
248
260
249
261
// To avoid Entry#log() returning a value that only would make sense for
250
262
// panic() to use in Entry#Panic(), we avoid the allocation by checking
251
263
// directly here.
252
264
if level <= PanicLevel {
253
- panic (& entry )
265
+ panic (newEntry )
254
266
}
255
267
}
256
268
257
269
func (entry * Entry ) fireHooks () {
258
- entry .Logger .mu .Lock ()
259
- defer entry .Logger .mu .Unlock ()
260
270
err := entry .Logger .Hooks .Fire (entry .Level , entry )
261
271
if err != nil {
262
272
fmt .Fprintf (os .Stderr , "Failed to fire hook: %v\n " , err )
263
273
}
264
274
}
265
275
266
276
func (entry * Entry ) write () {
267
- entry .Logger .mu .Lock ()
268
- defer entry .Logger .mu .Unlock ()
269
277
serialized , err := entry .Logger .Formatter .Format (entry )
270
278
if err != nil {
271
279
fmt .Fprintf (os .Stderr , "Failed to obtain reader, %v\n " , err )
272
280
return
273
281
}
274
- if _ , err = entry .Logger .Out .Write (serialized ); err != nil {
275
- fmt .Fprintf (os .Stderr , "Failed to write to log, %v\n " , err )
276
- }
282
+ func () {
283
+ entry .Logger .mu .Lock ()
284
+ defer entry .Logger .mu .Unlock ()
285
+ if _ , err := entry .Logger .Out .Write (serialized ); err != nil {
286
+ fmt .Fprintf (os .Stderr , "Failed to write to log, %v\n " , err )
287
+ }
288
+ }()
277
289
}
278
290
279
291
func (entry * Entry ) Log (level Level , args ... interface {}) {
0 commit comments