diff --git a/model/adjuster/clockskew.go b/model/adjuster/clockskew.go index b05e7dcfa47..24333757c1f 100644 --- a/model/adjuster/clockskew.go +++ b/model/adjuster/clockskew.go @@ -113,12 +113,21 @@ func (a *clockSkewAdjuster) buildNodesMap() { // or points to an ID for which there is no span. func (a *clockSkewAdjuster) buildSubGraphs() { a.roots = make(map[model.SpanID]*node) +IterateSpans: for _, n := range a.spans { - // TODO handle FOLLOWS_FROM references if n.span.ParentSpanID == 0 { a.roots[n.span.SpanID] = n continue } + + // Treat spans that have a FOLLOWS_FROM reference to their parent as root spans. + for _, ref := range n.span.References { + if ref.RefType == model.FollowsFrom && ref.SpanID == n.span.ParentSpanID { + a.roots[n.span.SpanID] = n + continue IterateSpans + } + } + if p, ok := a.spans[n.span.ParentSpanID]; ok { p.children = append(p.children, n) } else { diff --git a/model/adjuster/clockskew_test.go b/model/adjuster/clockskew_test.go index 6e4ba678cfa..05c6a80d793 100644 --- a/model/adjuster/clockskew_test.go +++ b/model/adjuster/clockskew_test.go @@ -33,6 +33,7 @@ func TestClockSkewAdjuster(t *testing.T) { host string adjusted int // start time after adjustment adjustedLogs []int // adjusted log timestamps + refs []model.SpanRef } toTime := func(t int) time.Time { @@ -66,6 +67,7 @@ func TestClockSkewAdjuster(t *testing.T) { model.String("ip", spanProto.host), }, }, + References: spanProto.refs, } trace.Spans = append(trace.Spans, span) } @@ -112,6 +114,13 @@ func TestClockSkewAdjuster(t *testing.T) { {id: 2, parent: 1, startTime: 0, duration: 50, host: "a", adjusted: 0}, }, }, + { + description: "do not adjust child that follows from parent", + trace: []spanProto{ + {id: 1, parent: 0, startTime: 10, duration: 100, host: "a", adjusted: 10}, + {id: 2, parent: 1, startTime: 110, duration: 100, host: "a", adjusted: 110, refs: []model.SpanRef{{RefType: model.FollowsFrom, SpanID: 1}}}, + }, + }, { description: "do not adjust child that fits inside parent", trace: []spanProto{