opentelemetry-sdk 0.5.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -2
  3. data/CHANGELOG.md +54 -0
  4. data/README.md +1 -1
  5. data/lib/opentelemetry/sdk.rb +2 -1
  6. data/lib/opentelemetry/sdk/baggage.rb +16 -0
  7. data/lib/opentelemetry/sdk/{correlation_context → baggage}/builder.rb +5 -5
  8. data/lib/opentelemetry/sdk/{correlation_context → baggage}/manager.rb +37 -27
  9. data/lib/opentelemetry/sdk/configurator.rb +41 -20
  10. data/lib/opentelemetry/sdk/resources/constants.rb +0 -4
  11. data/lib/opentelemetry/sdk/resources/resource.rb +33 -22
  12. data/lib/opentelemetry/sdk/trace.rb +1 -0
  13. data/lib/opentelemetry/sdk/trace/config/trace_config.rb +3 -3
  14. data/lib/opentelemetry/sdk/trace/event.rb +48 -0
  15. data/lib/opentelemetry/sdk/trace/export.rb +9 -4
  16. data/lib/opentelemetry/sdk/trace/export/batch_span_processor.rb +84 -36
  17. data/lib/opentelemetry/sdk/trace/export/console_span_exporter.rb +5 -8
  18. data/lib/opentelemetry/sdk/trace/export/in_memory_span_exporter.rb +8 -2
  19. data/lib/opentelemetry/sdk/trace/export/multi_span_exporter.rb +17 -16
  20. data/lib/opentelemetry/sdk/trace/export/noop_span_exporter.rb +6 -2
  21. data/lib/opentelemetry/sdk/trace/export/simple_span_processor.rb +22 -4
  22. data/lib/opentelemetry/sdk/trace/multi_span_processor.rb +30 -6
  23. data/lib/opentelemetry/sdk/trace/noop_span_processor.rb +17 -3
  24. data/lib/opentelemetry/sdk/trace/samplers.rb +51 -43
  25. data/lib/opentelemetry/sdk/trace/samplers/decision.rb +3 -3
  26. data/lib/opentelemetry/sdk/trace/samplers/parent_based.rb +54 -0
  27. data/lib/opentelemetry/sdk/trace/samplers/result.rb +3 -3
  28. data/lib/opentelemetry/sdk/trace/samplers/trace_id_ratio_based.rb +45 -0
  29. data/lib/opentelemetry/sdk/trace/span.rb +30 -36
  30. data/lib/opentelemetry/sdk/trace/span_data.rb +16 -3
  31. data/lib/opentelemetry/sdk/trace/tracer.rb +13 -11
  32. data/lib/opentelemetry/sdk/trace/tracer_provider.rb +4 -2
  33. data/lib/opentelemetry/sdk/version.rb +1 -1
  34. metadata +30 -11
  35. data/lib/opentelemetry/sdk/correlation_context.rb +0 -16
  36. data/lib/opentelemetry/sdk/trace/samplers/parent_or_else.rb +0 -43
  37. data/lib/opentelemetry/sdk/trace/samplers/probability_sampler.rb +0 -64
@@ -15,6 +15,7 @@ end
15
15
 
16
16
  require 'opentelemetry/sdk/trace/samplers'
17
17
  require 'opentelemetry/sdk/trace/config'
18
+ require 'opentelemetry/sdk/trace/event'
18
19
  require 'opentelemetry/sdk/trace/export'
19
20
  require 'opentelemetry/sdk/trace/multi_span_processor'
20
21
  require 'opentelemetry/sdk/trace/noop_span_processor'
@@ -10,7 +10,7 @@ module OpenTelemetry
10
10
  module Config
11
11
  # Class that holds global trace parameters.
12
12
  class TraceConfig
13
- DEFAULT_SAMPLER = Samplers::ALWAYS_ON
13
+ DEFAULT_SAMPLER = Samplers.parent_based(root: Samplers::ALWAYS_ON)
14
14
  DEFAULT_MAX_ATTRIBUTES_COUNT = 32
15
15
  DEFAULT_MAX_EVENTS_COUNT = 128
16
16
  DEFAULT_MAX_LINKS_COUNT = 32
