github.com/kiali/kiali@v1.84.0/tracing/jaeger/model/converter/json/from_domain.go (about) 1 // Copyright (c) 2019 The Jaeger Authors. 2 // Copyright (c) 2017 Uber Technologies, Inc. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 // Cloned from github.com/jaegertracing/jaeger/ 17 18 // nolint 19 package json 20 21 import ( 22 "strings" 23 24 "github.com/kiali/kiali/log" 25 "github.com/kiali/kiali/tracing/jaeger/model" 26 "github.com/kiali/kiali/tracing/jaeger/model/json" 27 ) 28 29 // FromDomain converts model.Trace into json.Trace format. 30 // It assumes that the domain model is valid, namely that all enums 31 // have valid values, so that it does not need to check for errors. 32 func FromDomain(trace *model.Trace) *json.Trace { 33 fd := fromDomain{} 34 fd.convertKeyValuesFunc = fd.convertKeyValues 35 return fd.fromDomain(trace) 36 } 37 38 // FromDomainEmbedProcess converts model.Span into json.Span format. 39 // This format includes a ParentSpanID and an embedded Process. 40 func FromDomainEmbedProcess(span *model.Span) *json.Span { 41 fd := fromDomain{} 42 fd.convertKeyValuesFunc = fd.convertKeyValuesString 43 return fd.convertSpanEmbedProcess(span) 44 } 45 46 type fromDomain struct { 47 convertKeyValuesFunc func(keyValues model.KeyValues) []json.KeyValue 48 } 49 50 func (fd fromDomain) fromDomain(trace *model.Trace) *json.Trace { 51 jSpans := make([]json.Span, len(trace.Spans)) 52 processes := &processHashtable{} 53 var traceID json.TraceID 54 for i, span := range trace.Spans { 55 if i == 0 { 56 traceId := model.TraceID{} 57 traceId.Unmarshal(span.TraceId) 58 traceID = json.TraceID(traceId.String()) 59 } 60 processID := json.ProcessID(processes.getKey(span.Process)) 61 jSpans[i] = fd.convertSpan(span, processID) 62 } 63 jTrace := &json.Trace{ 64 TraceID: traceID, 65 Spans: jSpans, 66 Processes: fd.convertProcesses(processes.getMapping()), 67 Warnings: trace.Warnings, 68 } 69 return jTrace 70 } 71 72 func (fd fromDomain) convertSpanInternal(span *model.Span) json.Span { 73 traceId := model.TraceID{} 74 traceId.Unmarshal(span.TraceId) 75 spanId, err := model.SpanIDFromBytes(span.SpanId) 76 if err != nil { 77 // On purpose to not propagate this error to the upper caller 78 log.Warningf("jaeger SpanId unmarshall error: %v", err) 79 spanId = 0 80 } 81 return json.Span{ 82 TraceID: json.TraceID(traceId.String()), 83 SpanID: json.SpanID(spanId.String()), 84 Flags: uint32(span.Flags), 85 OperationName: span.OperationName, 86 StartTime: model.TimeAsEpochMicroseconds(span.StartTime.AsTime()), 87 Duration: model.DurationAsMicroseconds(span.Duration.AsDuration()), 88 Tags: fd.convertKeyValues(span.Tags), 89 Logs: fd.convertLogs(span.Logs), 90 } 91 } 92 93 func (fd fromDomain) convertSpan(span *model.Span, processID json.ProcessID) json.Span { 94 s := fd.convertSpanInternal(span) 95 s.ProcessID = processID 96 s.Warnings = span.Warnings 97 s.References = fd.convertReferences(span) 98 return s 99 } 100 101 func (fd fromDomain) convertSpanEmbedProcess(span *model.Span) *json.Span { 102 s := fd.convertSpanInternal(span) 103 process := fd.convertProcess(span.Process) 104 s.Process = &process 105 s.References = fd.convertReferences(span) 106 return &s 107 } 108 109 func (fd fromDomain) convertReferences(span *model.Span) []json.Reference { 110 out := make([]json.Reference, 0, len(span.References)) 111 for _, ref := range span.References { 112 traceId := model.TraceID{} 113 traceId.Unmarshal(ref.TraceId) 114 spanId, err := model.SpanIDFromBytes(ref.SpanId) 115 if err != nil { 116 // On purpose to not propagate this error to the upper caller 117 log.Warningf("jaeger SpanId unmarshall error: %v", err) 118 spanId = 0 119 } 120 out = append(out, json.Reference{ 121 RefType: fd.convertRefType(ref.RefType), 122 TraceID: json.TraceID(traceId.String()), 123 SpanID: json.SpanID(spanId.String()), 124 }) 125 } 126 return out 127 } 128 129 func (fd fromDomain) convertRefType(refType model.SpanRefType) json.ReferenceType { 130 if refType == model.FollowsFrom { 131 return json.FollowsFrom 132 } 133 return json.ChildOf 134 } 135 136 func (fd fromDomain) convertKeyValues(keyValues model.KeyValues) []json.KeyValue { 137 out := make([]json.KeyValue, len(keyValues)) 138 for i, kv := range keyValues { 139 var value interface{} 140 switch kv.VType { 141 case model.StringType: 142 value = kv.VStr 143 case model.BoolType: 144 value = kv.Bool() 145 case model.Int64Type: 146 value = kv.Int64() 147 case model.Float64Type: 148 value = kv.Float64() 149 case model.BinaryType: 150 value = kv.Binary() 151 } 152 153 out[i] = json.KeyValue{ 154 Key: kv.Key, 155 Type: json.ValueType(strings.ToLower(kv.VType.String())), 156 Value: value, 157 } 158 } 159 return out 160 } 161 162 func (fd fromDomain) convertKeyValuesString(keyValues model.KeyValues) []json.KeyValue { 163 out := make([]json.KeyValue, len(keyValues)) 164 for i, kv := range keyValues { 165 out[i] = json.KeyValue{ 166 Key: kv.Key, 167 Type: json.ValueType(strings.ToLower(kv.VType.String())), 168 Value: kv.AsString(), 169 } 170 } 171 return out 172 } 173 174 func (fd fromDomain) convertLogs(logs []*model.Log) []json.Log { 175 out := make([]json.Log, len(logs)) 176 for i, log := range logs { 177 out[i] = json.Log{ 178 Timestamp: model.TimeAsEpochMicroseconds(log.Timestamp.AsTime()), 179 Fields: fd.convertKeyValuesFunc(log.Fields), 180 } 181 } 182 return out 183 } 184 185 func (fd fromDomain) convertProcesses(processes map[string]*model.Process) map[json.ProcessID]json.Process { 186 out := make(map[json.ProcessID]json.Process) 187 for key, process := range processes { 188 out[json.ProcessID(key)] = fd.convertProcess(process) 189 } 190 return out 191 } 192 193 func (fd fromDomain) convertProcess(process *model.Process) json.Process { 194 return json.Process{ 195 ServiceName: process.ServiceName, 196 Tags: fd.convertKeyValuesFunc(process.Tags), 197 } 198 } 199 200 // DependenciesFromDomain converts []model.DependencyLink into []json.DependencyLink format. 201 func DependenciesFromDomain(dependencyLinks []model.DependencyLink) []json.DependencyLink { 202 retMe := make([]json.DependencyLink, 0, len(dependencyLinks)) 203 for _, dependencyLink := range dependencyLinks { 204 retMe = append( 205 retMe, 206 json.DependencyLink{ 207 Parent: dependencyLink.Parent, 208 Child: dependencyLink.Child, 209 CallCount: dependencyLink.CallCount, 210 }, 211 ) 212 } 213 return retMe 214 }