opentelemetry-sdk 1.0.0.rc1 → 1.0.0.rc2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5e0b06b7a072f462eeef975e4342a9e9800fb85794e2625f454d17eb20ef2be
4
- data.tar.gz: a42a11084a981f147bdc5a3c5d21f1a4a1752d5a971819658573cb4964d43f49
3
+ metadata.gz: d43559eaa2be64a3597d078d032c168429702e47bdeaee1ac454dc5e74f9f496
4
+ data.tar.gz: 583f42bb1b6543d6375d3cfc8e4bd2319d5146306f42a73d726ca73f3c01e56d
5
5
  SHA512:
6
- metadata.gz: 670059ca8ef7d7aeba579c6b70a8217ac5e4fa879b39afee715b4ff1852e8643bf87581943b70d949480a728c531d20efc8ed42fa878f0a5291d55f31cc22607
7
- data.tar.gz: 604feaa8d9952cce4a0eff45b743601b85ea2a5f7b03af316c5ae45c6df2fd57a2712d43d417a30a2df44b493fd6c8bc03f8924014a75d2fd29b9bfe513c7adf
6
+ metadata.gz: 14112a30284f0ececabcf75dda91f6634b3748c44ccec52e19c6d42e7fae59979e6ea82ef276d21ea5503d2b4f35821945b62d2b1afc83c5bcb9d4a6a9ce6bf4
7
+ data.tar.gz: 87aaa08db88b9495c86ee1135cdcbfb95827fbbed42edf3280500d86025ff269ee3af95c675e20231267e7b561082cea12df7738db004922468246ad437805fb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Release History: opentelemetry-sdk
2
2
 
