@@ -136,15 +136,17 @@ func (td toDomain) transformSpan(zSpan *zipkincore.Span) []*model.Span {
136
136
}
137
137
138
138
flags := td .getFlags (zSpan )
139
- // TODO StartTime and Duration could theoretically be defined only via cs/cr/sr/ss annotations.
139
+
140
+ startTime , duration := td .getStartTimeAndDuration (zSpan )
141
+
140
142
result := []* model.Span {{
141
143
TraceID : traceID ,
142
144
SpanID : model .NewSpanID (uint64 (zSpan .ID )),
143
145
OperationName : zSpan .Name ,
144
146
References : refs ,
145
147
Flags : flags ,
146
- StartTime : model .EpochMicrosecondsAsTime (uint64 (zSpan . GetTimestamp () )),
147
- Duration : model .MicrosecondsAsDuration (uint64 (zSpan . GetDuration () )),
148
+ StartTime : model .EpochMicrosecondsAsTime (uint64 (startTime )),
149
+ Duration : model .MicrosecondsAsDuration (uint64 (duration )),
148
150
Tags : tags ,
149
151
Logs : td .getLogs (zSpan .Annotations ),
150
152
}}
@@ -188,6 +190,30 @@ func (td toDomain) getFlags(zSpan *zipkincore.Span) model.Flags {
188
190
return f
189
191
}
190
192
193
+ // Get a correct start time to use for the span if it's not set directly
194
+ func (td toDomain ) getStartTimeAndDuration (zSpan * zipkincore.Span ) (int64 , int64 ) {
195
+ timestamp := zSpan .GetTimestamp ()
196
+ duration := zSpan .GetDuration ()
197
+ if timestamp == 0 {
198
+ cs := td .findAnnotation (zSpan , zipkincore .CLIENT_SEND )
199
+ sr := td .findAnnotation (zSpan , zipkincore .SERVER_RECV )
200
+ if cs != nil {
201
+ timestamp = cs .Timestamp
202
+ cr := td .findAnnotation (zSpan , zipkincore .CLIENT_RECV )
203
+ if cr != nil && duration == 0 {
204
+ duration = cr .Timestamp - cs .Timestamp
205
+ }
206
+ } else if sr != nil {
207
+ timestamp = sr .Timestamp
208
+ ss := td .findAnnotation (zSpan , zipkincore .SERVER_SEND )
209
+ if ss != nil && duration == 0 {
210
+ duration = ss .Timestamp - sr .Timestamp
211
+ }
212
+ }
213
+ }
214
+ return timestamp , duration
215
+ }
216
+
191
217
// generateProcess takes a Zipkin Span and produces a model.Process.
192
218
// An optional error may also be returned, but it is not fatal.
193
219
func (td toDomain ) generateProcess (zSpan * zipkincore.Span ) (* model.Process , error ) {
0 commit comments