...

Source file src/go.opentelemetry.io/otel/sdk/trace/span.go

Documentation: go.opentelemetry.io/otel/sdk/trace

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

View as plain text