@@ -30,13 +30,13 @@ module OpenTelemetry
30
30
  # The global default max number of attributes per {Span}.
31
31
  attr_reader :max_attributes_count
32
32
 
33
- # The global default max number of {OpenTelemetry::Trace::Event}s per {Span}.
33
+ # The global default max number of {OpenTelemetry::SDK::Trace::Event}s per {Span}.
34
34
  attr_reader :max_events_count
35
35
 
36
36
  # The global default max number of {OpenTelemetry::Trace::Link} entries per {Span}.
37
37
  attr_reader :max_links_count
38
38
 
39
- # The global default max number of attributes per {OpenTelemetry::Trace::Event}.
39
+ # The global default max number of attributes per {OpenTelemetry::SDK::Trace::Event}.
40
40
  attr_reader :max_attributes_per_event
41
41
 
42
42
  # The global default max number of attributes per {OpenTelemetry::Trace::Link}.
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ module SDK
9
+ module Trace
10
+ # A text annotation with a set of attributes and a timestamp.
11
+ class Event
12
+ EMPTY_ATTRIBUTES = {}.freeze
13
+
14
+ private_constant :EMPTY_ATTRIBUTES
15
+
16
+ # Returns the name of this event
17
+ #
18
+ # @return [String]
19
+ attr_reader :name
20
+
21
+ # Returns the frozen attributes for this event
22
+ #
23
+ # @return [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
24
+ attr_reader :attributes
25
+
26
+ # Returns the timestamp for this event
27
+ #
28
+ # @return [Time]
29
+ attr_reader :timestamp
30
+
31
+ # Returns a new immutable {Event}.
32
+ #
33
+ # @param [String] name The name of this event
34
+ # @param [optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
35
+ # attributes A hash of attributes for this event. Attributes will be
36
+ # frozen during Event initialization.
37
+ # @param [optional Time] timestamp The timestamp for this event.
38
+ # Defaults to Time.now.
39
+ # @return [Event]
40
+ def initialize(name:, attributes: nil, timestamp: nil)
41
+ @name = name
42
+ @attributes = attributes.freeze || EMPTY_ATTRIBUTES
43
+ @timestamp = timestamp || Time.now
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -7,16 +7,21 @@
7
7
  module OpenTelemetry
8
8
  module SDK
9
9
  module Trace
10
- # The Export module contains the built-in exporters for the OpenTelemetry
10
+ # The Export module contains the built-in exporters and span processors for the OpenTelemetry
11
11
  # reference implementation.
12
12
  module Export
13
- # Result codes for the SpanExporter#export method.
13
+ # Result codes for the SpanExporter#export method and the SpanProcessor#force_flush and SpanProcessor#shutdown methods.
14
14
 
15
- # The export operation finished successfully.
15
+ # The operation finished successfully.
16
16
  SUCCESS = 0
17
17
 
18
- # The export operation finished with an error.
18
+ # The operation finished with an error.
19
19
  FAILURE = 1
20
+
21
+ # Additional result code for the SpanProcessor#force_flush and SpanProcessor#shutdown methods.
22
+
23
+ # The operation timed out.
24
+ TIMEOUT = 2
20
25
  end
21
26
  end
22
27
  end
@@ -13,6 +13,9 @@ module OpenTelemetry
13
13
  # Implementation of the duck type SpanProcessor that batches spans
14
14
  # exported by the SDK then pushes them to the exporter pipeline.
15
15
  #
16
+ # Typically, the BatchSpanProcessor will be more suitable for
17
+ # production environments than the SimpleSpanProcessor.
18
+ #
16
19
  # All spans reported by the SDK implementation are first added to a
17
20
  # synchronized queue (with a {max_queue_size} maximum size, after the
18
21
  # size is reached spans are dropped) and exported every
@@ -22,50 +25,63 @@ module OpenTelemetry
22
25
  # If the queue gets half full a preemptive notification is sent to the
23
26
  # worker thread that exports the spans to wake up and start a new
24
27
  # export cycle.
