@@ -78,8 +78,20 @@ func NewEntry(logger *Logger) *Entry {
7878}
7979}
8080
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+
8189// Returns the bytes representation of this entry from the formatter.
8290func (entry * Entry ) Bytes () ([]byte , error ) {
91+ return entry .bytes_nolock ()
92+ }
93+
94+ func (entry * Entry ) bytes_nolock () ([]byte , error ) {
8395return entry .Logger .Formatter .Format (entry )
8496}
8597
@@ -212,68 +224,68 @@ func (entry Entry) HasCaller() (has bool) {
212224
213225// This function is not declared with a pointer value because otherwise
214226// 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 ) {
216228var buffer * bytes.Buffer
217229
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 ()
225234}
226235
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 ()
232245}
233- entry .Logger .mu .Unlock ()
234246
235- entry .fireHooks ()
247+ newEntry .fireHooks ()
236248
237249buffer = getBuffer ()
238250defer func () {
239- entry .Buffer = nil
251+ newEntry .Buffer = nil
240252putBuffer (buffer )
241253}()
242254buffer .Reset ()
243- entry .Buffer = buffer
255+ newEntry .Buffer = buffer
244256
245- entry .write ()
257+ newEntry .write ()
246258
247- entry .Buffer = nil
259+ newEntry .Buffer = nil
248260
249261// To avoid Entry#log() returning a value that only would make sense for
250262// panic() to use in Entry#Panic(), we avoid the allocation by checking
251263// directly here.
252264if level <= PanicLevel {
253- panic (& entry )
265+ panic (newEntry )
254266}
255267}
256268
257269func (entry * Entry ) fireHooks () {
258- entry .Logger .mu .Lock ()
259- defer entry .Logger .mu .Unlock ()
260270err := entry .Logger .Hooks .Fire (entry .Level , entry )
261271if err != nil {
262272fmt .Fprintf (os .Stderr , "Failed to fire hook: %v\n " , err )
263273}
264274}
265275
266276func (entry * Entry ) write () {
267- entry .Logger .mu .Lock ()
268- defer entry .Logger .mu .Unlock ()
269277serialized , err := entry .Logger .Formatter .Format (entry )
270278if err != nil {
271279fmt .Fprintf (os .Stderr , "Failed to obtain reader, %v\n " , err )
272280return
273281}
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+ }()
277289}
278290
279291func (entry * Entry ) Log (level Level , args ... interface {}) {
0 commit comments