forked from jaegertracing/jaeger
/
to_domain.go
158 lines (141 loc) · 5.24 KB
/
to_domain.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright (c) 2017 Uber Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package jaeger
import (
"fmt"
"github.com/jaegertracing/jaeger/model"
"github.com/jaegertracing/jaeger/thrift-gen/jaeger"
)
// ToDomain transforms a set of spans and a process in jaeger.thrift format into a slice of model.Span.
// A valid []*model.Span is always returned, even when there are errors.
// Errors are presented as tags on spans
func ToDomain(jSpans []*jaeger.Span, jProcess *jaeger.Process) []*model.Span {
return toDomain{}.ToDomain(jSpans, jProcess)
}
// ToDomainSpan transforms a span in jaeger.thrift format into model.Span.
// A valid model.Span is always returned, even when there are errors.
// Errors are presented as tags on spans
func ToDomainSpan(jSpan *jaeger.Span, jProcess *jaeger.Process) *model.Span {
return toDomain{}.ToDomainSpan(jSpan, jProcess)
}
// ToDomainProcess transforms a process in jaeger.thrift format to model.Span.
func ToDomainProcess(jProcess *jaeger.Process) *model.Process {
return toDomain{}.getProcess(jProcess)
}
type toDomain struct{}
func (td toDomain) ToDomain(jSpans []*jaeger.Span, jProcess *jaeger.Process) []*model.Span {
spans := make([]*model.Span, len(jSpans))
mProcess := td.getProcess(jProcess)
for i, jSpan := range jSpans {
spans[i] = td.transformSpan(jSpan, mProcess)
}
return spans
}
func (td toDomain) ToDomainSpan(jSpan *jaeger.Span, jProcess *jaeger.Process) *model.Span {
mProcess := td.getProcess(jProcess)
return td.transformSpan(jSpan, mProcess)
}
func (td toDomain) transformSpan(jSpan *jaeger.Span, mProcess *model.Process) *model.Span {
traceID := model.NewTraceID(uint64(jSpan.TraceIdHigh), uint64(jSpan.TraceIdLow))
//allocate extra space for future append operation
tags := td.getTags(jSpan.Tags, 1)
refs := td.getReferences(jSpan.References)
// We no longer store ParentSpanID in the domain model, but the data in Thrift model
// might still have these IDs without representing them in the References, so we
// convert it back into child-of reference.
if jSpan.ParentSpanId != 0 {
parentSpanID := model.NewSpanID(uint64(jSpan.ParentSpanId))
refs = model.MaybeAddParentSpanID(traceID, parentSpanID, refs)
}
return &model.Span{
TraceID: traceID,
SpanID: model.NewSpanID(uint64(jSpan.SpanId)),
OperationName: jSpan.OperationName,
References: refs,
Flags: model.Flags(jSpan.Flags),
StartTime: model.EpochMicrosecondsAsTime(uint64(jSpan.StartTime)),
Duration: model.MicrosecondsAsDuration(uint64(jSpan.Duration)),
Tags: tags,
Logs: td.getLogs(jSpan.Logs),
Process: mProcess,
}
}
func (td toDomain) getReferences(jRefs []*jaeger.SpanRef) []model.SpanRef {
if len(jRefs) == 0 {
return nil
}
mRefs := make([]model.SpanRef, len(jRefs))
for idx, jRef := range jRefs {
mRefs[idx] = model.SpanRef{
RefType: model.SpanRefType(int(jRef.RefType)),
TraceID: model.NewTraceID(uint64(jRef.TraceIdHigh), uint64(jRef.TraceIdLow)),
SpanID: model.NewSpanID(uint64(jRef.SpanId)),
}
}
return mRefs
}
// getProcess takes a jaeger.thrift process and produces a model.Process.
// Any errors are presented as tags
func (td toDomain) getProcess(jProcess *jaeger.Process) *model.Process {
if jProcess == nil {
return nil
}
tags := td.getTags(jProcess.Tags, 0)
return &model.Process{
Tags: tags,
ServiceName: jProcess.ServiceName,
}
}
//convert the jaeger.Tag slice to domain KeyValue slice
//zipkin/to_domain.go does not give a default slice size since it has to filter annotations, jaeger conversion is more predictable
//thus to avoid future full array copy when using append, pre-allocate extra space as an optimization
func (td toDomain) getTags(tags []*jaeger.Tag, extraSpace int) model.KeyValues {
if len(tags) == 0 {
return nil
}
retMe := make(model.KeyValues, len(tags), len(tags)+extraSpace)
for i, tag := range tags {
retMe[i] = td.getTag(tag)
}
return retMe
}
func (td toDomain) getTag(tag *jaeger.Tag) model.KeyValue {
switch tag.VType {
case jaeger.TagType_BOOL:
return model.Bool(tag.Key, tag.GetVBool())
case jaeger.TagType_BINARY:
return model.Binary(tag.Key, tag.GetVBinary())
case jaeger.TagType_DOUBLE:
return model.Float64(tag.Key, tag.GetVDouble())
case jaeger.TagType_LONG:
return model.Int64(tag.Key, tag.GetVLong())
case jaeger.TagType_STRING:
return model.String(tag.Key, tag.GetVStr())
default:
return model.String(tag.Key, fmt.Sprintf("Unknown VType: %+v", tag))
}
}
func (td toDomain) getLogs(logs []*jaeger.Log) []model.Log {
if len(logs) == 0 {
return nil
}
retMe := make([]model.Log, len(logs))
for i, log := range logs {
retMe[i] = model.Log{
Timestamp: model.EpochMicrosecondsAsTime(uint64(log.Timestamp)),
Fields: td.getTags(log.Fields, 0),
}
}
return retMe
}