1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package tracetransform
16
17 import (
18 "go.opentelemetry.io/otel/attribute"
19 "go.opentelemetry.io/otel/codes"
20 "go.opentelemetry.io/otel/sdk/instrumentation"
21 tracesdk "go.opentelemetry.io/otel/sdk/trace"
22 "go.opentelemetry.io/otel/trace"
23 tracepb "go.opentelemetry.io/proto/otlp/trace/v1"
24 )
25
26
27
28 func Spans(sdl []tracesdk.ReadOnlySpan) []*tracepb.ResourceSpans {
29 if len(sdl) == 0 {
30 return nil
31 }
32
33 rsm := make(map[attribute.Distinct]*tracepb.ResourceSpans)
34
35 type key struct {
36 r attribute.Distinct
37 is instrumentation.Scope
38 }
39 ssm := make(map[key]*tracepb.ScopeSpans)
40
41 var resources int
42 for _, sd := range sdl {
43 if sd == nil {
44 continue
45 }
46
47 rKey := sd.Resource().Equivalent()
48 k := key{
49 r: rKey,
50 is: sd.InstrumentationScope(),
51 }
52 scopeSpan, iOk := ssm[k]
53 if !iOk {
54
55 scopeSpan = &tracepb.ScopeSpans{
56 Scope: InstrumentationScope(sd.InstrumentationScope()),
57 Spans: []*tracepb.Span{},
58 SchemaUrl: sd.InstrumentationScope().SchemaURL,
59 }
60 }
61 scopeSpan.Spans = append(scopeSpan.Spans, span(sd))
62 ssm[k] = scopeSpan
63
64 rs, rOk := rsm[rKey]
65 if !rOk {
66 resources++
67
68 rs = &tracepb.ResourceSpans{
69 Resource: Resource(sd.Resource()),
70 ScopeSpans: []*tracepb.ScopeSpans{scopeSpan},
71 SchemaUrl: sd.Resource().SchemaURL(),
72 }
73 rsm[rKey] = rs
74 continue
75 }
76
77
78
79
80
81
82 if !iOk {
83 rs.ScopeSpans = append(rs.ScopeSpans, scopeSpan)
84 }
85 }
86
87
88 rss := make([]*tracepb.ResourceSpans, 0, resources)
89 for _, rs := range rsm {
90 rss = append(rss, rs)
91 }
92 return rss
93 }
94
95
96 func span(sd tracesdk.ReadOnlySpan) *tracepb.Span {
97 if sd == nil {
98 return nil
99 }
100
101 tid := sd.SpanContext().TraceID()
102 sid := sd.SpanContext().SpanID()
103
104 s := &tracepb.Span{
105 TraceId: tid[:],
106 SpanId: sid[:],
107 TraceState: sd.SpanContext().TraceState().String(),
108 Status: status(sd.Status().Code, sd.Status().Description),
109 StartTimeUnixNano: uint64(sd.StartTime().UnixNano()),
110 EndTimeUnixNano: uint64(sd.EndTime().UnixNano()),
111 Links: links(sd.Links()),
112 Kind: spanKind(sd.SpanKind()),
113 Name: sd.Name(),
114 Attributes: KeyValues(sd.Attributes()),
115 Events: spanEvents(sd.Events()),
116 DroppedAttributesCount: uint32(sd.DroppedAttributes()),
117 DroppedEventsCount: uint32(sd.DroppedEvents()),
118 DroppedLinksCount: uint32(sd.DroppedLinks()),
119 }
120
121 if psid := sd.Parent().SpanID(); psid.IsValid() {
122 s.ParentSpanId = psid[:]
123 }
124
125 return s
126 }
127
128
129 func status(status codes.Code, message string) *tracepb.Status {
130 var c tracepb.Status_StatusCode
131 switch status {
132 case codes.Ok:
133 c = tracepb.Status_STATUS_CODE_OK
134 case codes.Error:
135 c = tracepb.Status_STATUS_CODE_ERROR
136 default:
137 c = tracepb.Status_STATUS_CODE_UNSET
138 }
139 return &tracepb.Status{
140 Code: c,
141 Message: message,
142 }
143 }
144
145
146 func links(links []tracesdk.Link) []*tracepb.Span_Link {
147 if len(links) == 0 {
148 return nil
149 }
150
151 sl := make([]*tracepb.Span_Link, 0, len(links))
152 for _, otLink := range links {
153
154
155 otLink := otLink
156
157 tid := otLink.SpanContext.TraceID()
158 sid := otLink.SpanContext.SpanID()
159
160 sl = append(sl, &tracepb.Span_Link{
161 TraceId: tid[:],
162 SpanId: sid[:],
163 Attributes: KeyValues(otLink.Attributes),
164 DroppedAttributesCount: uint32(otLink.DroppedAttributeCount),
165 })
166 }
167 return sl
168 }
169
170
171 func spanEvents(es []tracesdk.Event) []*tracepb.Span_Event {
172 if len(es) == 0 {
173 return nil
174 }
175
176 events := make([]*tracepb.Span_Event, len(es))
177
178 for i := 0; i < len(es); i++ {
179 events[i] = &tracepb.Span_Event{
180 Name: es[i].Name,
181 TimeUnixNano: uint64(es[i].Time.UnixNano()),
182 Attributes: KeyValues(es[i].Attributes),
183 DroppedAttributesCount: uint32(es[i].DroppedAttributeCount),
184 }
185 }
186 return events
187 }
188
189
190 func spanKind(kind trace.SpanKind) tracepb.Span_SpanKind {
191 switch kind {
192 case trace.SpanKindInternal:
193 return tracepb.Span_SPAN_KIND_INTERNAL
194 case trace.SpanKindClient:
195 return tracepb.Span_SPAN_KIND_CLIENT
196 case trace.SpanKindServer:
197 return tracepb.Span_SPAN_KIND_SERVER
198 case trace.SpanKindProducer:
199 return tracepb.Span_SPAN_KIND_PRODUCER
200 case trace.SpanKindConsumer:
201 return tracepb.Span_SPAN_KIND_CONSUMER
202 default:
203 return tracepb.Span_SPAN_KIND_UNSPECIFIED
204 }
205 }
206
View as plain text