github.com/matrixorigin/matrixone@v0.7.0/pkg/util/export/observability/trace/span.go (about) 1 // Copyright 2022 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package trace 16 17 import ( 18 "context" 19 "encoding/hex" 20 "encoding/json" 21 "github.com/matrixorigin/matrixone/pkg/util/export/observability" 22 "sync" 23 "time" 24 "unsafe" 25 26 "github.com/matrixorigin/matrixone/pkg/util/export/table" 27 28 v11 "go.opentelemetry.io/proto/otlp/common/v1" 29 v1 "go.opentelemetry.io/proto/otlp/resource/v1" 30 tracepb "go.opentelemetry.io/proto/otlp/trace/v1" 31 ) 32 33 type Span struct { 34 TraceId string 35 SpanId string 36 ParentSpanId string 37 Kind string 38 Name string 39 StartTime time.Time 40 EndTime time.Time 41 Duration uint64 42 Status *tracepb.Status 43 Resource *v1.Resource 44 Attributes []*v11.KeyValue 45 Links []*tracepb.Span_Link 46 Events []*tracepb.Span_Event 47 } 48 49 var spanPool = &sync.Pool{New: func() any { 50 return &Span{} 51 }} 52 53 func NewSpan() *Span { 54 return spanPool.Get().(*Span) 55 } 56 57 func (*Span) GetName() string { 58 return observability.SpansTable.GetIdentify() 59 } 60 61 func (*Span) GetTable() *table.Table { 62 return observability.SpansTable 63 } 64 65 func (s *Span) FillRow(ctx context.Context, row *table.Row) { 66 row.Reset() 67 row.SetColumnVal(observability.SpansTraceIDCol, s.TraceId) 68 row.SetColumnVal(observability.SpansSpanIDCol, s.SpanId) 69 row.SetColumnVal(observability.SpansParentTraceIDCol, s.ParentSpanId) 70 row.SetColumnVal(observability.SpansSpanKindCol, s.Kind) 71 row.SetColumnVal(observability.SpansSpanNameCol, s.Name) 72 row.SetColumnVal(observability.SpansStartTimeCol, s.StartTime) 73 row.SetColumnVal(observability.SpansEndTimeCol, s.EndTime) 74 row.SetColumnVal(observability.SpansDurationCol, s.Duration) 75 row.SetColumnVal(observability.SpansStatusCol, trsfStatus(s.Status)) 76 row.SetColumnVal(observability.SpansResourceCol, trsfResource(s.Resource)) 77 row.SetColumnVal(observability.SpansAttributesCol, trsfAttributes(s.Attributes)) 78 row.SetColumnVal(observability.SpansLinksCol, trsfSpanLink(s.Links)) 79 row.SetColumnVal(observability.SpansEventsCol, trsfEvents(s.Events)) 80 } 81 82 func (s *Span) Size() int64 { 83 return int64(unsafe.Sizeof(s)) + int64( 84 len(s.TraceId)+len(s.SpanId)+len(s.ParentSpanId)+len(s.Kind)+len(s.Name), 85 ) 86 } 87 88 func (s *Span) Free() { 89 s.TraceId = "" 90 s.SpanId = "" 91 s.ParentSpanId = "" 92 s.Kind = "" 93 s.Name = "" 94 s.StartTime = time.Time{} 95 s.EndTime = time.Time{} 96 s.Duration = 0 97 s.Resource = nil 98 s.Links = nil 99 s.Attributes = nil 100 spanPool.Put(s) 101 } 102 103 func trsfResource(r *v1.Resource) string { 104 return trsfAttributes(r.Attributes) 105 } 106 107 func trsfAttributes(kvs []*v11.KeyValue) string { 108 109 obj := TransferAttributes(kvs) 110 bytes, err := json.Marshal(&obj) 111 if err != nil { 112 return "{}" 113 } 114 return string(bytes[:]) 115 } 116 117 func trsfStatus(s *tracepb.Status) string { 118 if bytes, err := json.Marshal(s); err != nil { 119 return "{}" 120 } else { 121 return string(bytes[:]) 122 } 123 } 124 125 func trsfSpanLink(links []*tracepb.Span_Link) string { 126 if bytes, err := json.Marshal(&links); err != nil { 127 return "[]" 128 } else { 129 return string(bytes[:]) 130 } 131 } 132 133 func trsfEvents(events []*tracepb.Span_Event) string { 134 if bytes, err := json.Marshal(&events); err != nil { 135 return "[]" 136 } else { 137 return string(bytes[:]) 138 } 139 } 140 141 func TransferAttributes(attrs []*v11.KeyValue) map[string]any { 142 143 m := make(map[string]any, len(attrs)) 144 for _, kv := range attrs { 145 146 key := kv.GetKey() 147 val := kv.GetValue() 148 switch val.Value.(type) { 149 case *v11.AnyValue_StringValue: 150 m[key] = val.GetStringValue() 151 case *v11.AnyValue_BoolValue: 152 m[key] = val.GetBoolValue() 153 case *v11.AnyValue_IntValue: 154 m[key] = val.GetIntValue() 155 case *v11.AnyValue_DoubleValue: 156 m[key] = val.GetDoubleValue() 157 case *v11.AnyValue_BytesValue: 158 m[key] = hex.EncodeToString(val.GetBytesValue()) 159 case *v11.AnyValue_ArrayValue: 160 m[key] = TransferArrayValue(val.GetArrayValue()) 161 case *v11.AnyValue_KvlistValue: 162 m[key] = TransferAttributes(val.GetKvlistValue().GetValues()) 163 default: 164 m[key] = val 165 } 166 } 167 return m 168 } 169 170 func TransferArrayValue(vals *v11.ArrayValue) []any { 171 if len(vals.Values) == 0 { 172 return nil 173 } 174 175 val := vals.Values[0] 176 arr := make([]any, 0, len(vals.Values)) 177 178 switch val.Value.(type) { 179 case *v11.AnyValue_StringValue: 180 for _, v := range vals.Values { 181 arr = append(arr, v.GetStringValue()) 182 } 183 case *v11.AnyValue_BoolValue: 184 for _, v := range vals.Values { 185 arr = append(arr, v.GetBoolValue()) 186 } 187 case *v11.AnyValue_IntValue: 188 for _, v := range vals.Values { 189 arr = append(arr, v.GetIntValue()) 190 } 191 case *v11.AnyValue_DoubleValue: 192 for _, v := range vals.Values { 193 arr = append(arr, v.GetDoubleValue()) 194 } 195 default: 196 for _, v := range vals.Values { 197 arr = append(arr, v.GetValue()) 198 } 199 } 200 return arr 201 }