trace.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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. package global
  15. /*
  16. This file contains the forwarding implementation of the TracerProvider used as
  17. the default global instance. Prior to initialization of an SDK, Tracers
  18. returned by the global TracerProvider will provide no-op functionality. This
  19. means that all Span created prior to initialization are no-op Spans.
  20. Once an SDK has been initialized, all provided no-op Tracers are swapped for
  21. Tracers provided by the SDK defined TracerProvider. However, any Span started
  22. prior to this initialization does not change its behavior. Meaning, the Span
  23. remains a no-op Span.
  24. The implementation to track and swap Tracers locks all new Tracer creation
  25. until the swap is complete. This assumes that this operation is not
  26. performance-critical. If that assumption is incorrect, be sure to configure an
  27. SDK prior to any Tracer creation.
  28. */
  29. import (
  30. "context"
  31. "sync"
  32. "sync/atomic"
  33. "go.opentelemetry.io/otel/attribute"
  34. "go.opentelemetry.io/otel/codes"
  35. "go.opentelemetry.io/otel/trace"
  36. )
  37. // tracerProvider is a placeholder for a configured SDK TracerProvider.
  38. //
  39. // All TracerProvider functionality is forwarded to a delegate once
  40. // configured.
  41. type tracerProvider struct {
  42. mtx sync.Mutex
  43. tracers map[il]*tracer
  44. delegate trace.TracerProvider
  45. }
  46. // Compile-time guarantee that tracerProvider implements the TracerProvider
  47. // interface.
  48. var _ trace.TracerProvider = &tracerProvider{}
  49. // setDelegate configures p to delegate all TracerProvider functionality to
  50. // provider.
  51. //
  52. // All Tracers provided prior to this function call are switched out to be
  53. // Tracers provided by provider.
  54. //
  55. // It is guaranteed by the caller that this happens only once.
  56. func (p *tracerProvider) setDelegate(provider trace.TracerProvider) {
  57. p.mtx.Lock()
  58. defer p.mtx.Unlock()
  59. p.delegate = provider
  60. if len(p.tracers) == 0 {
  61. return
  62. }
  63. for _, t := range p.tracers {
  64. t.setDelegate(provider)
  65. }
  66. p.tracers = nil
  67. }
  68. // Tracer implements TracerProvider.
  69. func (p *tracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer {
  70. p.mtx.Lock()
  71. defer p.mtx.Unlock()
  72. if p.delegate != nil {
  73. return p.delegate.Tracer(name, opts...)
  74. }
  75. // At this moment it is guaranteed that no sdk is installed, save the tracer in the tracers map.
  76. key := il{
  77. name: name,
  78. version: trace.NewTracerConfig(opts...).InstrumentationVersion(),
  79. }
  80. if p.tracers == nil {
  81. p.tracers = make(map[il]*tracer)
  82. }
  83. if val, ok := p.tracers[key]; ok {
  84. return val
  85. }
  86. t := &tracer{name: name, opts: opts, provider: p}
  87. p.tracers[key] = t
  88. return t
  89. }
  90. type il struct {
  91. name string
  92. version string
  93. }
  94. // tracer is a placeholder for a trace.Tracer.
  95. //
  96. // All Tracer functionality is forwarded to a delegate once configured.
  97. // Otherwise, all functionality is forwarded to a NoopTracer.
  98. type tracer struct {
  99. name string
  100. opts []trace.TracerOption
  101. provider *tracerProvider
  102. delegate atomic.Value
  103. }
  104. // Compile-time guarantee that tracer implements the trace.Tracer interface.
  105. var _ trace.Tracer = &tracer{}
  106. // setDelegate configures t to delegate all Tracer functionality to Tracers
  107. // created by provider.
  108. //
  109. // All subsequent calls to the Tracer methods will be passed to the delegate.
  110. //
  111. // It is guaranteed by the caller that this happens only once.
  112. func (t *tracer) setDelegate(provider trace.TracerProvider) {
  113. t.delegate.Store(provider.Tracer(t.name, t.opts...))
  114. }
  115. // Start implements trace.Tracer by forwarding the call to t.delegate if
  116. // set, otherwise it forwards the call to a NoopTracer.
  117. func (t *tracer) Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
  118. delegate := t.delegate.Load()
  119. if delegate != nil {
  120. return delegate.(trace.Tracer).Start(ctx, name, opts...)
  121. }
  122. s := nonRecordingSpan{sc: trace.SpanContextFromContext(ctx), tracer: t}
  123. ctx = trace.ContextWithSpan(ctx, s)
  124. return ctx, s
  125. }
  126. // nonRecordingSpan is a minimal implementation of a Span that wraps a
  127. // SpanContext. It performs no operations other than to return the wrapped
  128. // SpanContext.
  129. type nonRecordingSpan struct {
  130. sc trace.SpanContext
  131. tracer *tracer
  132. }
  133. var _ trace.Span = nonRecordingSpan{}
  134. // SpanContext returns the wrapped SpanContext.
  135. func (s nonRecordingSpan) SpanContext() trace.SpanContext { return s.sc }
  136. // IsRecording always returns false.
  137. func (nonRecordingSpan) IsRecording() bool { return false }
  138. // SetStatus does nothing.
  139. func (nonRecordingSpan) SetStatus(codes.Code, string) {}
  140. // SetError does nothing.
  141. func (nonRecordingSpan) SetError(bool) {}
  142. // SetAttributes does nothing.
  143. func (nonRecordingSpan) SetAttributes(...attribute.KeyValue) {}
  144. // End does nothing.
  145. func (nonRecordingSpan) End(...trace.SpanEndOption) {}
  146. // RecordError does nothing.
  147. func (nonRecordingSpan) RecordError(error, ...trace.EventOption) {}
  148. // AddEvent does nothing.
  149. func (nonRecordingSpan) AddEvent(string, ...trace.EventOption) {}
  150. // SetName does nothing.
  151. func (nonRecordingSpan) SetName(string) {}
  152. func (s nonRecordingSpan) TracerProvider() trace.TracerProvider { return s.tracer.provider }