25
- class BatchSpanProcessor
26
- EXPORTER_TIMEOUT_MILLIS = 30_000
27
- SCHEDULE_DELAY_MILLIS = 5_000
28
- MAX_QUEUE_SIZE = 2048
29
- MAX_EXPORT_BATCH_SIZE = 512
30
- private_constant(:SCHEDULE_DELAY_MILLIS, :MAX_QUEUE_SIZE, :MAX_EXPORT_BATCH_SIZE)
31
-
28
+ class BatchSpanProcessor # rubocop:disable Metrics/ClassLength
29
+ # Returns a new instance of the {BatchSpanProcessor}.
30
+ #
31
+ # @param [SpanExporter] exporter
32
+ # @param [Numeric] exporter_timeout_millis the delay interval between two
33
+ # consecutive exports. Defaults to the value of the OTEL_BSP_EXPORT_TIMEOUT_MILLIS
34
+ # environment variable, if set, or 30,000 (30 seconds).
35
+ # @param [Numeric] schedule_delay_millis the maximum allowed time to export data.
36
+ # Defaults to the value of the OTEL_BSP_SCHEDULE_DELAY_MILLIS environment
37
+ # variable, if set, or 5,000 (5 seconds).
38
+ # @param [Integer] max_queue_size the maximum queue size in spans.
39
+ # Defaults to the value of the OTEL_BSP_MAX_QUEUE_SIZE environment
40
+ # variable, if set, or 2048.
41
+ # @param [Integer] max_export_batch_size the maximum batch size in spans.
42
+ # Defaults to the value of the OTEL_BSP_MAX_EXPORT_BATCH_SIZE environment
43
+ # variable, if set, or 512.
44
+ #
45
+ # @return a new instance of the {BatchSpanProcessor}.
32
46
  def initialize(exporter:,
33
- exporter_timeout_millis: EXPORTER_TIMEOUT_MILLIS,
34
- schedule_delay_millis: SCHEDULE_DELAY_MILLIS,
35
- max_queue_size: MAX_QUEUE_SIZE,
36
- max_export_batch_size: MAX_EXPORT_BATCH_SIZE)
47
+ exporter_timeout_millis: Float(ENV.fetch('OTEL_BSP_EXPORT_TIMEOUT_MILLIS', 30_000)),
48
+ schedule_delay_millis: Float(ENV.fetch('OTEL_BSP_SCHEDULE_DELAY_MILLIS', 5_000)),
49
+ max_queue_size: Integer(ENV.fetch('OTEL_BSP_MAX_QUEUE_SIZE', 2048)),
50
+ max_export_batch_size: Integer(ENV.fetch('OTEL_BSP_MAX_EXPORT_BATCH_SIZE', 512)),
51
+ start_thread_on_boot: String(ENV['OTEL_RUBY_BSP_START_THREAD_ON_BOOT']) !~ /false/i)
37
52
  raise ArgumentError if max_export_batch_size > max_queue_size
38
53
 
39
54
  @exporter = exporter
40
55
  @exporter_timeout_seconds = exporter_timeout_millis / 1000.0
41
56
  @mutex = Mutex.new
57
+ @export_mutex = Mutex.new
42
58
  @condition = ConditionVariable.new
43
59
  @keep_running = true
44
60
  @delay_seconds = schedule_delay_millis / 1000.0
45
61
  @max_queue_size = max_queue_size
46
62
  @batch_size = max_export_batch_size
47
63
  @spans = []
48
- @thread = Thread.new { work }
64
+ @pid = nil
65
+ @thread = nil
66
+ reset_on_fork(restart_thread: start_thread_on_boot)
49
67
  end
50
68
 
51
- # does nothing for this processor
52
- def on_start(span)
53
- # noop
54
- end
69
+ # Does nothing for this processor
70
+ def on_start(_span, _parent_context); end
55
71
 
56
- # adds a span to the batcher, threadsafe may block on lock
72
+ # Adds a span to the batch. Thread-safe; may block on lock.
57
73
  def on_finish(span) # rubocop:disable Metrics/AbcSize
58
74
  return unless span.context.trace_flags.sampled?
59
75
 
60
76
  lock do
77
+ reset_on_fork
61
78
  n = spans.size + 1 - max_queue_size
