ConsumeWithFinal consumes the trace, but allows for performance savings when it is known that this is the last expected input trace. the spanCount returned is the number of duplicate spans between the two traces
(tr *Trace, final bool)
| 45 | // it is known that this is the last expected input trace. the spanCount returned |
| 46 | // is the number of duplicate spans between the two traces |
| 47 | func (c *Combiner) ConsumeWithFinal(tr *Trace, final bool) (spanCount int) { |
| 48 | if tr == nil { |
| 49 | return |
| 50 | } |
| 51 | |
| 52 | // First call? |
| 53 | if c.result == nil { |
| 54 | c.result = tr |
| 55 | |
| 56 | // Pre-alloc map with input size. This saves having to grow the |
| 57 | // map from the small starting size. |
| 58 | n := 0 |
| 59 | for _, b := range c.result.ResourceSpans { |
| 60 | for _, ils := range b.ScopeSpans { |
| 61 | n += len(ils.Spans) |
| 62 | } |
| 63 | } |
| 64 | c.spans = make(map[uint64]struct{}, n) |
| 65 | |
| 66 | for _, b := range c.result.ResourceSpans { |
| 67 | for _, ils := range b.ScopeSpans { |
| 68 | for _, s := range ils.Spans { |
| 69 | c.spans[util.SpanIDAndKindToToken(s.SpanID, s.Kind)] = struct{}{} |
| 70 | } |
| 71 | } |
| 72 | } |
| 73 | return |
| 74 | } |
| 75 | |
| 76 | // coalesce root level information |
| 77 | if tr.EndTimeUnixNano > c.result.EndTimeUnixNano { |
| 78 | c.result.EndTimeUnixNano = tr.EndTimeUnixNano |
| 79 | } |
| 80 | if tr.StartTimeUnixNano < c.result.StartTimeUnixNano || c.result.StartTimeUnixNano == 0 { |
| 81 | c.result.StartTimeUnixNano = tr.StartTimeUnixNano |
| 82 | } |
| 83 | if c.result.RootServiceName == "" { |
| 84 | c.result.RootServiceName = tr.RootServiceName |
| 85 | } |
| 86 | if c.result.RootSpanName == "" { |
| 87 | c.result.RootSpanName = tr.RootSpanName |
| 88 | } |
| 89 | c.result.DurationNano = c.result.EndTimeUnixNano - c.result.StartTimeUnixNano |
| 90 | |
| 91 | // loop through every span and copy spans in B that don't exist to A |
| 92 | for _, b := range tr.ResourceSpans { |
| 93 | notFoundILS := b.ScopeSpans[:0] |
| 94 | |
| 95 | for _, ils := range b.ScopeSpans { |
| 96 | notFoundSpans := ils.Spans[:0] |
| 97 | for _, s := range ils.Spans { |
| 98 | // if not already encountered, then keep |
| 99 | token := util.SpanIDAndKindToToken(s.SpanID, s.Kind) |
| 100 | _, ok := c.spans[token] |
| 101 | if !ok { |
| 102 | notFoundSpans = append(notFoundSpans, s) |
| 103 | |
| 104 | // If last expected input, then we don't need to record |