3
+ ### v1.0.0.rc2 / 2021-06-23
4
+
5
+ * BREAKING CHANGE: Remove optional parent_context from in_span [729](https://github.com/open-telemetry/opentelemetry-ruby/pull/729)
6
+ * BREAKING CHANGE: Replace Time.now with Process.clock_gettime [717](https://github.com/open-telemetry/opentelemetry-ruby/pull/717)
7
+ * BREAKING CHANGE: Refactor Baggage to remove Noop* [800](https://github.com/open-telemetry/opentelemetry-ruby/pull/800)
8
+ * BREAKING CHANGE: Remove unnecessary readers from SDK Tracer [820](https://github.com/open-telemetry/opentelemetry-ruby/pull/820)
9
+ - Tracer no longer surfaces attribute readers for the name, version, or tracer_provider
10
+ * BREAKING CHANGE: Total order constraint on span.status= [805](https://github.com/open-telemetry/opentelemetry-ruby/pull/805)
11
+
12
+ * ADDED: Add Tracer.non_recording_span to API [799](https://github.com/open-telemetry/opentelemetry-ruby/pull/799)
13
+ * ADDED: Add unnamed tracer warning message [830](https://github.com/open-telemetry/opentelemetry-ruby/pull/830)
14
+ * ADDED: Allow disabling of install messages [831](https://github.com/open-telemetry/opentelemetry-ruby/pull/831)
15
+ * FIXED: Rename cloud.zone to cloud.availability_zone [734](https://github.com/open-telemetry/opentelemetry-ruby/pull/734)
16
+ * FIXED: Improve attribute error messages [742](https://github.com/open-telemetry/opentelemetry-ruby/pull/742)
17
+ * FIXED: Support OTEL_SERVICE_NAME env var [806]https://github.com/open-telemetry/opentelemetry-ruby/pull/806
18
+ * FIXED: Flakey tracer provider test
19
+
3
20
  ### v1.0.0.rc1 / 2021-05-21
4
21
 
5
22
  * BREAKING CHANGE: Remove optional parent_context from in_span
@@ -55,7 +55,7 @@ module OpenTelemetry
55
55
  # Configure everything
56
56
  #
57
57
  # OpenTelemetry::SDK.configure do |c|
58
- # c.logger = Logger.new('/dev/null')
58
+ # c.logger = Logger.new(File::NULL)
59
59
  # c.add_span_processor SpanProcessor.new(SomeExporter.new)
60
60
  # c.use_all
61
61
  # end
@@ -74,6 +74,7 @@ module OpenTelemetry
74
74
  end
75
75
 
76
76
  require 'opentelemetry/sdk/configurator'
77
+ require 'opentelemetry/sdk/forwarding_logger'
77
78
  require 'opentelemetry/sdk/internal'
78
79
  require 'opentelemetry/sdk/instrumentation_library'
79
80
  require 'opentelemetry/sdk/resources'
@@ -15,7 +15,7 @@ module OpenTelemetry
15
15
 
16
16
  private_constant :USE_MODE_UNSPECIFIED, :USE_MODE_ONE, :USE_MODE_ALL
17
17
 
18
- attr_writer :logger, :propagators, :error_handler, :id_generator
18
+ attr_writer :propagators, :error_handler, :id_generator
19
19
 
20
20
  def initialize
21
21
  @instrumentation_names = []
@@ -31,6 +31,15 @@ module OpenTelemetry
31
31
  @logger ||= OpenTelemetry.logger
32
32
  end
33
33
 
34
+ # Accepts a logger and wraps it in the {ForwardingLogger} which allows
35
+ # for controlling the severity level emitted by the OpenTelemetry.logger
36
+ # independently of the supplied logger.
37
+ #
38
+ # @param [Logger] new_logger The logger for OpenTelemetry to use
39
+ def logger=(new_logger)
40
+ @logger = ForwardingLogger.new(new_logger, level: ENV['OTEL_LOG_LEVEL'] || Logger::INFO)
41
+ end
42
+
34
43
  def error_handler
35
44
  @error_handler ||= OpenTelemetry.error_handler
36
45
  end
@@ -112,7 +121,6 @@ module OpenTelemetry
112
121
  def configure
113
122
  OpenTelemetry.logger = logger
114
123
  OpenTelemetry.error_handler = error_handler
115
- OpenTelemetry.baggage = Baggage::Manager.new
116
124
  configure_propagation
117
125
  configure_span_processors
118
126
  tracer_provider.id_generator = @id_generator
@@ -123,7 +131,7 @@ module OpenTelemetry
123
131
  private
124
132
 
125
133
  def tracer_provider
126
- @tracer_provider ||= Trace::TracerProvider.new(@resource)
134
+ @tracer_provider ||= Trace::TracerProvider.new(resource: @resource)
127
135
  end
128
136
 
129
137
  def check_use_mode!(mode)
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module OpenTelemetry
6
+ module SDK
7
+ # The ForwardingLogger provides a wrapper to control the OpenTelemetry
8
+ # log level, while respecting the configured level of the supplied logger.
9
+ # If the OTEL_LOG_LEVEL is set to debug, and the supplied logger is configured
10
+ # with an ERROR log level, only OpenTelemetry logs at the ERROR level or higher
11
+ # will be emitted.
12
+ class ForwardingLogger
13
+ def initialize(logger, level:) # rubocop:disable Metrics/CyclomaticComplexity
14
+ @logger = logger
15
+
16
+ if level.is_a?(Integer)
17
+ @level = level
18
+ else
19
+ case level.to_s.downcase
20
+ when 'debug'
21
+ @level = Logger::DEBUG
22
+ when 'info'
23
+ @level = Logger::INFO
24
+ when 'warn'
25
+ @level = Logger::WARN
26
+ when 'error'
27
+ @level = Logger::ERROR
28
+ when 'fatal'
29
+ @level = Logger::FATAL
30
+ when 'unknown'
31
+ @level = Logger::UNKNOWN
32
+ else
33
+ raise ArgumentError, "invalid log level: #{level}"
34
+ end
35
+ end
36
+ end
37
+
38
+ def add(severity, message = nil, progname = nil)
39
+ return true if severity < @level
40
+
41
+ @logger.add(severity, message, progname)
42
+ end
43
+
44
+ def debug(progname = nil, &block)
45
+ add(Logger::DEBUG, nil, progname, &block)
46
+ end
47
+
48
+ def info(progname = nil, &block)
49
+ add(Logger::INFO, nil, progname, &block)
50
+ end
51
+
52
+ def warn(progname = nil, &block)
53
+ add(Logger::WARN, nil, progname, &block)
54
+ end
55
+
56
+ def error(progname = nil, &block)
57
+ add(Logger::ERROR, nil, progname, &block)
58
+ end
59
+
60
+ def fatal(progname = nil, &block)
61
+ add(Logger::FATAL, nil, progname, &block)
62
+ end
63
+
64
+ def unknown(progname = nil, &block)
65
+ add(Logger::UNKNOWN, nil, progname, &block)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -31,7 +31,7 @@ module OpenTelemetry
31
31
  end
32
32
 
33
33
  def default
34
- @default ||= create(Constants::SERVICE_RESOURCE[:name] => 'unknown_service').merge(process).merge(telemetry_sdk)
34
+ @default ||= create(Constants::SERVICE_RESOURCE[:name] => 'unknown_service').merge(process).merge(telemetry_sdk).merge(service_name_from_env)
35
35
  end
36
36
 
37
37
  def telemetry_sdk
@@ -64,6 +64,13 @@ module OpenTelemetry
64
64
 
65
65
  create(resource_attributes)
66
66
  end
67
+
68
+ private
69
+
70
+ def service_name_from_env
71
+ service_name = ENV['OTEL_SERVICE_NAME']
72
+ create(Constants::SERVICE_RESOURCE[:name] => service_name) unless service_name.nil?
73
+ end
67
74
  end
68
75
 
69
76
  # @api private
@@ -14,12 +14,11 @@ module OpenTelemetry
14
14
  end
15
15
 
16
16
  require 'opentelemetry/sdk/trace/samplers'
17
- require 'opentelemetry/sdk/trace/config'
17
+ require 'opentelemetry/sdk/trace/span_limits'
18
18
  require 'opentelemetry/sdk/trace/event'
19
19
  require 'opentelemetry/sdk/trace/export'
20
- require 'opentelemetry/sdk/trace/multi_span_processor'
21
- require 'opentelemetry/sdk/trace/noop_span_processor'
22
20
  require 'opentelemetry/sdk/trace/span_data'
21
+ require 'opentelemetry/sdk/trace/span_processor'
23
22
  require 'opentelemetry/sdk/trace/span'
24
23
  require 'opentelemetry/sdk/trace/tracer'
25
24
  require 'opentelemetry/sdk/trace/tracer_provider'
@@ -31,6 +31,5 @@ require 'opentelemetry/sdk/trace/export/batch_span_processor'
31
31
  require 'opentelemetry/sdk/trace/export/console_span_exporter'
32
32
  require 'opentelemetry/sdk/trace/export/in_memory_span_exporter'
33
33
  require 'opentelemetry/sdk/trace/export/metrics_reporter'
34
- require 'opentelemetry/sdk/trace/export/multi_span_exporter'
35
- require 'opentelemetry/sdk/trace/export/noop_span_exporter'
34
+ require 'opentelemetry/sdk/trace/export/span_exporter'
36
35
  require 'opentelemetry/sdk/trace/export/simple_span_processor'
@@ -8,24 +8,25 @@ module OpenTelemetry
8
8
  module SDK
9
9
  module Trace
10
10
  module Export
11
- # A noop exporter that demonstrates and documents the SpanExporter
12
- # duck type. SpanExporter allows different tracing services to export
11
+ # SpanExporter describes a duck type. It is not required to subclass this
12
+ # class to provide an implementation of SpanExporter, provided the interface is
13
+ # satisfied. SpanExporter allows different tracing services to export
13
14
  # recorded data for sampled spans in their own format.
14
15
  #
15
16
  # To export data an exporter MUST be registered to the {TracerProvider} using
16
- # a {SimpleSpanProcessor} or a {BatchSpanProcessor}.
17
- class NoopSpanExporter
17
+ # a {SpanProcessor} implementation.
18
+ class SpanExporter
18
19
  def initialize
19
20
  @stopped = false
20
21
  end
21
22
 
22
- # Called to export sampled {Span}s.
23
+ # Called to export sampled {SpanData}s.
23
24
  #
24
- # @param [Enumerable<Span>] spans the list of sampled {Span}s to be
25
+ # @param [Enumerable<SpanData>] span_data the list of sampled {SpanData} to be
25
26
  # exported.
26
27
  # @param [optional Numeric] timeout An optional timeout in seconds.
27
28
  # @return [Integer] the result of the export.
28
- def export(spans, timeout: nil)
29
+ def export(span_data, timeout: nil)
29
30
  return SUCCESS unless @stopped
30
31
 
31
32
  FAILURE
@@ -10,13 +10,13 @@ module OpenTelemetry
10
10
  # Implementation of {OpenTelemetry::Trace::Span} that records trace events.
11
11
  #
12
12
  # This implementation includes reader methods intended to allow access to
13
- # internal state by SpanProcessors (see {NoopSpanProcessor} for the interface).
13
+ # internal state by {SpanProcessor}s.
14
14
  # Instrumentation should use the API provided by {OpenTelemetry::Trace::Span}
15
15
  # and should consider {Span} to be write-only.
16
16
  #
17
17
  # rubocop:disable Metrics/ClassLength
18
18
  class Span < OpenTelemetry::Trace::Span
19
- DEFAULT_STATUS = OpenTelemetry::Trace::Status.new(OpenTelemetry::Trace::Status::UNSET)
19
+ DEFAULT_STATUS = OpenTelemetry::Trace::Status.unset
20
20
  EMPTY_ATTRIBUTES = {}.freeze
21
21
 
22
22
  private_constant :DEFAULT_STATUS, :EMPTY_ATTRIBUTES
@@ -159,7 +159,7 @@ module OpenTelemetry
159
159
  event_attributes = {
160
160
  'exception.type' => exception.class.to_s,
161
161
  'exception.message' => exception.message,
162
- 'exception.stacktrace' => exception.full_message(highlight: false, order: :top)
162
+ 'exception.stacktrace' => exception.full_message(highlight: false, order: :top).encode('UTF-8', invalid: :replace, undef: :replace, replace: '�')
163
163
  }
164
164
  event_attributes.merge!(attributes) unless attributes.nil?
165
165
  add_event('exception', attributes: event_attributes)
@@ -167,20 +167,23 @@ module OpenTelemetry
167
167
 
168
168
  # Sets the Status to the Span
169
169
  #
170
- # If used, this will override the default Span status. Default is OK.
170
+ # If used, this will override the default Span status. Default has code = Status::UNSET.
171
171
  #
172
- # Only the value of the last call will be recorded, and implementations
173
- # are free to ignore previous calls.
172
+ # An attempt to set the status with code == Status::UNSET is ignored.
173
+ # If the status is set with code == Status::OK, any further attempt to set the status
174
+ # is ignored.
174
175
  #
175
176
  # @param [Status] status The new status, which overrides the default Span
176
- # status, which is OK.
177
+ # status, which has code = Status::UNSET.
177
178
  #
178
179
  # @return [void]
179
180
  def status=(status)
181
+ return if status.code == OpenTelemetry::Trace::Status::UNSET
182
+
180
183
  @mutex.synchronize do
181
184
  if @ended
182
185
  OpenTelemetry.logger.warn('Calling status= on an ended Span.')
183
- else
186
+ elsif @status.code != OpenTelemetry::Trace::Status::OK
184
187
  @status = status
185
188
  end
186
189
  end
@@ -235,7 +238,7 @@ module OpenTelemetry
235
238
  @events.freeze
236
239
  @ended = true
237
240
  end
238
- @span_processor.on_finish(self)
241
+ @span_processors.each { |processor| processor.on_finish(self) }
239
242
  self
240
243
  end
241
244
 
@@ -273,14 +276,14 @@ module OpenTelemetry
273
276
  end
274
277
 
275
278
  # @api private
276
- def initialize(context, parent_context, name, kind, parent_span_id, trace_config, span_processor, attributes, links, start_timestamp, resource, instrumentation_library) # rubocop:disable Metrics/AbcSize
279
+ def initialize(context, parent_context, name, kind, parent_span_id, span_limits, span_processors, attributes, links, start_timestamp, resource, instrumentation_library) # rubocop:disable Metrics/AbcSize
277
280
  super(span_context: context)
278
281
  @mutex = Mutex.new
279
282
  @name = name
280
283
  @kind = kind
281
284
  @parent_span_id = parent_span_id.freeze || OpenTelemetry::Trace::INVALID_SPAN_ID
282
- @trace_config = trace_config
283
- @span_processor = span_processor
285
+ @span_limits = span_limits
286
+ @span_processors = span_processors
284
287
  @resource = resource
285
288
  @instrumentation_library = instrumentation_library
286
289
  @ended = false
@@ -293,8 +296,8 @@ module OpenTelemetry
293
296
  @attributes = attributes.nil? ? nil : Hash[attributes] # We need a mutable copy of attributes.
294
297
  trim_span_attributes(@attributes)
295
298
  @events = nil
296
- @links = trim_links(links, trace_config.max_links_count, trace_config.max_attributes_per_link)
297
- @span_processor.on_start(self, parent_context)
299
+ @links = trim_links(links, span_limits.link_count_limit, span_limits.attribute_per_link_count_limit)
300
+ @span_processors.each { |processor| processor.on_start(self, parent_context) }
298
301
  end
299
302
 
300
303
  # TODO: Java implementation overrides finalize to log if a span isn't finished.
@@ -310,7 +313,7 @@ module OpenTelemetry
310
313
  def trim_span_attributes(attrs)
311
314
  return if attrs.nil?
312
315
 
313
- excess = attrs.size - @trace_config.max_attributes_count
316
+ excess = attrs.size - @span_limits.attribute_count_limit
314
317
  excess.times { attrs.shift } if excess.positive?
315
318
  truncate_attribute_values(attrs)
316
319
  nil
@@ -319,51 +322,51 @@ module OpenTelemetry
319
322
  def truncate_attribute_values(attrs)
320
323
  return EMPTY_ATTRIBUTES if attrs.nil?
321
324
 
322
- max_attributes_length = @trace_config.max_attributes_length
323
- attrs.each { |key, value| attrs[key] = OpenTelemetry::Common::Utilities.truncate(value, max_attributes_length) } if max_attributes_length
325
+ attribute_length_limit = @span_limits.attribute_length_limit
326
+ attrs.each { |key, value| attrs[key] = OpenTelemetry::Common::Utilities.truncate(value, attribute_length_limit) } if attribute_length_limit
324
327
  attrs
325
328
  end
326
329
 
327
- def trim_links(links, max_links_count, max_attributes_per_link) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
330
+ def trim_links(links, link_count_limit, attribute_per_link_count_limit) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
328
331
  # Fast path (likely) common cases.
329
332
  return nil if links.nil?
330
333
 
331
- if links.size <= max_links_count &&
332
- links.all? { |link| link.attributes.size <= max_attributes_per_link && Internal.valid_attributes?(name, 'link', link.attributes) }
334
+ if links.size <= link_count_limit &&
335
+ links.all? { |link| link.attributes.size <= attribute_per_link_count_limit && Internal.valid_attributes?(name, 'link', link.attributes) }
333
336
  return links.frozen? ? links : links.clone.freeze
334
337
  end
335
338
 
336
339
  # Slow path: trim attributes for each Link.
337
- links.last(max_links_count).map! do |link|
340
+ links.last(link_count_limit).map! do |link|
338
341
  attrs = Hash[link.attributes] # link.attributes is frozen, so we need an unfrozen copy to adjust.
339
342
  attrs.keep_if { |key, value| Internal.valid_key?(key) && Internal.valid_value?(value) }
340
- excess = attrs.size - max_attributes_per_link
343
+ excess = attrs.size - attribute_per_link_count_limit
341
344
  excess.times { attrs.shift } if excess.positive?
342
345
  OpenTelemetry::Trace::Link.new(link.span_context, attrs)
343
346
  end.freeze
344
347
  end
345
348
 
346
349
  def append_event(events, event) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
347
- max_events_count = @trace_config.max_events_count
348
- max_attributes_per_event = @trace_config.max_attributes_per_event
350
+ event_count_limit = @span_limits.event_count_limit
351
+ attribute_per_event_count_limit = @span_limits.attribute_per_event_count_limit
349
352
  valid_attributes = Internal.valid_attributes?(name, 'event', event.attributes)
350
353
 
351
354
  # Fast path (likely) common case.
352
- if events.size < max_events_count &&
353
- event.attributes.size <= max_attributes_per_event &&
355
+ if events.size < event_count_limit &&
356
+ event.attributes.size <= attribute_per_event_count_limit &&
354
357
  valid_attributes
355
358
  return events << event
356
359
  end
357
360
 
358
361
  # Slow path.
359
- excess = events.size + 1 - max_events_count
362
+ excess = events.size + 1 - event_count_limit
360
363
  events.shift(excess) if excess.positive?
361
364
 
362
- excess = event.attributes.size - max_attributes_per_event
365
+ excess = event.attributes.size - attribute_per_event_count_limit
363
366
  if excess.positive? || !valid_attributes
364
367
  attrs = Hash[event.attributes] # event.attributes is frozen, so we need an unfrozen copy to adjust.
365
368
  attrs.keep_if { |key, value| Internal.valid_key?(key) && Internal.valid_value?(value) }
366
- excess = attrs.size - max_attributes_per_event
369
+ excess = attrs.size - attribute_per_event_count_limit
367
370
  excess.times { attrs.shift } if excess.positive?
368
371
  event = Event.new(event.name, attrs.freeze, event.timestamp)
369
372
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright The OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ module SDK
9
+ module Trace
10
+ # Class that holds global trace parameters.
11
+ class SpanLimits
12
+ # The global default max number of attributes per {Span}.
13
+ attr_reader :attribute_count_limit
14
+
15
+ # The global default max length of attribute value per {Span}.
16
+ attr_reader :attribute_length_limit
17
+
18
+ # The global default max number of {OpenTelemetry::SDK::Trace::Event}s per {Span}.
19
+ attr_reader :event_count_limit
20
+
21
+ # The global default max number of {OpenTelemetry::Trace::Link} entries per {Span}.
22
+ attr_reader :link_count_limit
23
+
24
+ # The global default max number of attributes per {OpenTelemetry::SDK::Trace::Event}.
25
+ attr_reader :attribute_per_event_count_limit
26
+
27
+ # The global default max number of attributes per {OpenTelemetry::Trace::Link}.
28
+ attr_reader :attribute_per_link_count_limit
29
+
30
+ # Returns a {SpanLimits} with the desired values.
31
+ #
32
+ # @return [SpanLimits] with the desired values.
33
+ # @raise [ArgumentError] if any of the max numbers are not positive.
34
+ def initialize(attribute_count_limit: Integer(ENV.fetch('OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT', 128)), # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
35
+ attribute_length_limit: ENV['OTEL_RUBY_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT'],
36
+ event_count_limit: Integer(ENV.fetch('OTEL_SPAN_EVENT_COUNT_LIMIT', 128)),
37
+ link_count_limit: Integer(ENV.fetch('OTEL_SPAN_LINK_COUNT_LIMIT', 128)),
38
+ attribute_per_event_count_limit: attribute_count_limit,
39
+ attribute_per_link_count_limit: attribute_count_limit)
40
+ raise ArgumentError, 'attribute_count_limit must be positive' unless attribute_count_limit.positive?
41
+ raise ArgumentError, 'attribute_length_limit must not be less than 32' unless attribute_length_limit.nil? || Integer(attribute_length_limit) >= 32
42
+ raise ArgumentError, 'event_count_limit must be positive' unless event_count_limit.positive?
43
+ raise ArgumentError, 'link_count_limit must be positive' unless link_count_limit.positive?
44
+ raise ArgumentError, 'attribute_per_event_count_limit must be positive' unless attribute_per_event_count_limit.positive?
45
+ raise ArgumentError, 'attribute_per_link_count_limit must be positive' unless attribute_per_link_count_limit.positive?
46
+
47
+ @attribute_count_limit = attribute_count_limit
48
+ @attribute_length_limit = attribute_length_limit.nil? ? nil : Integer(attribute_length_limit)
49
+ @event_count_limit = event_count_limit
50
+ @link_count_limit = link_count_limit
51
+ @attribute_per_event_count_limit = attribute_per_event_count_limit
52
+ @attribute_per_link_count_limit = attribute_per_link_count_limit
53
+ end
54
+
55
+ # The default {SpanLimits}.
56
+ DEFAULT = new
57
+ end
58
+ end
59
+ end
60
+ end
@@ -4,17 +4,14 @@
4
4
  #
5
5
  # SPDX-License-Identifier: Apache-2.0
6
6
 
7
- require 'singleton'
8
-
9
7
  module OpenTelemetry
10
8
  module SDK
11
9
  module Trace
12
- # NoopSpanProcessor is a singleton implementation of the duck type
13
- # SpanProcessor that provides synchronous no-op hooks for when a
14
- # {Span} is started or when a {Span} is ended.
15
- class NoopSpanProcessor
16
- include Singleton
17
-
10
+ # SpanProcessor describes a duck type and provides synchronous no-op hooks for when a
11
+ # {Span} is started or when a {Span} is ended. It is not required to subclass this
12
+ # class to provide an implementation of SpanProcessor, provided the interface is
13
+ # satisfied.
14
+ class SpanProcessor
18
15
  # Called when a {Span} is started, if the {Span#recording?}
19
16
  # returns true.
20
17
  #
@@ -9,10 +9,6 @@ module OpenTelemetry
9
9
  module Trace
10
10
  # {Tracer} is the SDK implementation of {OpenTelemetry::Trace::Tracer}.
11
11
  class Tracer < OpenTelemetry::Trace::Tracer
12
- attr_reader :name
13
- attr_reader :version
14
- attr_reader :tracer_provider
15
-
16
12
  # @api private
17
13
  #
18
14
  # Returns a new {Tracer} instance.
@@ -23,8 +19,6 @@ module OpenTelemetry
23
19
  #
24
20
  # @return [Tracer]
25
21
  def initialize(name, version, tracer_provider)
26
- @name = name
27
- @version = version
28
22
  @instrumentation_library = InstrumentationLibrary.new(name, version)
29
23
  @tracer_provider = tracer_provider
30
24
  end
@@ -42,37 +36,7 @@ module OpenTelemetry
42
36
  parent_span_id = parent_span_context.span_id
43
37
  trace_id = parent_span_context.trace_id
44
38
  end
45
- trace_id ||= tracer_provider.id_generator.generate_trace_id
46
- sampler = tracer_provider.active_trace_config.sampler
47
- result = sampler.should_sample?(trace_id: trace_id, parent_context: with_parent, links: links, name: name, kind: kind, attributes: attributes)
48
- internal_create_span(result, name, kind, trace_id, parent_span_id, attributes, links, start_timestamp, with_parent)
49
- end
50
-
51
- private
52
-
53
- def internal_create_span(result, name, kind, trace_id, parent_span_id, attributes, links, start_timestamp, parent_context) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
54
- span_id = tracer_provider.id_generator.generate_span_id
55
- if result.recording? && !tracer_provider.stopped?
56
- trace_flags = result.sampled? ? OpenTelemetry::Trace::TraceFlags::SAMPLED : OpenTelemetry::Trace::TraceFlags::DEFAULT
57
- context = OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id, span_id: span_id, trace_flags: trace_flags, tracestate: result.tracestate)
58
- attributes = attributes&.merge(result.attributes) || result.attributes
59
- Span.new(
60
- context,
61
- parent_context,
62
- name,
63
- kind,
64
- parent_span_id,
65
- tracer_provider.active_trace_config,
66
- tracer_provider.active_span_processor,
67
- attributes,
68
- links,
69
- start_timestamp,
70
- tracer_provider.resource,
71
- @instrumentation_library
72
- )
73
- else
74
- OpenTelemetry::Trace::Span.new(span_context: OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id, span_id: span_id, tracestate: result.tracestate))
75
- end
39
+ @tracer_provider.internal_create_span(name, kind, trace_id, parent_span_id, attributes, links, start_timestamp, with_parent, @instrumentation_library)
76
40
  end
77
41
  end
78
42
  end
@@ -8,24 +8,35 @@ module OpenTelemetry
8
8
  module SDK
9
9
  module Trace
10
10
  # {TracerProvider} is the SDK implementation of {OpenTelemetry::Trace::TracerProvider}.
11
- class TracerProvider < OpenTelemetry::Trace::TracerProvider
11
+ class TracerProvider < OpenTelemetry::Trace::TracerProvider # rubocop:disable Metrics/ClassLength
12
12
  Key = Struct.new(:name, :version)
13
13
  private_constant(:Key)
14
14
 
15
- attr_accessor :active_trace_config, :id_generator
16
- attr_reader :active_span_processor, :stopped, :resource
17
- alias stopped? stopped
15
+ attr_accessor :span_limits, :id_generator, :sampler
16
+ attr_reader :resource
18
17
 
19
18
  # Returns a new {TracerProvider} instance.
20
19
  #
20
+ # @param [optional Sampler] sampler The sampling policy for new spans
21
+ # @param [optional Resource] resource The resource to associate with spans
22
+ # created by Tracers created by this TracerProvider
23
+ # @param [optional IDGenerator] id_generator The trace and span ID generation
24
+ # policy
25
+ # @param [optional SpanLimits] span_limits The limits to apply to attribute,
26
+ # event and link counts for Spans created by Tracers created by this
27
+ # TracerProvider
28
+ #
21
29
  # @return [TracerProvider]
22
- def initialize(resource = OpenTelemetry::SDK::Resources::Resource.create)
30
+ def initialize(sampler: sampler_from_environment(Samplers.parent_based(root: Samplers::ALWAYS_ON)),
31
+ resource: OpenTelemetry::SDK::Resources::Resource.create,
32
+ id_generator: OpenTelemetry::Trace,
33
+ span_limits: SpanLimits::DEFAULT)
23
34
  @mutex = Mutex.new
24
35
  @registry = {}
25
- @active_span_processor = NoopSpanProcessor.instance
26
- @active_trace_config = Config::TraceConfig::DEFAULT
27
- @id_generator = OpenTelemetry::Trace
28
- @registered_span_processors = []
36
+ @span_processors = []
37
+ @span_limits = span_limits
38
+ @sampler = sampler
39
+ @id_generator = id_generator
29
40
  @stopped = false
30
41
  @resource = resource
31
42
  end
@@ -39,6 +50,7 @@ module OpenTelemetry
39
50
  def tracer(name = nil, version = nil)
40
51
  name ||= ''
41
52
  version ||= ''
53
+ OpenTelemetry.logger.warn 'calling TracerProvider#tracer without providing a tracer name.' if name.empty?
42
54
  @mutex.synchronize { @registry[Key.new(name, version)] ||= Tracer.new(name, version, self) }
43
55
  end
44
56
 
@@ -52,14 +64,24 @@ module OpenTelemetry
52
64
  # After this is called all the newly created {Span}s will be no-op.
53
65
  #
54
66
  # @param [optional Numeric] timeout An optional timeout in seconds.
67
+ # @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
68
+ # a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
55
69
  def shutdown(timeout: nil)
56
70
  @mutex.synchronize do
57
71
  if @stopped
58
72
  OpenTelemetry.logger.warn('calling Tracer#shutdown multiple times.')
59
- return
73
+ return Export::FAILURE
74
+ end
75
+
76
+ start_time = OpenTelemetry::Common::Utilities.timeout_timestamp
77
+ results = @span_processors.map do |processor|
78
+ remaining_timeout = OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time)
79
+ break [Export::TIMEOUT] if remaining_timeout&.zero?
80
+
81
+ processor.shutdown(timeout: remaining_timeout)
60
82
  end
61
- @active_span_processor.shutdown(timeout: timeout)
62
83
  @stopped = true
84
+ results.max || Export::SUCCESS
63
85
  end
64
86
  end
65
87
 
@@ -78,7 +100,14 @@ module OpenTelemetry
78
100
  @mutex.synchronize do
79
101
  return Export::SUCCESS if @stopped
80
102
 
81
- @active_span_processor.force_flush(timeout: timeout)
103
+ start_time = OpenTelemetry::Common::Utilities.timeout_timestamp
104
+ results = @span_processors.map do |processor|
105
+ remaining_timeout = OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time)
106
+ return Export::TIMEOUT if remaining_timeout&.zero?
107
+
108
+ processor.force_flush(timeout: remaining_timeout)
109
+ end
110
+ results.max || Export::SUCCESS
82
111
  end
83
112
  end
84
113
 
@@ -91,13 +120,53 @@ module OpenTelemetry
91
120
  OpenTelemetry.logger.warn('calling Tracer#add_span_processor after shutdown.')
92
121
  return
93
122
  end
94
- @registered_span_processors << span_processor
95
- @active_span_processor = if @registered_span_processors.size == 1
96
- span_processor
97
- else
98
- MultiSpanProcessor.new(@registered_span_processors.dup)
99
- end
123
+ @span_processors = @span_processors.dup.push(span_processor)
124
+ end
125
+ end
126
+
127
+ # @api private
128
+ def internal_create_span(name, kind, trace_id, parent_span_id, attributes, links, start_timestamp, parent_context, instrumentation_library) # rubocop:disable Metrics/MethodLength
129
+ trace_id ||= @id_generator.generate_trace_id
130
+ result = @sampler.should_sample?(trace_id: trace_id, parent_context: parent_context, links: links, name: name, kind: kind, attributes: attributes)
131
+ span_id = @id_generator.generate_span_id
132
+ if result.recording? && !@stopped
133
+ trace_flags = result.sampled? ? OpenTelemetry::Trace::TraceFlags::SAMPLED : OpenTelemetry::Trace::TraceFlags::DEFAULT
134
+ context = OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id, span_id: span_id, trace_flags: trace_flags, tracestate: result.tracestate)
135
+ attributes = attributes&.merge(result.attributes) || result.attributes
136
+ Span.new(
137
+ context,
138
+ parent_context,
139
+ name,
140
+ kind,
141
+ parent_span_id,
142
+ @span_limits,
143
+ @span_processors,
144
+ attributes,
145
+ links,
146
+ start_timestamp,
147
+ @resource,
148
+ instrumentation_library
149
+ )
150
+ else
151
+ OpenTelemetry::Trace.non_recording_span(OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id, span_id: span_id, tracestate: result.tracestate))
152
+ end
153
+ end
154
+
155
+ private
156
+
157
+ def sampler_from_environment(default_sampler) # rubocop:disable Metrics/CyclomaticComplexity
158
+ case ENV['OTEL_TRACES_SAMPLER']
159
+ when 'always_on' then Samplers::ALWAYS_ON
160
+ when 'always_off' then Samplers::ALWAYS_OFF
161
+ when 'traceidratio' then Samplers.trace_id_ratio_based(Float(ENV.fetch('OTEL_TRACES_SAMPLER_ARG', 1.0)))
162
+ when 'parentbased_always_on' then Samplers.parent_based(root: Samplers::ALWAYS_ON)
163
+ when 'parentbased_always_off' then Samplers.parent_based(root: Samplers::ALWAYS_OFF)
164
+ when 'parentbased_traceidratio' then Samplers.parent_based(root: Samplers.trace_id_ratio_based(Float(ENV.fetch('OTEL_TRACES_SAMPLER_ARG', 1.0))))
165
+ else default_sampler
100
166
  end
167
+ rescue StandardError => e
168
+ OpenTelemetry.handle_error(exception: e, message: "installing default sampler #{default_sampler.description}")
169
+ default_sampler
101
170
  end
102
171
  end
103
172
  end
@@ -7,6 +7,6 @@
7
7
  module OpenTelemetry
8
8
  module SDK
9
9
  ## Current OpenTelemetry version
10
- VERSION = '1.0.0.rc1'
10
+ VERSION = '1.0.0.rc2'
11
11
  end
12
12
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opentelemetry-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc1
4
+ version: 1.0.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenTelemetry Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-21 00:00:00.000000000 Z
11
+ date: 2021-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opentelemetry-api
@@ -16,42 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.0.0.rc1
19
+ version: 1.0.0.rc2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.0.0.rc1
26
+ version: 1.0.0.rc2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: opentelemetry-common
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.18.0
33
+ version: 0.19.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.18.0
40
+ version: 0.19.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: opentelemetry-instrumentation-base
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 0.18.0
47
+ version: 0.18.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 0.18.0
54
+ version: 0.18.1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -192,25 +192,21 @@ files:
192
192
  - lib/opentelemetry-sdk.rb
193
193
  - lib/opentelemetry/sdk.rb
194
194
  - lib/opentelemetry/sdk/configurator.rb
195
+ - lib/opentelemetry/sdk/forwarding_logger.rb
195
196
  - lib/opentelemetry/sdk/instrumentation_library.rb
196
197
  - lib/opentelemetry/sdk/internal.rb
197
198
  - lib/opentelemetry/sdk/resources.rb
198
199
  - lib/opentelemetry/sdk/resources/constants.rb
199
200
  - lib/opentelemetry/sdk/resources/resource.rb
200
201
  - lib/opentelemetry/sdk/trace.rb
201
- - lib/opentelemetry/sdk/trace/config.rb
202
- - lib/opentelemetry/sdk/trace/config/trace_config.rb
203
202
  - lib/opentelemetry/sdk/trace/event.rb
204
203
  - lib/opentelemetry/sdk/trace/export.rb
205
204
  - lib/opentelemetry/sdk/trace/export/batch_span_processor.rb
206
205
  - lib/opentelemetry/sdk/trace/export/console_span_exporter.rb
207
206
  - lib/opentelemetry/sdk/trace/export/in_memory_span_exporter.rb
208
207
  - lib/opentelemetry/sdk/trace/export/metrics_reporter.rb
209
- - lib/opentelemetry/sdk/trace/export/multi_span_exporter.rb
210
- - lib/opentelemetry/sdk/trace/export/noop_span_exporter.rb
211
208
  - lib/opentelemetry/sdk/trace/export/simple_span_processor.rb
212
- - lib/opentelemetry/sdk/trace/multi_span_processor.rb
213
- - lib/opentelemetry/sdk/trace/noop_span_processor.rb
209
+ - lib/opentelemetry/sdk/trace/export/span_exporter.rb
214
210
  - lib/opentelemetry/sdk/trace/samplers.rb
215
211
  - lib/opentelemetry/sdk/trace/samplers/constant_sampler.rb
216
212
  - lib/opentelemetry/sdk/trace/samplers/decision.rb
@@ -219,6 +215,8 @@ files:
219
215
  - lib/opentelemetry/sdk/trace/samplers/trace_id_ratio_based.rb
220
216
  - lib/opentelemetry/sdk/trace/span.rb
221
217
  - lib/opentelemetry/sdk/trace/span_data.rb
218
+ - lib/opentelemetry/sdk/trace/span_limits.rb
219
+ - lib/opentelemetry/sdk/trace/span_processor.rb
222
220
  - lib/opentelemetry/sdk/trace/tracer.rb
223
221
  - lib/opentelemetry/sdk/trace/tracer_provider.rb
224
222
  - lib/opentelemetry/sdk/version.rb
@@ -226,10 +224,10 @@ homepage: https://github.com/open-telemetry/opentelemetry-ruby
226
224
  licenses:
227
225
  - Apache-2.0
228
226
  metadata:
229
- changelog_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-sdk/v1.0.0.rc1/file.CHANGELOG.html
227
+ changelog_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-sdk/v1.0.0.rc2/file.CHANGELOG.html
230
228
  source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/main/sdk
231
229
  bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby/issues
232
- documentation_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-sdk/v1.0.0.rc1
230
+ documentation_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-sdk/v1.0.0.rc2
233
231
  post_install_message:
234
232
  rdoc_options: []
235
233
  require_paths:
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright The OpenTelemetry Authors
4
- #
5
- # SPDX-License-Identifier: Apache-2.0
6
-
7
- module OpenTelemetry
8
- module SDK
9
- module Trace
10
- # The Config module contains the configuration logic for the
11
- # OpenTelemetry SDK.
12
- module Config
13
- end
14
- end
15
- end
16
- end
17
-
18
- require 'opentelemetry/sdk/trace/config/trace_config'
@@ -1,85 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright The OpenTelemetry Authors
4
- #
5
- # SPDX-License-Identifier: Apache-2.0
6
-
7
- module OpenTelemetry
8
- module SDK
9
- module Trace
10
- module Config
11
- # Class that holds global trace parameters.
12
- class TraceConfig
13
- # The global default sampler (see {Samplers}).
14
- attr_reader :sampler
15
-
16
- # The global default max number of attributes per {Span}.
17
- attr_reader :max_attributes_count
18
-
19
- # The global default max length of attribute value per {Span}.
20
- attr_reader :max_attributes_length
21
-
22
- # The global default max number of {OpenTelemetry::SDK::Trace::Event}s per {Span}.
23
- attr_reader :max_events_count
24
-
25
- # The global default max number of {OpenTelemetry::Trace::Link} entries per {Span}.
26
- attr_reader :max_links_count
27
-
28
- # The global default max number of attributes per {OpenTelemetry::SDK::Trace::Event}.
29
- attr_reader :max_attributes_per_event
30
-
31
- # The global default max number of attributes per {OpenTelemetry::Trace::Link}.
32
- attr_reader :max_attributes_per_link
33
-
34
- # Returns a {TraceConfig} with the desired values.
35
- #
36
- # @return [TraceConfig] with the desired values.
37
- # @raise [ArgumentError] if any of the max numbers are not positive.
38
- def initialize(sampler: sampler_from_environment(Samplers.parent_based(root: Samplers::ALWAYS_ON)), # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
39
- max_attributes_count: Integer(ENV.fetch('OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT', 128)),
40
- max_attributes_length: ENV['OTEL_RUBY_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT'],
41
- max_events_count: Integer(ENV.fetch('OTEL_SPAN_EVENT_COUNT_LIMIT', 128)),
42
- max_links_count: Integer(ENV.fetch('OTEL_SPAN_LINK_COUNT_LIMIT', 128)),
43
- max_attributes_per_event: max_attributes_count,
44
- max_attributes_per_link: max_attributes_count)
45
- raise ArgumentError, 'max_attributes_count must be positive' unless max_attributes_count.positive?
46
- raise ArgumentError, 'max_attributes_length must not be less than 32' unless max_attributes_length.nil? || Integer(max_attributes_length) >= 32
47
- raise ArgumentError, 'max_events_count must be positive' unless max_events_count.positive?
48
- raise ArgumentError, 'max_links_count must be positive' unless max_links_count.positive?
49
- raise ArgumentError, 'max_attributes_per_event must be positive' unless max_attributes_per_event.positive?
50
- raise ArgumentError, 'max_attributes_per_link must be positive' unless max_attributes_per_link.positive?
51
-
52
- @sampler = sampler
53
- @max_attributes_count = max_attributes_count
54
- @max_attributes_length = max_attributes_length.nil? ? nil : Integer(max_attributes_length)
55
- @max_events_count = max_events_count
56
- @max_links_count = max_links_count
57
- @max_attributes_per_event = max_attributes_per_event
58
- @max_attributes_per_link = max_attributes_per_link
59
- end
60
-
61
- # TODO: from_proto
62
- private
63
-
64
- def sampler_from_environment(default_sampler) # rubocop:disable Metrics/CyclomaticComplexity
65
- case ENV['OTEL_TRACES_SAMPLER']
66
- when 'always_on' then Samplers::ALWAYS_ON
67
- when 'always_off' then Samplers::ALWAYS_OFF
68
- when 'traceidratio' then Samplers.trace_id_ratio_based(Float(ENV.fetch('OTEL_TRACES_SAMPLER_ARG', 1.0)))
69
- when 'parentbased_always_on' then Samplers.parent_based(root: Samplers::ALWAYS_ON)
70
- when 'parentbased_always_off' then Samplers.parent_based(root: Samplers::ALWAYS_OFF)
71
- when 'parentbased_traceidratio' then Samplers.parent_based(root: Samplers.trace_id_ratio_based(Float(ENV.fetch('OTEL_TRACES_SAMPLER_ARG', 1.0))))
72
- else default_sampler
73
- end
74
- rescue StandardError => e
75
- OpenTelemetry.handle_error(exception: e, message: "installing default sampler #{default_sampler.description}")
76
- default_sampler
77
- end
78
-
79
- # The default {TraceConfig}.
80
- DEFAULT = new
81
- end
82
- end
83
- end
84
- end
85
- end
@@ -1,76 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright The OpenTelemetry Authors
4
- #
5
- # SPDX-License-Identifier: Apache-2.0
6
-
7
- module OpenTelemetry
8
- module SDK
9
- module Trace
10
- module Export
11
- # Implementation of the SpanExporter duck type that simply forwards all
12
- # received spans to a collection of SpanExporters.
13
- #
14
- # Can be used to export to multiple backends using the same
15
- # SpanProcessor like a {SimpleSpanProcessor} or a
16
- # {BatchSpanProcessor}.
17
- class MultiSpanExporter
18
- def initialize(span_exporters)
19
- @span_exporters = span_exporters.clone.freeze
20
- end
21
-
22
- # Called to export sampled {Span}s.
23
- #
24
- # @param [Enumerable<Span>] spans the list of sampled {Span}s to be
25
- # exported.
26
- # @param [optional Numeric] timeout An optional timeout in seconds.
27
- # @return [Integer] the result of the export.
28
- def export(spans, timeout: nil)
29
- start_time = OpenTelemetry::Common::Utilities.timeout_timestamp
30
- results = @span_exporters.map do |span_exporter|
31
- span_exporter.export(spans, timeout: OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time))
32
- rescue => e # rubocop:disable Style/RescueStandardError
33
- OpenTelemetry.logger.warn("exception raised by export - #{e}")
34
- FAILURE
35
- end
36
- results.uniq.max || SUCCESS
37
- end
38
-
39
- # Called when {TracerProvider#force_flush} is called, if this exporter is
40
- # registered to a {TracerProvider} object.
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 force_flush(timeout: nil)
46
- start_time = OpenTelemetry::Common::Utilities.timeout_timestamp
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?
50
-
51
- processor.force_flush(timeout: remaining_timeout)
52
- end
53
- results.uniq.max || SUCCESS
54
- end
55
-
56
- # Called when {TracerProvider#shutdown} is called, if this exporter is
57
- # registered to a {TracerProvider} object.
58
- #
59
- # @param [optional Numeric] timeout An optional timeout in seconds.
60
- # @return [Integer] SUCCESS if no error occurred, FAILURE if a
61
- # non-specific failure occurred, TIMEOUT if a timeout occurred.
62
- def shutdown(timeout: nil)
63
- start_time = OpenTelemetry::Common::Utilities.timeout_timestamp
64
- results = @span_exporters.map do |processor|
65
- remaining_timeout = OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time)
66
- return TIMEOUT if remaining_timeout&.zero?
67
-
68
- processor.shutdown(timeout: remaining_timeout)
69
- end
70
- results.uniq.max || SUCCESS
71
- end
72
- end
73
- end
74
- end
75
- end
76
- end
@@ -1,86 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright The OpenTelemetry Authors
4
- #
5
- # SPDX-License-Identifier: Apache-2.0
6
-
7
- module OpenTelemetry
8
- module SDK
9
- module Trace
10
- # Implementation of the SpanProcessor duck type that simply forwards all
11
- # received events to a list of SpanProcessors.
12
- class MultiSpanProcessor
13
- # Creates a new {MultiSpanProcessor}.
14
- #
15
- # @param [Enumerable<SpanProcessor>] span_processors a collection of
16
- # SpanProcessors.
17
- # @return [MultiSpanProcessor]
18
- def initialize(span_processors)
19
- @span_processors = span_processors.to_a.freeze
20
- end
21
-
22
- # Called when a {Span} is started, if the {Span#recording?}
23
- # returns true.
24
- #
25
- # This method is called synchronously on the execution thread, should
26
- # not throw or block the execution thread.
27
- #
28
- # @param [Span] span the {Span} that just started.
29
- # @param [Context] parent_context the parent {Context} of the newly
30
- # started span.
31
- def on_start(span, parent_context)
32
- @span_processors.each { |processor| processor.on_start(span, parent_context) }
33
- end
34
-
35
- # Called when a {Span} is ended, if the {Span#recording?}
36
- # returns true.
37
- #
38
- # This method is called synchronously on the execution thread, should
39
- # not throw or block the execution thread.
40
- #
41
- # @param [Span] span the {Span} that just ended.
42
- def on_finish(span)
43
- @span_processors.each { |processor| processor.on_finish(span) }
44
- end
45
-
46
- # Export all ended spans to the configured `Exporter` that have not yet
47
- # been exported.
48
- #
49
- # This method should only be called in cases where it is absolutely
50
- # necessary, such as when using some FaaS providers that may suspend
51
- # the process after an invocation, but before the `Processor` exports
52
- # the completed spans.
53
- #
54
- # @param [optional Numeric] timeout An optional timeout in seconds.
55
- # @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
56
- # a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
57
- def force_flush(timeout: nil)
58
- start_time = OpenTelemetry::Common::Utilities.timeout_timestamp
59
- results = @span_processors.map do |processor|
60
- remaining_timeout = OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time)
61
- return Export::TIMEOUT if remaining_timeout&.zero?
62
-
63
- processor.force_flush(timeout: remaining_timeout)
64
- end
65
- results.uniq.max
66
- end
67
-
68
- # Called when {TracerProvider#shutdown} is called.
69
- #
70
- # @param [optional Numeric] timeout An optional timeout in seconds.
71
- # @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
72
- # a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
73
- def shutdown(timeout: nil)
74
- start_time = OpenTelemetry::Common::Utilities.timeout_timestamp
75
- results = @span_processors.map do |processor|
76
- remaining_timeout = OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time)
77
- return Export::TIMEOUT if remaining_timeout&.zero?
78
-
79
- processor.shutdown(timeout: remaining_timeout)
80
- end
81
- results.uniq.max
82
- end
83
- end
84
- end
85
- end
86
- end