62
79
  spans.shift(n) if n.positive?
63
80
  spans << span
64
- @condition.signal if spans.size > max_queue_size / 2
81
+ @condition.signal if spans.size > batch_size
65
82
  end
66
83
  end
67
84
 
68
- # TODO: test this explicitly.
69
85
  # Export all ended spans to the configured `Exporter` that have not yet
70
86
  # been exported.
71
87
  #
@@ -73,26 +89,53 @@ module OpenTelemetry
73
89
  # necessary, such as when using some FaaS providers that may suspend
74
90
  # the process after an invocation, but before the `Processor` exports
75
91
  # the completed spans.
76
- def force_flush
77
- snapshot = lock { spans.shift(spans.size) }
92
+ #
93
+ # @param [optional Numeric] timeout An optional timeout in seconds.
94
+ # @return [Integer] SUCCESS if no error occurred, FAILURE if a
95
+ # non-specific failure occurred, TIMEOUT if a timeout occurred.
96
+ def force_flush(timeout: nil) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
97
+ start_time = Time.now
98
+ snapshot = lock do
99
+ reset_on_fork(restart_thread: false) if @keep_running
100
+ spans.shift(spans.size)
101
+ end
78
102
  until snapshot.empty?
103
+ remaining_timeout = OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time)
104
+ return TIMEOUT if remaining_timeout&.zero?
105
+
79
106
  batch = snapshot.shift(@batch_size).map!(&:to_span_data)
80
- result_code = @exporter.export(batch)
81
- report_result(result_code, batch)
107
+ result_code = export_batch(batch, timeout: remaining_timeout)
108
+ return result_code unless result_code == SUCCESS
109
+ end
110
+
111
+ SUCCESS
112
+ ensure
113
+ # Unshift the remaining spans if we timed out. We drop excess spans from
114
+ # the snapshot because they're older than any spans in the spans buffer.
115
+ lock do
116
+ n = spans.size + snapshot.size - max_queue_size
117
+ snapshot.shift(n) if n.positive?
118
+ spans.unshift(snapshot) unless snapshot.empty?
119
+ @condition.signal if spans.size > max_queue_size / 2
82
120
  end
83
121
  end
84
122
 
85
- # shuts the consumer thread down and flushes the current accumulated buffer
86
- # will block until the thread is finished
87
- def shutdown
123
+ # Shuts the consumer thread down and flushes the current accumulated buffer
124
+ # will block until the thread is finished.
125
+ #
126
+ # @param [optional Numeric] timeout An optional timeout in seconds.
127
+ # @return [Integer] SUCCESS if no error occurred, FAILURE if a
128
+ # non-specific failure occurred, TIMEOUT if a timeout occurred.
129
+ def shutdown(timeout: nil)
130
+ start_time = Time.now
88
131
  lock do
89
132
  @keep_running = false
90
133
  @condition.signal
91
134
  end
92
135
 
93
- @thread.join
94
- force_flush
95
- @exporter.shutdown
136
+ @thread.join(timeout)
137
+ force_flush(timeout: OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time))
138
+ @exporter.shutdown(timeout: OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time))
96
139
  end
97
140
 
98
141
  private
@@ -102,6 +145,7 @@ module OpenTelemetry
102
145
  def work
103
146
  loop do
104
147
  batch = lock do
148
+ reset_on_fork(restart_thread: false)
105
149
  @condition.wait(@mutex, @delay_seconds) if spans.size < batch_size && @keep_running
106
150
  @condition.wait(@mutex, @delay_seconds) while spans.empty? && @keep_running
107
151
  return unless @keep_running
@@ -113,15 +157,19 @@ module OpenTelemetry
113
157
  end
114
158
  end
115
159
 
116
- def export_batch(batch)
117
- result_code = export_with_timeout(batch)
118
- report_result(result_code, batch)
160
+ def reset_on_fork(restart_thread: true)
161
+ pid = Process.pid
162
+ return if @pid == pid
163
+
164
+ @pid = pid
165
+ spans.clear
166
+ @thread = Thread.new { work } if restart_thread
119
167
  end
120
168
 
