span.go (24798B)
1 // Copyright The OpenTelemetry 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 trace // import "go.opentelemetry.io/otel/sdk/trace" 16 17 import ( 18 "context" 19 "fmt" 20 "reflect" 21 "runtime" 22 rt "runtime/trace" 23 "strings" 24 "sync" 25 "time" 26 "unicode/utf8" 27 28 "go.opentelemetry.io/otel/attribute" 29 "go.opentelemetry.io/otel/codes" 30 "go.opentelemetry.io/otel/sdk/instrumentation" 31 "go.opentelemetry.io/otel/sdk/internal" 32 "go.opentelemetry.io/otel/sdk/resource" 33 semconv "go.opentelemetry.io/otel/semconv/v1.17.0" 34 "go.opentelemetry.io/otel/trace" 35 ) 36 37 // ReadOnlySpan allows reading information from the data structure underlying a 38 // trace.Span. It is used in places where reading information from a span is 39 // necessary but changing the span isn't necessary or allowed. 40 // 41 // Warning: methods may be added to this interface in minor releases. 42 type ReadOnlySpan interface { 43 // Name returns the name of the span. 44 Name() string 45 // SpanContext returns the unique SpanContext that identifies the span. 46 SpanContext() trace.SpanContext 47 // Parent returns the unique SpanContext that identifies the parent of the 48 // span if one exists. If the span has no parent the returned SpanContext 49 // will be invalid. 50 Parent() trace.SpanContext 51 // SpanKind returns the role the span plays in a Trace. 52 SpanKind() trace.SpanKind 53 // StartTime returns the time the span started recording. 54 StartTime() time.Time 55 // EndTime returns the time the span stopped recording. It will be zero if 56 // the span has not ended. 57 EndTime() time.Time 58 // Attributes returns the defining attributes of the span. 59 // The order of the returned attributes is not guaranteed to be stable across invocations. 60 Attributes() []attribute.KeyValue 61 // Links returns all the links the span has to other spans. 62 Links() []Link 63 // Events returns all the events that occurred within in the spans 64 // lifetime. 65 Events() []Event 66 // Status returns the spans status. 67 Status() Status 68 // InstrumentationScope returns information about the instrumentation 69 // scope that created the span. 70 InstrumentationScope() instrumentation.Scope 71 // InstrumentationLibrary returns information about the instrumentation 72 // library that created the span. 73 // Deprecated: please use InstrumentationScope instead. 74 InstrumentationLibrary() instrumentation.Library 75 // Resource returns information about the entity that produced the span. 76 Resource() *resource.Resource 77 // DroppedAttributes returns the number of attributes dropped by the span 78 // due to limits being reached. 79 DroppedAttributes() int 80 // DroppedLinks returns the number of links dropped by the span due to 81 // limits being reached. 82 DroppedLinks() int 83 // DroppedEvents returns the number of events dropped by the span due to 84 // limits being reached. 85 DroppedEvents() int 86 // ChildSpanCount returns the count of spans that consider the span a 87 // direct parent. 88 ChildSpanCount() int 89 90 // A private method to prevent users implementing the 91 // interface and so future additions to it will not 92 // violate compatibility. 93 private() 94 } 95 96 // ReadWriteSpan exposes the same methods as trace.Span and in addition allows 97 // reading information from the underlying data structure. 98 // This interface exposes the union of the methods of trace.Span (which is a 99 // "write-only" span) and ReadOnlySpan. New methods for writing or reading span 100 // information should be added under trace.Span or ReadOnlySpan, respectively. 101 // 102 // Warning: methods may be added to this interface in minor releases. 103 type ReadWriteSpan interface { 104 trace.Span 105 ReadOnlySpan 106 } 107 108 // recordingSpan is an implementation of the OpenTelemetry Span API 109 // representing the individual component of a trace that is sampled. 110 type recordingSpan struct { 111 // mu protects the contents of this span. 112 mu sync.Mutex 113 114 // parent holds the parent span of this span as a trace.SpanContext. 115 parent trace.SpanContext 116 117 // spanKind represents the kind of this span as a trace.SpanKind. 118 spanKind trace.SpanKind 119 120 // name is the name of this span. 121 name string 122 123 // startTime is the time at which this span was started. 124 startTime time.Time 125 126 // endTime is the time at which this span was ended. It contains the zero 127 // value of time.Time until the span is ended. 128 endTime time.Time 129 130 // status is the status of this span. 131 status Status 132 133 // childSpanCount holds the number of child spans created for this span. 134 childSpanCount int 135 136 // spanContext holds the SpanContext of this span. 137 spanContext trace.SpanContext 138 139 // attributes is a collection of user provided key/values. The collection 140 // is constrained by a configurable maximum held by the parent 141 // TracerProvider. When additional attributes are added after this maximum 142 // is reached these attributes the user is attempting to add are dropped. 143 // This dropped number of attributes is tracked and reported in the 144 // ReadOnlySpan exported when the span ends. 145 attributes []attribute.KeyValue 146 droppedAttributes int 147 148 // events are stored in FIFO queue capped by configured limit. 149 events evictedQueue 150 151 // links are stored in FIFO queue capped by configured limit. 152 links evictedQueue 153 154 // executionTracerTaskEnd ends the execution tracer span. 155 executionTracerTaskEnd func() 156 157 // tracer is the SDK tracer that created this span. 158 tracer *tracer 159 } 160 161 var _ ReadWriteSpan = (*recordingSpan)(nil) 162 var _ runtimeTracer = (*recordingSpan)(nil) 163 164 // SpanContext returns the SpanContext of this span. 165 func (s *recordingSpan) SpanContext() trace.SpanContext { 166 if s == nil { 167 return trace.SpanContext{} 168 } 169 return s.spanContext 170 } 171 172 // IsRecording returns if this span is being recorded. If this span has ended 173 // this will return false. 174 func (s *recordingSpan) IsRecording() bool { 175 if s == nil { 176 return false 177 } 178 s.mu.Lock() 179 defer s.mu.Unlock() 180 181 return s.endTime.IsZero() 182 } 183 184 // SetStatus sets the status of the Span in the form of a code and a 185 // description, overriding previous values set. The description is only 186 // included in the set status when the code is for an error. If this span is 187 // not being recorded than this method does nothing. 188 func (s *recordingSpan) SetStatus(code codes.Code, description string) { 189 if !s.IsRecording() { 190 return 191 } 192 s.mu.Lock() 193 defer s.mu.Unlock() 194 if s.status.Code > code { 195 return 196 } 197 198 status := Status{Code: code} 199 if code == codes.Error { 200 status.Description = description 201 } 202 203 s.status = status 204 } 205 206 // SetAttributes sets attributes of this span. 207 // 208 // If a key from attributes already exists the value associated with that key 209 // will be overwritten with the value contained in attributes. 210 // 211 // If this span is not being recorded than this method does nothing. 212 // 213 // If adding attributes to the span would exceed the maximum amount of 214 // attributes the span is configured to have, the last added attributes will 215 // be dropped. 216 func (s *recordingSpan) SetAttributes(attributes ...attribute.KeyValue) { 217 if !s.IsRecording() { 218 return 219 } 220 221 s.mu.Lock() 222 defer s.mu.Unlock() 223 224 limit := s.tracer.provider.spanLimits.AttributeCountLimit 225 if limit == 0 { 226 // No attributes allowed. 227 s.droppedAttributes += len(attributes) 228 return 229 } 230 231 // If adding these attributes could exceed the capacity of s perform a 232 // de-duplication and truncation while adding to avoid over allocation. 233 if limit > 0 && len(s.attributes)+len(attributes) > limit { 234 s.addOverCapAttrs(limit, attributes) 235 return 236 } 237 238 // Otherwise, add without deduplication. When attributes are read they 239 // will be deduplicated, optimizing the operation. 240 for _, a := range attributes { 241 if !a.Valid() { 242 // Drop all invalid attributes. 243 s.droppedAttributes++ 244 continue 245 } 246 a = truncateAttr(s.tracer.provider.spanLimits.AttributeValueLengthLimit, a) 247 s.attributes = append(s.attributes, a) 248 } 249 } 250 251 // addOverCapAttrs adds the attributes attrs to the span s while 252 // de-duplicating the attributes of s and attrs and dropping attributes that 253 // exceed the limit. 254 // 255 // This method assumes s.mu.Lock is held by the caller. 256 // 257 // This method should only be called when there is a possibility that adding 258 // attrs to s will exceed the limit. Otherwise, attrs should be added to s 259 // without checking for duplicates and all retrieval methods of the attributes 260 // for s will de-duplicate as needed. 261 // 262 // This method assumes limit is a value > 0. The argument should be validated 263 // by the caller. 264 func (s *recordingSpan) addOverCapAttrs(limit int, attrs []attribute.KeyValue) { 265 // In order to not allocate more capacity to s.attributes than needed, 266 // prune and truncate this addition of attributes while adding. 267 268 // Do not set a capacity when creating this map. Benchmark testing has 269 // showed this to only add unused memory allocations in general use. 270 exists := make(map[attribute.Key]int) 271 s.dedupeAttrsFromRecord(&exists) 272 273 // Now that s.attributes is deduplicated, adding unique attributes up to 274 // the capacity of s will not over allocate s.attributes. 275 for _, a := range attrs { 276 if !a.Valid() { 277 // Drop all invalid attributes. 278 s.droppedAttributes++ 279 continue 280 } 281 282 if idx, ok := exists[a.Key]; ok { 283 // Perform all updates before dropping, even when at capacity. 284 s.attributes[idx] = a 285 continue 286 } 287 288 if len(s.attributes) >= limit { 289 // Do not just drop all of the remaining attributes, make sure 290 // updates are checked and performed. 291 s.droppedAttributes++ 292 } else { 293 a = truncateAttr(s.tracer.provider.spanLimits.AttributeValueLengthLimit, a) 294 s.attributes = append(s.attributes, a) 295 exists[a.Key] = len(s.attributes) - 1 296 } 297 } 298 } 299 300 // truncateAttr returns a truncated version of attr. Only string and string 301 // slice attribute values are truncated. String values are truncated to at 302 // most a length of limit. Each string slice value is truncated in this fashion 303 // (the slice length itself is unaffected). 304 // 305 // No truncation is performed for a negative limit. 306 func truncateAttr(limit int, attr attribute.KeyValue) attribute.KeyValue { 307 if limit < 0 { 308 return attr 309 } 310 switch attr.Value.Type() { 311 case attribute.STRING: 312 if v := attr.Value.AsString(); len(v) > limit { 313 return attr.Key.String(safeTruncate(v, limit)) 314 } 315 case attribute.STRINGSLICE: 316 v := attr.Value.AsStringSlice() 317 for i := range v { 318 if len(v[i]) > limit { 319 v[i] = safeTruncate(v[i], limit) 320 } 321 } 322 return attr.Key.StringSlice(v) 323 } 324 return attr 325 } 326 327 // safeTruncate truncates the string and guarantees valid UTF-8 is returned. 328 func safeTruncate(input string, limit int) string { 329 if trunc, ok := safeTruncateValidUTF8(input, limit); ok { 330 return trunc 331 } 332 trunc, _ := safeTruncateValidUTF8(strings.ToValidUTF8(input, ""), limit) 333 return trunc 334 } 335 336 // safeTruncateValidUTF8 returns a copy of the input string safely truncated to 337 // limit. The truncation is ensured to occur at the bounds of complete UTF-8 338 // characters. If invalid encoding of UTF-8 is encountered, input is returned 339 // with false, otherwise, the truncated input will be returned with true. 340 func safeTruncateValidUTF8(input string, limit int) (string, bool) { 341 for cnt := 0; cnt <= limit; { 342 r, size := utf8.DecodeRuneInString(input[cnt:]) 343 if r == utf8.RuneError { 344 return input, false 345 } 346 347 if cnt+size > limit { 348 return input[:cnt], true 349 } 350 cnt += size 351 } 352 return input, true 353 } 354 355 // End ends the span. This method does nothing if the span is already ended or 356 // is not being recorded. 357 // 358 // The only SpanOption currently supported is WithTimestamp which will set the 359 // end time for a Span's life-cycle. 360 // 361 // If this method is called while panicking an error event is added to the 362 // Span before ending it and the panic is continued. 363 func (s *recordingSpan) End(options ...trace.SpanEndOption) { 364 // Do not start by checking if the span is being recorded which requires 365 // acquiring a lock. Make a minimal check that the span is not nil. 366 if s == nil { 367 return 368 } 369 370 // Store the end time as soon as possible to avoid artificially increasing 371 // the span's duration in case some operation below takes a while. 372 et := internal.MonotonicEndTime(s.startTime) 373 374 // Do relative expensive check now that we have an end time and see if we 375 // need to do any more processing. 376 if !s.IsRecording() { 377 return 378 } 379 380 config := trace.NewSpanEndConfig(options...) 381 if recovered := recover(); recovered != nil { 382 // Record but don't stop the panic. 383 defer panic(recovered) 384 opts := []trace.EventOption{ 385 trace.WithAttributes( 386 semconv.ExceptionType(typeStr(recovered)), 387 semconv.ExceptionMessage(fmt.Sprint(recovered)), 388 ), 389 } 390 391 if config.StackTrace() { 392 opts = append(opts, trace.WithAttributes( 393 semconv.ExceptionStacktrace(recordStackTrace()), 394 )) 395 } 396 397 s.addEvent(semconv.ExceptionEventName, opts...) 398 } 399 400 if s.executionTracerTaskEnd != nil { 401 s.executionTracerTaskEnd() 402 } 403 404 s.mu.Lock() 405 // Setting endTime to non-zero marks the span as ended and not recording. 406 if config.Timestamp().IsZero() { 407 s.endTime = et 408 } else { 409 s.endTime = config.Timestamp() 410 } 411 s.mu.Unlock() 412 413 sps := s.tracer.provider.getSpanProcessors() 414 if len(sps) == 0 { 415 return 416 } 417 snap := s.snapshot() 418 for _, sp := range sps { 419 sp.sp.OnEnd(snap) 420 } 421 } 422 423 // RecordError will record err as a span event for this span. An additional call to 424 // SetStatus is required if the Status of the Span should be set to Error, this method 425 // does not change the Span status. If this span is not being recorded or err is nil 426 // than this method does nothing. 427 func (s *recordingSpan) RecordError(err error, opts ...trace.EventOption) { 428 if s == nil || err == nil || !s.IsRecording() { 429 return 430 } 431 432 opts = append(opts, trace.WithAttributes( 433 semconv.ExceptionType(typeStr(err)), 434 semconv.ExceptionMessage(err.Error()), 435 )) 436 437 c := trace.NewEventConfig(opts...) 438 if c.StackTrace() { 439 opts = append(opts, trace.WithAttributes( 440 semconv.ExceptionStacktrace(recordStackTrace()), 441 )) 442 } 443 444 s.addEvent(semconv.ExceptionEventName, opts...) 445 } 446 447 func typeStr(i interface{}) string { 448 t := reflect.TypeOf(i) 449 if t.PkgPath() == "" && t.Name() == "" { 450 // Likely a builtin type. 451 return t.String() 452 } 453 return fmt.Sprintf("%s.%s", t.PkgPath(), t.Name()) 454 } 455 456 func recordStackTrace() string { 457 stackTrace := make([]byte, 2048) 458 n := runtime.Stack(stackTrace, false) 459 460 return string(stackTrace[0:n]) 461 } 462 463 // AddEvent adds an event with the provided name and options. If this span is 464 // not being recorded than this method does nothing. 465 func (s *recordingSpan) AddEvent(name string, o ...trace.EventOption) { 466 if !s.IsRecording() { 467 return 468 } 469 s.addEvent(name, o...) 470 } 471 472 func (s *recordingSpan) addEvent(name string, o ...trace.EventOption) { 473 c := trace.NewEventConfig(o...) 474 e := Event{Name: name, Attributes: c.Attributes(), Time: c.Timestamp()} 475 476 // Discard attributes over limit. 477 limit := s.tracer.provider.spanLimits.AttributePerEventCountLimit 478 if limit == 0 { 479 // Drop all attributes. 480 e.DroppedAttributeCount = len(e.Attributes) 481 e.Attributes = nil 482 } else if limit > 0 && len(e.Attributes) > limit { 483 // Drop over capacity. 484 e.DroppedAttributeCount = len(e.Attributes) - limit 485 e.Attributes = e.Attributes[:limit] 486 } 487 488 s.mu.Lock() 489 s.events.add(e) 490 s.mu.Unlock() 491 } 492 493 // SetName sets the name of this span. If this span is not being recorded than 494 // this method does nothing. 495 func (s *recordingSpan) SetName(name string) { 496 if !s.IsRecording() { 497 return 498 } 499 500 s.mu.Lock() 501 defer s.mu.Unlock() 502 s.name = name 503 } 504 505 // Name returns the name of this span. 506 func (s *recordingSpan) Name() string { 507 s.mu.Lock() 508 defer s.mu.Unlock() 509 return s.name 510 } 511 512 // Name returns the SpanContext of this span's parent span. 513 func (s *recordingSpan) Parent() trace.SpanContext { 514 s.mu.Lock() 515 defer s.mu.Unlock() 516 return s.parent 517 } 518 519 // SpanKind returns the SpanKind of this span. 520 func (s *recordingSpan) SpanKind() trace.SpanKind { 521 s.mu.Lock() 522 defer s.mu.Unlock() 523 return s.spanKind 524 } 525 526 // StartTime returns the time this span started. 527 func (s *recordingSpan) StartTime() time.Time { 528 s.mu.Lock() 529 defer s.mu.Unlock() 530 return s.startTime 531 } 532 533 // EndTime returns the time this span ended. For spans that have not yet 534 // ended, the returned value will be the zero value of time.Time. 535 func (s *recordingSpan) EndTime() time.Time { 536 s.mu.Lock() 537 defer s.mu.Unlock() 538 return s.endTime 539 } 540 541 // Attributes returns the attributes of this span. 542 // 543 // The order of the returned attributes is not guaranteed to be stable. 544 func (s *recordingSpan) Attributes() []attribute.KeyValue { 545 s.mu.Lock() 546 defer s.mu.Unlock() 547 s.dedupeAttrs() 548 return s.attributes 549 } 550 551 // dedupeAttrs deduplicates the attributes of s to fit capacity. 552 // 553 // This method assumes s.mu.Lock is held by the caller. 554 func (s *recordingSpan) dedupeAttrs() { 555 // Do not set a capacity when creating this map. Benchmark testing has 556 // showed this to only add unused memory allocations in general use. 557 exists := make(map[attribute.Key]int) 558 s.dedupeAttrsFromRecord(&exists) 559 } 560 561 // dedupeAttrsFromRecord deduplicates the attributes of s to fit capacity 562 // using record as the record of unique attribute keys to their index. 563 // 564 // This method assumes s.mu.Lock is held by the caller. 565 func (s *recordingSpan) dedupeAttrsFromRecord(record *map[attribute.Key]int) { 566 // Use the fact that slices share the same backing array. 567 unique := s.attributes[:0] 568 for _, a := range s.attributes { 569 if idx, ok := (*record)[a.Key]; ok { 570 unique[idx] = a 571 } else { 572 unique = append(unique, a) 573 (*record)[a.Key] = len(unique) - 1 574 } 575 } 576 // s.attributes have element types of attribute.KeyValue. These types are 577 // not pointers and they themselves do not contain pointer fields, 578 // therefore the duplicate values do not need to be zeroed for them to be 579 // garbage collected. 580 s.attributes = unique 581 } 582 583 // Links returns the links of this span. 584 func (s *recordingSpan) Links() []Link { 585 s.mu.Lock() 586 defer s.mu.Unlock() 587 if len(s.links.queue) == 0 { 588 return []Link{} 589 } 590 return s.interfaceArrayToLinksArray() 591 } 592 593 // Events returns the events of this span. 594 func (s *recordingSpan) Events() []Event { 595 s.mu.Lock() 596 defer s.mu.Unlock() 597 if len(s.events.queue) == 0 { 598 return []Event{} 599 } 600 return s.interfaceArrayToEventArray() 601 } 602 603 // Status returns the status of this span. 604 func (s *recordingSpan) Status() Status { 605 s.mu.Lock() 606 defer s.mu.Unlock() 607 return s.status 608 } 609 610 // InstrumentationScope returns the instrumentation.Scope associated with 611 // the Tracer that created this span. 612 func (s *recordingSpan) InstrumentationScope() instrumentation.Scope { 613 s.mu.Lock() 614 defer s.mu.Unlock() 615 return s.tracer.instrumentationScope 616 } 617 618 // InstrumentationLibrary returns the instrumentation.Library associated with 619 // the Tracer that created this span. 620 func (s *recordingSpan) InstrumentationLibrary() instrumentation.Library { 621 s.mu.Lock() 622 defer s.mu.Unlock() 623 return s.tracer.instrumentationScope 624 } 625 626 // Resource returns the Resource associated with the Tracer that created this 627 // span. 628 func (s *recordingSpan) Resource() *resource.Resource { 629 s.mu.Lock() 630 defer s.mu.Unlock() 631 return s.tracer.provider.resource 632 } 633 634 func (s *recordingSpan) addLink(link trace.Link) { 635 if !s.IsRecording() || !link.SpanContext.IsValid() { 636 return 637 } 638 639 l := Link{SpanContext: link.SpanContext, Attributes: link.Attributes} 640 641 // Discard attributes over limit. 642 limit := s.tracer.provider.spanLimits.AttributePerLinkCountLimit 643 if limit == 0 { 644 // Drop all attributes. 645 l.DroppedAttributeCount = len(l.Attributes) 646 l.Attributes = nil 647 } else if limit > 0 && len(l.Attributes) > limit { 648 l.DroppedAttributeCount = len(l.Attributes) - limit 649 l.Attributes = l.Attributes[:limit] 650 } 651 652 s.mu.Lock() 653 s.links.add(l) 654 s.mu.Unlock() 655 } 656 657 // DroppedAttributes returns the number of attributes dropped by the span 658 // due to limits being reached. 659 func (s *recordingSpan) DroppedAttributes() int { 660 s.mu.Lock() 661 defer s.mu.Unlock() 662 return s.droppedAttributes 663 } 664 665 // DroppedLinks returns the number of links dropped by the span due to limits 666 // being reached. 667 func (s *recordingSpan) DroppedLinks() int { 668 s.mu.Lock() 669 defer s.mu.Unlock() 670 return s.links.droppedCount 671 } 672 673 // DroppedEvents returns the number of events dropped by the span due to 674 // limits being reached. 675 func (s *recordingSpan) DroppedEvents() int { 676 s.mu.Lock() 677 defer s.mu.Unlock() 678 return s.events.droppedCount 679 } 680 681 // ChildSpanCount returns the count of spans that consider the span a 682 // direct parent. 683 func (s *recordingSpan) ChildSpanCount() int { 684 s.mu.Lock() 685 defer s.mu.Unlock() 686 return s.childSpanCount 687 } 688 689 // TracerProvider returns a trace.TracerProvider that can be used to generate 690 // additional Spans on the same telemetry pipeline as the current Span. 691 func (s *recordingSpan) TracerProvider() trace.TracerProvider { 692 return s.tracer.provider 693 } 694 695 // snapshot creates a read-only copy of the current state of the span. 696 func (s *recordingSpan) snapshot() ReadOnlySpan { 697 var sd snapshot 698 s.mu.Lock() 699 defer s.mu.Unlock() 700 701 sd.endTime = s.endTime 702 sd.instrumentationScope = s.tracer.instrumentationScope 703 sd.name = s.name 704 sd.parent = s.parent 705 sd.resource = s.tracer.provider.resource 706 sd.spanContext = s.spanContext 707 sd.spanKind = s.spanKind 708 sd.startTime = s.startTime 709 sd.status = s.status 710 sd.childSpanCount = s.childSpanCount 711 712 if len(s.attributes) > 0 { 713 s.dedupeAttrs() 714 sd.attributes = s.attributes 715 } 716 sd.droppedAttributeCount = s.droppedAttributes 717 if len(s.events.queue) > 0 { 718 sd.events = s.interfaceArrayToEventArray() 719 sd.droppedEventCount = s.events.droppedCount 720 } 721 if len(s.links.queue) > 0 { 722 sd.links = s.interfaceArrayToLinksArray() 723 sd.droppedLinkCount = s.links.droppedCount 724 } 725 return &sd 726 } 727 728 func (s *recordingSpan) interfaceArrayToLinksArray() []Link { 729 linkArr := make([]Link, 0) 730 for _, value := range s.links.queue { 731 linkArr = append(linkArr, value.(Link)) 732 } 733 return linkArr 734 } 735 736 func (s *recordingSpan) interfaceArrayToEventArray() []Event { 737 eventArr := make([]Event, 0) 738 for _, value := range s.events.queue { 739 eventArr = append(eventArr, value.(Event)) 740 } 741 return eventArr 742 } 743 744 func (s *recordingSpan) addChild() { 745 if !s.IsRecording() { 746 return 747 } 748 s.mu.Lock() 749 s.childSpanCount++ 750 s.mu.Unlock() 751 } 752 753 func (*recordingSpan) private() {} 754 755 // runtimeTrace starts a "runtime/trace".Task for the span and returns a 756 // context containing the task. 757 func (s *recordingSpan) runtimeTrace(ctx context.Context) context.Context { 758 if !rt.IsEnabled() { 759 // Avoid additional overhead if runtime/trace is not enabled. 760 return ctx 761 } 762 nctx, task := rt.NewTask(ctx, s.name) 763 764 s.mu.Lock() 765 s.executionTracerTaskEnd = task.End 766 s.mu.Unlock() 767 768 return nctx 769 } 770 771 // nonRecordingSpan is a minimal implementation of the OpenTelemetry Span API 772 // that wraps a SpanContext. It performs no operations other than to return 773 // the wrapped SpanContext or TracerProvider that created it. 774 type nonRecordingSpan struct { 775 // tracer is the SDK tracer that created this span. 776 tracer *tracer 777 sc trace.SpanContext 778 } 779 780 var _ trace.Span = nonRecordingSpan{} 781 782 // SpanContext returns the wrapped SpanContext. 783 func (s nonRecordingSpan) SpanContext() trace.SpanContext { return s.sc } 784 785 // IsRecording always returns false. 786 func (nonRecordingSpan) IsRecording() bool { return false } 787 788 // SetStatus does nothing. 789 func (nonRecordingSpan) SetStatus(codes.Code, string) {} 790 791 // SetError does nothing. 792 func (nonRecordingSpan) SetError(bool) {} 793 794 // SetAttributes does nothing. 795 func (nonRecordingSpan) SetAttributes(...attribute.KeyValue) {} 796 797 // End does nothing. 798 func (nonRecordingSpan) End(...trace.SpanEndOption) {} 799 800 // RecordError does nothing. 801 func (nonRecordingSpan) RecordError(error, ...trace.EventOption) {} 802 803 // AddEvent does nothing. 804 func (nonRecordingSpan) AddEvent(string, ...trace.EventOption) {} 805 806 // SetName does nothing. 807 func (nonRecordingSpan) SetName(string) {} 808 809 // TracerProvider returns the trace.TracerProvider that provided the Tracer 810 // that created this span. 811 func (s nonRecordingSpan) TracerProvider() trace.TracerProvider { return s.tracer.provider } 812 813 func isRecording(s SamplingResult) bool { 814 return s.Decision == RecordOnly || s.Decision == RecordAndSample 815 } 816 817 func isSampled(s SamplingResult) bool { 818 return s.Decision == RecordAndSample 819 } 820 821 // Status is the classified state of a Span. 822 type Status struct { 823 // Code is an identifier of a Spans state classification. 824 Code codes.Code 825 // Description is a user hint about why that status was set. It is only 826 // applicable when Code is Error. 827 Description string 828 }