@@ -65,6 +65,11 @@ func durationToMilliseconds(timeDuration time.Duration) int64 {
6565}
6666
6767type traceItem interface {
68+ // rLock must be called before invoking time or writeItem.
69+ rLock ()
70+ // rUnlock must be called after processing the item is complete.
71+ rUnlock ()
72+
6873 // time returns when the trace was recorded as completed.
6974 time () time.Time
7075 // writeItem outputs the traceItem to the buffer. If stepThreshold is non-nil, only output the
@@ -79,6 +84,10 @@ type traceStep struct {
7984 fields []Field
8085}
8186
87+ // rLock doesn't need to do anything because traceStep instances are immutable.
88+ func (s traceStep ) rLock () {}
89+ func (s traceStep ) rUnlock () {}
90+
8291func (s traceStep ) time () time.Time {
8392 return s .stepTime
8493}
@@ -106,6 +115,14 @@ type Trace struct {
106115 traceItems []traceItem
107116}
108117
118+ func (t * Trace ) rLock () {
119+ t .lock .RLock ()
120+ }
121+
122+ func (t * Trace ) rUnlock () {
123+ t .lock .RUnlock ()
124+ }
125+
109126func (t * Trace ) time () time.Time {
110127 if t .endTime != nil {
111128 return * t .endTime
@@ -231,8 +248,10 @@ func (t *Trace) logTrace() {
231248func (t * Trace ) writeTraceSteps (b * bytes.Buffer , formatter string , stepThreshold * time.Duration ) {
232249 lastStepTime := t .startTime
233250 for _ , stepOrTrace := range t .traceItems {
251+ stepOrTrace .rLock ()
234252 stepOrTrace .writeItem (b , formatter , lastStepTime , stepThreshold )
235253 lastStepTime = stepOrTrace .time ()
254+ stepOrTrace .rUnlock ()
236255 }
237256}
238257
0 commit comments