121
- def export_with_timeout(batch)
122
- Timeout.timeout(@exporter_timeout_seconds) { @exporter.export(batch) }
123
- rescue Timeout::Error
124
- FAILURE
169
+ def export_batch(batch, timeout: @exporter_timeout_seconds)
170
+ result_code = @export_mutex.synchronize { @exporter.export(batch, timeout: timeout) }
171
+ report_result(result_code, batch)
172
+ result_code
125
173
  end
126
174
 
127
175
  def report_result(result_code, batch)
@@ -14,24 +14,21 @@ module OpenTelemetry
14
14
  #
15
15
  # Potentially useful for exploratory purposes.
16
16
  class ConsoleSpanExporter
17
- ResultCodes = OpenTelemetry::SDK::Trace::Export
18
-
19
- private_constant(:ResultCodes)
20
-
21
17
  def initialize
22
18
  @stopped = false
23
19
  end
24
20
 
25
- def export(spans)
26
- return ResultCodes::FAILURE if @stopped
21
+ def export(spans, timeout: nil)
22
+ return FAILURE if @stopped
27
23
 
28
24
  Array(spans).each { |s| pp s }
29
25
 
30
- ResultCodes::SUCCESS
26
+ SUCCESS
31
27
  end
32
28
 
33
- def shutdown
29
+ def shutdown(timeout: nil)
34
30
  @stopped = true
31
+ SUCCESS
35
32
  end
36
33
  end
37
34
  end
@@ -60,9 +60,10 @@ module OpenTelemetry
60
60
  #
61
61
  # @param [Enumerable<SpanData>] span_datas the list of sampled {SpanData}s to be
62
62
  # exported.
63
+ # @param [optional Numeric] timeout An optional timeout in seconds.
63
64
  # @return [Integer] the result of the export, SUCCESS or
64
65
  # FAILURE
65
- def export(span_datas)
66
+ def export(span_datas, timeout: nil)
66
67
  @mutex.synchronize do
67
68
  return FAILURE if @stopped
68
69
 
@@ -73,11 +74,16 @@ module OpenTelemetry
73
74
 
74
75
  # Called when {TracerProvider#shutdown} is called, if this exporter is
75
76
  # registered to a {TracerProvider} object.
76
- def shutdown
77
+ #
78
+ # @param [optional Numeric] timeout An optional timeout in seconds.
79
+ # @return [Integer] SUCCESS if no error occurred, FAILURE if a
80
+ # non-specific failure occurred, TIMEOUT if a timeout occurred.
81
+ def shutdown(timeout: nil)
77
82
  @mutex.synchronize do
78
83
  @finished_spans.clear
79
84
  @stopped = true
80
85
  end
86
+ SUCCESS
81
87
  end
82
88
  end
83
89
  end
@@ -23,33 +23,34 @@ module OpenTelemetry
23
23
  #
24
24
  # @param [Enumerable<Span>] spans the list of sampled {Span}s to be
25
25
  # exported.
26
+ # @param [optional Numeric] timeout An optional timeout in seconds.
26
27
  # @return [Integer] the result of the export.
27
- def export(spans)
28
- @span_exporters.inject(SUCCESS) do |result_code, span_exporter|
29
- merge_result_code(result_code, span_exporter.export(spans))
28
+ def export(spans, timeout: nil)
29
+ start_time = Time.now
30
+ results = @span_exporters.map do |span_exporter|
31
+ span_exporter.export(spans, timeout: OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time))
30
32
  rescue => e # rubocop:disable Style/RescueStandardError
31
33
  OpenTelemetry.logger.warn("exception raised by export - #{e}")
32
34
  FAILURE
33
35
  end
36
+ results.uniq.max || SUCCESS
34
37
  end
35
38
 
36
39
  # Called when {TracerProvider#shutdown} is called, if this exporter is
37
40
  # registered to a {TracerProvider} object.
