/
v1_converter.go
124 lines (110 loc) · 3.38 KB
/
v1_converter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package jaeger
import (
v1 "github.com/jaegertracing/jaeger/proto-gen/otel/common/v1"
v1Trace "github.com/jaegertracing/jaeger/proto-gen/otel/trace/v1"
"github.com/mrasu/GravityR/otel/omodel"
"github.com/pkg/errors"
"github.com/samber/lo"
semconv "go.opentelemetry.io/otel/semconv/v1.12.0"
"reflect"
)
type v1Converter struct{}
type spanHolder struct {
orig *v1Trace.Span
span *omodel.Span
}
func ToTraceTrees(resourceSpans []*v1Trace.ResourceSpans) []*omodel.TraceTree {
c := &v1Converter{}
return c.toTraceTrees(resourceSpans)
}
func (c *v1Converter) toTraceTrees(resourceSpans []*v1Trace.ResourceSpans) []*omodel.TraceTree {
spanIdMap := map[string]*spanHolder{}
for _, rSpan := range resourceSpans {
for _, lSpan := range rSpan.InstrumentationLibrarySpans {
for _, span := range lSpan.Spans {
spanIdMap[string(span.SpanId)] = &spanHolder{orig: span, span: c.toOmodelSpan(span, rSpan)}
}
}
}
var roots []*omodel.Span
for _, h := range spanIdMap {
if c.isRootSpan(h.orig) {
roots = append(roots, h.span)
continue
}
if parent, ok := spanIdMap[string(h.orig.ParentSpanId)]; ok {
parent.span.Children = append(parent.span.Children, h.span)
h.span.Parent = parent.span
} else {
roots = append(roots, h.span)
}
}
return lo.Map(roots, func(root *omodel.Span, _ int) *omodel.TraceTree {
root.SortChildren()
return omodel.NewTraceTree(root)
})
}
func (c *v1Converter) toOmodelSpan(s *v1Trace.Span, rs *v1Trace.ResourceSpans) *omodel.Span {
serviceName := ""
if rs.Resource != nil {
for _, r := range rs.Resource.Attributes {
if r.Key == string(semconv.ServiceNameKey) {
serviceName = r.Value.GetStringValue()
break
}
}
}
attrs := map[string]*omodel.AnyValue{}
for _, attr := range s.Attributes {
attrs[attr.Key] = c.toAnyValue(attr.Value)
}
return &omodel.Span{
Name: s.Name,
TraceId: s.TraceId,
SpanId: s.SpanId,
StartTimeUnixNano: s.StartTimeUnixNano,
EndTimeUnixNano: s.EndTimeUnixNano,
SpanAttributes: attrs,
ServiceName: serviceName,
}
}
func (c *v1Converter) toAnyValue(v *v1.AnyValue) *omodel.AnyValue {
return &omodel.AnyValue{Val: c.toAnyValueData(v)}
}
func (c *v1Converter) toAnyValueData(v *v1.AnyValue) omodel.AnyValueDatum {
switch vv := v.Value.(type) {
case *v1.AnyValue_StringValue:
return &omodel.AnyValueString{StringValue: vv.StringValue}
case *v1.AnyValue_BoolValue:
return &omodel.AnyValueBool{BoolValue: vv.BoolValue}
case *v1.AnyValue_IntValue:
return &omodel.AnyValueInt{IntValue: vv.IntValue}
case *v1.AnyValue_DoubleValue:
return &omodel.AnyValueDouble{DoubleValue: vv.DoubleValue}
case *v1.AnyValue_ArrayValue:
var vals []omodel.AnyValueDatum
for _, v := range vv.ArrayValue.Values {
vals = append(vals, c.toAnyValueData(v))
}
return &omodel.AnyValueArray{ArrayValues: vals}
case *v1.AnyValue_KvlistValue:
vals := map[string]omodel.AnyValueDatum{}
for _, v := range vv.KvlistValue.Values {
vals[v.Key] = c.toAnyValueData(v.Value)
}
return &omodel.AnyValueKV{KVValue: vals}
case *v1.AnyValue_BytesValue:
return &omodel.AnyValueBytes{BytesValue: vv.BytesValue}
default:
// This must not be happened
panic(errors.Errorf("not implemented any value: %s", reflect.TypeOf(vv).Name()))
}
}
func (c *v1Converter) isRootSpan(span *v1Trace.Span) bool {
for _, b := range span.ParentSpanId {
if b != 0 {
return false
}
}
return true
}