github.com/alibaba/ilogtail/pkg@v0.0.0-20250526110833-c53b480d046c/models/span.go (about) 1 // Copyright 2022 iLogtail Authors 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 models 16 17 type SpanKind int 18 19 const ( 20 _ SpanKind = iota 21 // Indicates that the span represents an internal operation within an application, 22 // as opposed to an operation happening at the boundaries. Default value. 23 SpanKindInternal 24 25 // Indicates that the span covers server-side handling of an RPC or other 26 // remote network request. 27 SpanKindServer 28 29 // Indicates that the span describes a request to some remote service. 30 SpanKindClient 31 32 // Indicates that the span describes a producer sending a message to a broker. 33 // Unlike CLIENT and SERVER, there is often no direct critical path latency relationship 34 // between producer and consumer spans. A PRODUCER span ends when the message was accepted 35 // by the broker while the logical processing of the message might span a much longer time. 36 SpanKindProducer 37 38 // Indicates that the span describes consumer receiving a message from a broker. 39 // Like the PRODUCER kind, there is often no direct critical path latency relationship 40 // between producer and consumer spans. 41 SpanKindConsumer 42 ) 43 44 type SpanKindText string 45 46 const ( 47 SpanKindTextInternal = "internal" 48 SpanKindTextServer = "server" 49 SpanKindTextClient = "client" 50 SpanKindTextProducer = "producer" 51 SpanKindTextConsumer = "consumer" 52 ) 53 54 type StatusCode int 55 56 const ( 57 StatusCodeUnSet StatusCode = iota 58 StatusCodeOK 59 StatusCodeError 60 ) 61 62 var ( 63 SpanKindTexts = map[SpanKind]SpanKindText{ 64 SpanKindInternal: SpanKindTextInternal, 65 SpanKindServer: SpanKindTextServer, 66 SpanKindClient: SpanKindTextClient, 67 SpanKindProducer: SpanKindTextProducer, 68 SpanKindConsumer: SpanKindTextConsumer, 69 } 70 SpanKindValues = map[SpanKindText]SpanKind{ 71 SpanKindTextInternal: SpanKindInternal, 72 SpanKindTextServer: SpanKindServer, 73 SpanKindTextClient: SpanKindClient, 74 SpanKindTextProducer: SpanKindProducer, 75 SpanKindTextConsumer: SpanKindConsumer, 76 } 77 78 noopSpanEvents = make([]*SpanEvent, 0) 79 noopSpanLinks = make([]*SpanLink, 0) 80 ) 81 82 type SpanLink struct { 83 TraceID string 84 SpanID string 85 TraceState string 86 Tags Tags 87 } 88 89 type SpanEvent struct { 90 Timestamp int64 91 Name string 92 Tags Tags 93 } 94 95 // A Span represents a single operation performed by a single component of the system. 96 type Span struct { 97 TraceID string 98 SpanID string 99 ParentSpanID string 100 Name string 101 TraceState string 102 103 StartTime uint64 104 EndTime uint64 105 ObservedTimestamp uint64 106 107 Kind SpanKind 108 Status StatusCode 109 Tags Tags 110 Links []*SpanLink 111 Events []*SpanEvent 112 } 113 114 func (m *Span) GetName() string { 115 if m != nil { 116 return m.Name 117 } 118 return "" 119 } 120 121 func (m *Span) SetName(name string) { 122 if m != nil { 123 m.Name = name 124 } 125 } 126 127 func (m *Span) GetTags() Tags { 128 if m != nil { 129 return m.Tags 130 } 131 return NilStringValues 132 } 133 134 func (m *Span) GetType() EventType { 135 return EventTypeSpan 136 } 137 138 func (m *Span) GetTimestamp() uint64 { 139 if m != nil { 140 return m.StartTime 141 } 142 return 0 143 } 144 145 func (m *Span) GetObservedTimestamp() uint64 { 146 if m != nil { 147 return m.ObservedTimestamp 148 } 149 return 0 150 } 151 152 func (m *Span) SetObservedTimestamp(timestamp uint64) { 153 if m != nil { 154 m.ObservedTimestamp = timestamp 155 } 156 } 157 158 func (m *Span) GetTraceID() string { 159 if m != nil { 160 return m.TraceID 161 } 162 return "" 163 } 164 165 func (m *Span) GetSpanID() string { 166 if m != nil { 167 return m.SpanID 168 } 169 return "" 170 } 171 172 func (m *Span) GetParentSpanID() string { 173 if m != nil { 174 return m.ParentSpanID 175 } 176 return "" 177 } 178 179 func (m *Span) GetTraceState() string { 180 if m != nil { 181 return m.TraceState 182 } 183 return "" 184 } 185 186 func (m *Span) GetStartTime() uint64 { 187 if m != nil { 188 return m.StartTime 189 } 190 return 0 191 } 192 193 func (m *Span) GetEndTime() uint64 { 194 if m != nil { 195 return m.EndTime 196 } 197 return 0 198 } 199 200 func (m *Span) GetKind() SpanKind { 201 if m != nil { 202 return m.Kind 203 } 204 return SpanKind(0) 205 } 206 207 func (m *Span) GetStatus() StatusCode { 208 if m != nil { 209 return m.Status 210 } 211 return StatusCodeUnSet 212 } 213 214 func (m *Span) GetLinks() []*SpanLink { 215 if m != nil { 216 return m.Links 217 } 218 return noopSpanLinks 219 } 220 221 func (m *Span) GetEvents() []*SpanEvent { 222 if m != nil { 223 return m.Events 224 } 225 return noopSpanEvents 226 } 227 228 func (m *Span) GetSize() int64 { 229 if m == nil { 230 return 0 231 } 232 233 var size int64 234 235 // Calculate size of string fields 236 size += int64(len(m.TraceID)) 237 size += int64(len(m.SpanID)) 238 size += int64(len(m.ParentSpanID)) 239 size += int64(len(m.Name)) 240 size += int64(len(m.TraceState)) 241 242 // Calculate size of Tags 243 if m.Tags.Len() > 0 { 244 sortedTags := m.Tags.SortTo(nil) 245 for _, tags := range sortedTags { 246 size += int64(len(tags.Key)) 247 size += int64(len(tags.Value)) 248 } 249 } 250 251 // Calculate size of Links 252 for _, link := range m.Links { 253 if link != nil { 254 size += int64(len(link.TraceID)) 255 size += int64(len(link.SpanID)) 256 size += int64(len(link.TraceState)) 257 if link.Tags.Len() > 0 { 258 sortedTags := link.Tags.SortTo(nil) 259 for _, tags := range sortedTags { 260 size += int64(len(tags.Key)) 261 size += int64(len(tags.Value)) 262 } 263 } 264 } 265 } 266 267 // Calculate size of Events 268 for _, event := range m.Events { 269 if event != nil { 270 size += int64(len(event.Name)) 271 if event.Tags.Len() > 0 { 272 sortedTags := event.Tags.SortTo(nil) 273 for _, tags := range sortedTags { 274 size += int64(len(tags.Key)) 275 size += int64(len(tags.Value)) 276 } 277 } 278 } 279 } 280 281 return size 282 } 283 284 func (m *Span) Clone() PipelineEvent { 285 if m != nil { 286 return &Span{ 287 TraceID: m.TraceID, 288 SpanID: m.SpanID, 289 ParentSpanID: m.ParentSpanID, 290 Name: m.Name, 291 TraceState: m.TraceState, 292 StartTime: m.StartTime, 293 EndTime: m.EndTime, 294 ObservedTimestamp: m.ObservedTimestamp, 295 Kind: m.Kind, 296 Status: m.Status, 297 Tags: m.Tags, 298 Links: m.Links, 299 Events: m.Events, 300 } 301 } 302 return nil 303 }