38
- def shutdown
39
- @span_exporters.each(&:shutdown)
40
- end
41
-
42
- private
41
+ #
42
+ # @param [optional Numeric] timeout An optional timeout in seconds.
43
+ # @return [Integer] SUCCESS if no error occurred, FAILURE if a
44
+ # non-specific failure occurred, TIMEOUT if a timeout occurred.
45
+ def shutdown(timeout: nil)
46
+ start_time = Time.now
47
+ results = @span_exporters.map do |processor|
48
+ remaining_timeout = OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time)
49
+ return TIMEOUT if remaining_timeout&.zero?
43
50
 
44
- # Returns a merged error code, see the rules in the code.
45
- def merge_result_code(result_code, new_result_code)
46
- if result_code == SUCCESS && new_result_code == SUCCESS
47
- # If both errors are success then return success.
48
- SUCCESS
49
- else
50
- # At this point at least one of the code is FAILURE, so return FAILURE.
51
- FAILURE
51
+ processor.shutdown(timeout: remaining_timeout)
52
52
  end
53
+ results.uniq.max || SUCCESS
53
54
  end
54
55
  end
55
56
  end
@@ -23,8 +23,9 @@ module OpenTelemetry
23
23
  #
24
24
  # @param [Enumerable<Span>] spans the list of sampled {Span}s to be
25
25
  # exported.
26
+ # @param [optional Numeric] timeout An optional timeout in seconds.
26
27
  # @return [Integer] the result of the export.
27
- def export(spans)
28
+ def export(spans, timeout: nil)
28
29
  return SUCCESS unless @stopped
29
30
 
30
31
  FAILURE
@@ -32,8 +33,11 @@ module OpenTelemetry
32
33
 
33
34
  # Called when {TracerProvider#shutdown} is called, if this exporter is
34
35
  # registered to a {TracerProvider} object.
35
- def shutdown
36
+ #
37
+ # @param [optional Numeric] timeout An optional timeout in seconds.
38
+ def shutdown(timeout: nil)
36
39
  @stopped = true
40
+ SUCCESS
37
41
  end
38
42
  end
39
43
  end
@@ -12,6 +12,12 @@ module OpenTelemetry
12
12
  # {Span} to {io.opentelemetry.proto.trace.v1.Span} and passes it to the
13
13
  # configured exporter.
14
14
  #
15
+ # Typically, the SimpleSpanProcessor will be most suitable for use in testing;
16
+ # it should be used with caution in production. It may be appropriate for
17
+ # production use in scenarios where creating multiple threads is not desirable
18
+ # as well as scenarios where different custom attributes should be added to
19
+ # individual spans based on code scopes.
20
+ #
15
21
  # Only spans that are recorded are converted, {OpenTelemetry::Trace::Span#is_recording?} must
16
22
  # return true.
17
23
  class SimpleSpanProcessor
@@ -33,7 +39,9 @@ module OpenTelemetry
33
39
  # not throw or block the execution thread.
34
40
  #
35
41
  # @param [Span] span the {Span} that just started.
36
- def on_start(span)
42
+ # @param [Context] parent_context the parent {Context} of the newly
43
+ # started span.
44
+ def on_start(span, parent_context)
37
45
  # Do nothing.
38
46
  end
39
47
 
@@ -59,11 +67,21 @@ module OpenTelemetry
59
67
  # necessary, such as when using some FaaS providers that may suspend
60
68
  # the process after an invocation, but before the `Processor` exports
61
69
  # the completed spans.
62
- def force_flush; end
70
+ #
71
+ # @param [optional Numeric] timeout An optional timeout in seconds.
72
+ # @return [Integer] SUCCESS if no error occurred, FAILURE if a
73
+ # non-specific failure occurred, TIMEOUT if a timeout occurred.
74
+ def force_flush(timeout: nil)
75
+ SUCCESS
76
+ end
63
77
 
64
78
  # Called when {TracerProvider#shutdown} is called.
65
- def shutdown
66
- @span_exporter&.shutdown
79
+ #
80
+ # @param [optional Numeric] timeout An optional timeout in seconds.
81
+ # @return [Integer] SUCCESS if no error occurred, FAILURE if a
82
+ # non-specific failure occurred, TIMEOUT if a timeout occurred.
83
+ def shutdown(timeout: nil)
84
+ @span_exporter&.shutdown(timeout: timeout) || SUCCESS
67
85
  end
68
86
  end
69
87
  end