opentelemetry-sdk 0.11.1 → 0.14.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 640e29efdf46f030e232f9fbb96f43f183438e546b8116eb94f989f83ab06966
4
- data.tar.gz: b6e023f909b6485b2eecd0ef150e4562c659b4d51856f87b226484c1db56b189
3
+ metadata.gz: 86e11789326f901d3c6e768ea1eac43f49826fd762a74e1878adaaf76d398074
4
+ data.tar.gz: 9431b37ace4dc00894f8aa81d89522d139120958a680141fe605a5ff73e57a66
5
5
  SHA512:
6
- metadata.gz: 5c58bfdb66b128e299ed2742c2327939ef02139c10b825d8ca5fe9a0c241340971e027a53c70de1777c9abf7a3c33e318ef936aa026aa6c4c496d6c0e3132a86
7
- data.tar.gz: c426b41723e57ddcfbe332f4b4e01982056b47813cc9afb05b4385f7bdeacc91544ee2c707bd98ce4824488ab89b407cc7ba73568e6b954cf7d39aed878f476c
6
+ metadata.gz: 6292a201663ec6e5a7cd54560ef25855865bc77b698fd4c80a1ee4bc4109760da9f9f3e2522753c0bcc6edd11728e0222093e3759db4466b12a423544f64358a
7
+ data.tar.gz: 602740b9c995cc0b204b45c2923914e57ddeaa5ba809d06e1b6707c2340597a53a33d9311e349ea2ece7b7c45181ecdf4a8b2e33511aab70a08cb081f2d9b30e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # Release History: opentelemetry-sdk
2
2
 
3
+ ### v0.14.0 / 2021-02-03
4
+
5
+ * BREAKING CHANGE: Replace getter and setter callables and remove rack specific propagators
6
+
7
+ * ADDED: Replace getter and setter callables and remove rack specific propagators
8
+
9
+ ### v0.13.1 / 2021-02-01
10
+
11
+ * FIXED: Leaky test
12
+ * FIXED: Allow env var override of service.name
13
+
14
+ ### v0.13.0 / 2021-01-29
15
+
16
+ * BREAKING CHANGE: Remove MILLIS from BatchSpanProcessor vars
17
+
18
+ * ADDED: Process.runtime resource
19
+ * ADDED: Provide default resource in SDK
20
+ * ADDED: Add optional attributes to record_exception
21
+ * FIXED: Resource.merge consistency
22
+ * FIXED: Remove MILLIS from BatchSpanProcessor vars
23
+
24
+ ### v0.12.1 / 2021-01-13
25
+
26
+ * FIXED: Fix several BatchSpanProcessor errors related to fork safety
27
+ * FIXED: Define default value for traceid ratio
28
+
29
+ ### v0.12.0 / 2020-12-24
30
+
31
+ * ADDED: Structured error handling
32
+ * ADDED: Pluggable ID generation
33
+ * FIXED: BSP dropped span buffer full reporting
34
+ * FIXED: Implement SDK environment variables
35
+ * FIXED: Remove incorrect TODO
36
+
3
37
  ### v0.11.1 / 2020-12-16
4
38
 
5
39
  * FIXED: BSP dropped span buffer full reporting
data/README.md CHANGED
@@ -66,8 +66,8 @@ The `opentelemetry-sdk` gem is distributed under the Apache 2.0 license. See [LI
66
66
  [opentelemetry-home]: https://opentelemetry.io
67
67
  [bundler-home]: https://bundler.io
68
68
  [repo-github]: https://github.com/open-telemetry/opentelemetry-ruby
69
- [license-github]: https://github.com/open-telemetry/opentelemetry-ruby/blob/master/LICENSE
70
- [examples-github]: https://github.com/open-telemetry/opentelemetry-ruby/tree/master/examples
69
+ [license-github]: https://github.com/open-telemetry/opentelemetry-ruby/blob/main/LICENSE
70
+ [examples-github]: https://github.com/open-telemetry/opentelemetry-ruby/tree/main/examples
71
71
  [ruby-sig]: https://github.com/open-telemetry/community#ruby-sig
72
72
  [community-meetings]: https://github.com/open-telemetry/community#community-meetings
73
73
  [ruby-gitter]: https://gitter.im/open-telemetry/opentelemetry-ruby
@@ -18,6 +18,11 @@ module OpenTelemetry
18
18
  module SDK
19
19
  extend self
20
20
 
21
+ # ConfigurationError is an exception type used to wrap configuration errors
22
+ # passed to OpenTelemetry.error_handler. This can be used to distinguish
23
+ # errors reported during SDK configuration.
24
+ ConfigurationError = Class.new(OpenTelemetry::Error)
25
+
21
26
  # Configures SDK and instrumentation
22
27
  #
23
28
  # @yieldparam [Configurator] configurator Yields a configurator to the
@@ -57,6 +62,12 @@ module OpenTelemetry
57
62
  configurator = Configurator.new
58
63
  yield configurator if block_given?
59
64
  configurator.configure
65
+ rescue StandardError
66
+ begin
67
+ raise ConfigurationError
68
+ rescue ConfigurationError => e
69
+ OpenTelemetry.handle_error(exception: e, message: 'unexpected configuration error')
70
+ end
60
71
  end
61
72
  end
62
73
  end
@@ -15,25 +15,28 @@ module OpenTelemetry
15
15
 
16
16
  private_constant :USE_MODE_UNSPECIFIED, :USE_MODE_ONE, :USE_MODE_ALL
17
17
 
18
- attr_writer :logger, :http_extractors, :http_injectors, :text_map_extractors,
19
- :text_map_injectors
18
+ attr_writer :logger, :extractors, :injectors, :error_handler,
19
+ :id_generator
20
20
 
21
21
  def initialize
22
22
  @instrumentation_names = []
23
23
  @instrumentation_config_map = {}
24
- @http_extractors = nil
25
- @http_injectors = nil
26
- @text_map_extractors = nil
27
- @text_map_injectors = nil
24
+ @injectors = nil
25
+ @extractors = nil
28
26
  @span_processors = []
29
27
  @use_mode = USE_MODE_UNSPECIFIED
30
- @resource = Resources::Resource.telemetry_sdk
28
+ @resource = Resources::Resource.default
29
+ @id_generator = OpenTelemetry::Trace
31
30
  end
32
31
 
33
32
  def logger
34
33
  @logger ||= OpenTelemetry.logger
35
34
  end
36
35
 
36
+ def error_handler
37
+ @error_handler ||= OpenTelemetry.error_handler
38
+ end
39
+
37
40
  # Accepts a resource object that is merged with the default telemetry sdk
38
41
  # resource. The use of this method is optional, and is provided as means
39
42
  # to include additional resource information.
@@ -41,7 +44,7 @@ module OpenTelemetry
41
44
  #
42
45
  # @param [Resource] new_resource The resource to be merged
43
46
  def resource=(new_resource)
44
- @resource = new_resource.merge(@resource)
47
+ @resource = @resource.merge(new_resource)
45
48
  end
46
49
 
47
50
  # Accepts a string that is merged in as the service.name resource attribute.
@@ -49,9 +52,9 @@ module OpenTelemetry
49
52
  # calls to this setter.
50
53
  # @param [String] service_name The value to be used as the service name
51
54
  def service_name=(service_name)
52
- @resource = OpenTelemetry::SDK::Resources::Resource.create(
55
+ self.resource = OpenTelemetry::SDK::Resources::Resource.create(
53
56
  OpenTelemetry::SDK::Resources::Constants::SERVICE_RESOURCE[:name] => service_name
54
- ).merge(@resource)
57
+ )
55
58
  end
56
59
 
57
60
  # Accepts a string that is merged in as the service.version resource attribute.
@@ -59,9 +62,9 @@ module OpenTelemetry
59
62
  # calls to this setter.
60
63
  # @param [String] service_version The value to be used as the service version
61
64
  def service_version=(service_version)
62
- @resource = OpenTelemetry::SDK::Resources::Resource.create(
65
+ self.resource = OpenTelemetry::SDK::Resources::Resource.create(
63
66
  OpenTelemetry::SDK::Resources::Constants::SERVICE_RESOURCE[:version] => service_version
64
- ).merge(@resource)
67
+ )
65
68
  end
66
69
 
67
70
  # Install an instrumentation with specificied optional +config+.
@@ -110,9 +113,11 @@ module OpenTelemetry
110
113
  # - install instrumentation
111
114
  def configure
112
115
  OpenTelemetry.logger = logger
116
+ OpenTelemetry.error_handler = error_handler
113
117
  OpenTelemetry.baggage = Baggage::Manager.new
114
118
  configure_propagation
115
119
  configure_span_processors
120
+ tracer_provider.id_generator = @id_generator
116
121
  OpenTelemetry.tracer_provider = tracer_provider
117
122
  install_instrumentation
118
123
  end
@@ -149,10 +154,8 @@ module OpenTelemetry
149
154
  end
150
155
 
151
156
  def configure_propagation
152
- OpenTelemetry.propagation.http = create_propagator(@http_injectors || default_http_injectors,
153
- @http_extractors || default_http_extractors)
154
- OpenTelemetry.propagation.text = create_propagator(@text_map_injectors || default_text_map_injectors,
155
- @text_map_extractors || default_text_map_extractors)
157
+ OpenTelemetry.propagation = create_propagator(@injectors || default_injectors,
158
+ @extractors || default_extractors)
156
159
  end
157
160
 
158
161
  def create_propagator(injectors, extractors)
@@ -163,25 +166,14 @@ module OpenTelemetry
163
166
  end
164
167
  end
165
168
 
166
- def default_http_injectors
167
- default_text_map_injectors
168
- end
169
-
170
- def default_http_extractors
171
- [
172
- OpenTelemetry::Trace::Propagation::TraceContext.rack_extractor,
173
- OpenTelemetry::Baggage::Propagation.rack_extractor
174
- ]
175
- end
176
-
177
- def default_text_map_injectors
169
+ def default_injectors
178
170
  [
179
171
  OpenTelemetry::Trace::Propagation::TraceContext.text_map_injector,
180
172
  OpenTelemetry::Baggage::Propagation.text_map_injector
181
173
  ]
182
174
  end
183
175
 
184
- def default_text_map_extractors
176
+ def default_extractors
185
177
  [
186
178
  OpenTelemetry::Trace::Propagation::TraceContext.text_map_extractor,
187
179
  OpenTelemetry::Baggage::Propagation.text_map_extractor
@@ -45,7 +45,17 @@ module OpenTelemetry
45
45
  end
46
46
 
47
47
  def valid_attributes?(attrs)
48
- attrs.nil? || attrs.all? { |k, v| valid_key?(k) && valid_value?(v) }
48
+ attrs.nil? || attrs.all? do |k, v|
49
+ if !valid_key?(k)
50
+ OpenTelemetry.handle_error(message: "invalid attribute key type #{v.class}")
51
+ false
52
+ elsif !valid_value?(v)
53
+ OpenTelemetry.handle_error(message: "invalid attribute value type #{v.class}")
54
+ false
55
+ else
56
+ true
57
+ end
58
+ end
49
59
  end
50
60
  end
51
61
  end
@@ -77,6 +77,46 @@ module OpenTelemetry
77
77
  deployment_name: 'k8s.deployment.name'
78
78
  }.freeze
79
79
 
80
+ # Attributes defining an operating system process.
81
+ PROCESS_RESOURCE = {
82
+ # Process identifier (PID).
83
+ pid: 'process.pid',
84
+
85
+ # The name of the process executable.
86
+ executable_name: 'process.executable.name',
87
+
88
+ # The full path to the process executable.
89
+ executable_path: 'process.executable.path',
90
+
91
+ # The command used to launch the process (i.e. the command name).
92
+ command: 'process.command',
93
+
94
+ # The full command used to launch the process as a single string
95
+ # representing the full command.
96
+ command_line: 'process.command_line',
97
+
98
+ # All the command arguments (including the command/executable itself)
99
+ # as received by the process.
100
+ command_args: 'process.command_args',
101
+
102
+ # The username of the user that owns the process.
103
+ owner: 'process.owner'
104
+ }.freeze
105
+
106
+ # Attributes defining the single (language) runtime instance which is monitored.
107
+ PROCESS_RUNTIME_RESOURCE = {
108
+ # The name of the runtime of this process.
109
+ name: 'process.runtime.name',
110
+
111
+ # The version of the runtime of this process, as returned by the runtime
112
+ # without modification.
113
+ version: 'process.runtime.version',
114
+
115
+ # An additional description about the runtime of the process, for example
116
+ # a specific vendor customization of the runtime environment.
117
+ description: 'process.runtime.description'
118
+ }.freeze
119
+
80
120
  # Attributes defining a computing instance (e.g. host).
81
121
  HOST_RESOURCE = {
82
122
  # Unique host id. For Cloud this must be the instance_id assigned by the
@@ -22,7 +22,7 @@ module OpenTelemetry
22
22
  def create(attributes = {})
23
23
  frozen_attributes = attributes.each_with_object({}) do |(k, v), memo|
24
24
  raise ArgumentError, 'attribute keys must be strings' unless k.is_a?(String)
25
- raise ArgumentError, 'attribute values must be strings, integers, floats, or booleans' unless Internal.valid_value?(v)
25
+ raise ArgumentError, 'attribute values must be (array of) strings, integers, floats, or booleans' unless Internal.valid_value?(v)
26
26
 
27
27
  memo[-k] = v.freeze
28
28
  end.freeze
@@ -30,6 +30,10 @@ module OpenTelemetry
30
30
  new(frozen_attributes)
31
31
  end
32
32
 
33
+ def default
34
+ @default ||= create(Constants::SERVICE_RESOURCE[:name] => 'unknown_service').merge(process).merge(telemetry_sdk)
35
+ end
36
+
33
37
  def telemetry_sdk
34
38
  resource_attributes = {
35
39
  Constants::TELEMETRY_SDK_RESOURCE[:name] => 'opentelemetry',
@@ -48,6 +52,18 @@ module OpenTelemetry
48
52
  resource_attributes.delete_if { |_key, value| value.nil? || value.empty? }
49
53
  create(resource_attributes)
50
54
  end
55
+
56
+ def process
57
+ resource_attributes = {
58
+ Constants::PROCESS_RESOURCE[:pid] => Process.pid,
59
+ Constants::PROCESS_RESOURCE[:command] => $PROGRAM_NAME,
60
+ Constants::PROCESS_RUNTIME_RESOURCE[:name] => RUBY_ENGINE,
61
+ Constants::PROCESS_RUNTIME_RESOURCE[:version] => RUBY_VERSION,
62
+ Constants::PROCESS_RUNTIME_RESOURCE[:description] => RUBY_DESCRIPTION
63
+ }
64
+
65
+ create(resource_attributes)
66
+ end
51
67
  end
52
68
 
53
69
  # @api private
@@ -79,11 +95,7 @@ module OpenTelemetry
79
95
  def merge(other)
80
96
  return self unless other.is_a?(Resource)
81
97
 
82
- merged_attributes = attributes.merge(other.attributes) do |_, old_v, new_v|
83
- old_v.empty? ? new_v : old_v
84
- end
85
-
86
- self.class.send(:new, merged_attributes.freeze)
98
+ self.class.send(:new, attributes.merge(other.attributes).freeze)
87
99
  end
88
100
 
89
101
  protected
@@ -10,20 +10,6 @@ module OpenTelemetry
10
10
  module Config
11
11
  # Class that holds global trace parameters.
12
12
  class TraceConfig
13
- DEFAULT_SAMPLER = Samplers.parent_based(root: Samplers::ALWAYS_ON)
14
- DEFAULT_MAX_ATTRIBUTES_COUNT = 32
15
- DEFAULT_MAX_EVENTS_COUNT = 128
16
- DEFAULT_MAX_LINKS_COUNT = 32
17
- DEFAULT_MAX_ATTRIBUTES_PER_EVENT = 32
18
- DEFAULT_MAX_ATTRIBUTES_PER_LINK = 32
19
-
20
- private_constant(:DEFAULT_SAMPLER,
21
- :DEFAULT_MAX_ATTRIBUTES_COUNT,
22
- :DEFAULT_MAX_EVENTS_COUNT,
23
- :DEFAULT_MAX_LINKS_COUNT,
24
- :DEFAULT_MAX_ATTRIBUTES_PER_EVENT,
25
- :DEFAULT_MAX_ATTRIBUTES_PER_LINK)
26
-
27
13
  # The global default sampler (see {Samplers}).
28
14
  attr_reader :sampler
29
15
 
@@ -46,12 +32,12 @@ module OpenTelemetry
46
32
  #
47
33
  # @return [TraceConfig] with the desired values.
48
34
  # @raise [ArgumentError] if any of the max numbers are not positive.
49
- def initialize(sampler: DEFAULT_SAMPLER,
50
- max_attributes_count: DEFAULT_MAX_ATTRIBUTES_COUNT,
51
- max_events_count: DEFAULT_MAX_EVENTS_COUNT,
52
- max_links_count: DEFAULT_MAX_LINKS_COUNT,
53
- max_attributes_per_event: DEFAULT_MAX_ATTRIBUTES_PER_EVENT,
54
- max_attributes_per_link: DEFAULT_MAX_ATTRIBUTES_PER_LINK)
35
+ def initialize(sampler: sampler_from_environment(Samplers.parent_based(root: Samplers::ALWAYS_ON)),
36
+ max_attributes_count: Integer(ENV.fetch('OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT', 1000)),
37
+ max_events_count: Integer(ENV.fetch('OTEL_SPAN_EVENT_COUNT_LIMIT', 1000)),
38
+ max_links_count: Integer(ENV.fetch('OTEL_SPAN_LINK_COUNT_LIMIT', 1000)),
39
+ max_attributes_per_event: max_attributes_count,
40
+ max_attributes_per_link: max_attributes_count)
55
41
  raise ArgumentError, 'max_attributes_count must be positive' unless max_attributes_count.positive?
56
42
  raise ArgumentError, 'max_events_count must be positive' unless max_events_count.positive?
57
43
  raise ArgumentError, 'max_links_count must be positive' unless max_links_count.positive?
@@ -67,6 +53,22 @@ module OpenTelemetry
67
53
  end
68
54
 
69
55
  # TODO: from_proto
56
+ private
57
+
58
+ def sampler_from_environment(default_sampler) # rubocop:disable Metrics/CyclomaticComplexity
59
+ case ENV['OTEL_TRACE_SAMPLER']
60
+ when 'always_on' then Samplers::ALWAYS_ON
61
+ when 'always_off' then Samplers::ALWAYS_OFF
62
+ when 'traceidratio' then Samplers.trace_id_ratio_based(Float(ENV.fetch('OTEL_TRACE_SAMPLER_ARG', 1.0)))
63
+ when 'parentbased_always_on' then Samplers.parent_based(root: Samplers::ALWAYS_ON)
64
+ when 'parentbased_always_off' then Samplers.parent_based(root: Samplers::ALWAYS_OFF)
65
+ when 'parentbased_traceidratio' then Samplers.parent_based(root: Samplers.trace_id_ratio_based(Float(ENV.fetch('OTEL_TRACE_SAMPLER_ARG', 1.0))))
66
+ else default_sampler
67
+ end
68
+ rescue StandardError => e
69
+ OpenTelemetry.handle_error(exception: e, message: "installing default sampler #{default_sampler.description}")
70
+ default_sampler
71
+ end
70
72
 
71
73
  # The default {TraceConfig}.
72
74
  DEFAULT = new
@@ -19,7 +19,7 @@ module OpenTelemetry
19
19
  # All spans reported by the SDK implementation are first added to a
20
20
  # synchronized queue (with a {max_queue_size} maximum size, after the
21
21
  # size is reached spans are dropped) and exported every
22
- # schedule_delay_millis to the exporter pipeline in batches of
22
+ # schedule_delay to the exporter pipeline in batches of
23
23
  # max_export_batch_size.
24
24
  #
25
25
  # If the queue gets half full a preemptive notification is sent to the
@@ -29,11 +29,11 @@ module OpenTelemetry
29
29
  # Returns a new instance of the {BatchSpanProcessor}.
30
30
  #
31
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
32
+ # @param [Numeric] exporter_timeout the delay interval between two
33
+ # consecutive exports. Defaults to the value of the OTEL_BSP_EXPORT_TIMEOUT
34
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
35
+ # @param [Numeric] schedule_delay the maximum allowed time to export data.
36
+ # Defaults to the value of the OTEL_BSP_SCHEDULE_DELAY environment
37
37
  # variable, if set, or 5,000 (5 seconds).
38
38
  # @param [Integer] max_queue_size the maximum queue size in spans.
39
39
  # Defaults to the value of the OTEL_BSP_MAX_QUEUE_SIZE environment
@@ -44,8 +44,8 @@ module OpenTelemetry
44
44
  #
45
45
  # @return a new instance of the {BatchSpanProcessor}.
46
46
  def initialize(exporter:,
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)),
47
+ exporter_timeout: Float(ENV.fetch('OTEL_BSP_EXPORT_TIMEOUT', 30_000)),
48
+ schedule_delay: Float(ENV.fetch('OTEL_BSP_SCHEDULE_DELAY', 5_000)),
49
49
  max_queue_size: Integer(ENV.fetch('OTEL_BSP_MAX_QUEUE_SIZE', 2048)),
50
50
  max_export_batch_size: Integer(ENV.fetch('OTEL_BSP_MAX_EXPORT_BATCH_SIZE', 512)),
51
51
  start_thread_on_boot: String(ENV['OTEL_RUBY_BSP_START_THREAD_ON_BOOT']) !~ /false/i,
@@ -53,12 +53,12 @@ module OpenTelemetry
53
53
  raise ArgumentError if max_export_batch_size > max_queue_size
54
54
 
55
55
  @exporter = exporter
56
- @exporter_timeout_seconds = exporter_timeout_millis / 1000.0
56
+ @exporter_timeout_seconds = exporter_timeout / 1000.0
57
57
  @mutex = Mutex.new
58
58
  @export_mutex = Mutex.new
59
59
  @condition = ConditionVariable.new
60
60
  @keep_running = true
61
- @delay_seconds = schedule_delay_millis / 1000.0
61
+ @delay_seconds = schedule_delay / 1000.0
62
62
  @max_queue_size = max_queue_size
63
63
  @batch_size = max_export_batch_size
64
64
  @metrics_reporter = metrics_reporter || OpenTelemetry::SDK::Trace::Export::MetricsReporter
@@ -78,8 +78,10 @@ module OpenTelemetry
78
78
  lock do
79
79
  reset_on_fork
80
80
  n = spans.size + 1 - max_queue_size
81
- spans.shift(n) if n.positive?
82
- report_dropped_spans(n, reason: 'buffer-full')
81
+ if n.positive?
82
+ spans.shift(n)
83
+ report_dropped_spans(n, reason: 'buffer-full')
84
+ end
83
85
  spans << span
84
86
  @condition.signal if spans.size > batch_size
85
87
  end
@@ -99,7 +101,7 @@ module OpenTelemetry
99
101
  def force_flush(timeout: nil) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
100
102
  start_time = Time.now
101
103
  snapshot = lock do
102
- reset_on_fork(restart_thread: false) if @keep_running
104
+ reset_on_fork if @keep_running
103
105
  spans.shift(spans.size)
104
106
  end
105
107
  until snapshot.empty?
@@ -134,12 +136,13 @@ module OpenTelemetry
134
136
  # non-specific failure occurred, TIMEOUT if a timeout occurred.
135
137
  def shutdown(timeout: nil)
136
138
  start_time = Time.now
137
- lock do
139
+ thread = lock do
138
140
  @keep_running = false
139
141
  @condition.signal
142
+ @thread
140
143
  end
141
144
 
142
- @thread.join(timeout)
145
+ thread&.join(timeout)
143
146
  force_flush(timeout: OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time))
144
147
  @exporter.shutdown(timeout: OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time))
145
148
  dropped_spans = lock { spans.size }
@@ -153,7 +156,6 @@ module OpenTelemetry
153
156
  def work # rubocop:disable Metrics/AbcSize
154
157
  loop do
155
158
  batch = lock do
156
- reset_on_fork(restart_thread: false)
157
159
  @condition.wait(@mutex, @delay_seconds) if spans.size < batch_size && @keep_running
158
160
  @condition.wait(@mutex, @delay_seconds) while spans.empty? && @keep_running
159
161
  return unless @keep_running
@@ -173,7 +175,7 @@ module OpenTelemetry
173
175
 
174
176
  @pid = pid
175
177
  spans.clear
176
- @thread = Thread.new { work } if restart_thread
178
+ @thread = restart_thread ? Thread.new { work } : nil
177
179
  end
178
180
 
179
181
  def export_batch(batch, timeout: @exporter_timeout_seconds)
@@ -187,7 +189,7 @@ module OpenTelemetry
187
189
  @metrics_reporter.add_to_counter('otel.bsp.export.success')
188
190
  @metrics_reporter.add_to_counter('otel.bsp.exported_spans', increment: batch.size)
189
191
  else
190
- OpenTelemetry.logger.error("Unable to export #{batch.size} spans")
192
+ OpenTelemetry.handle_error(message: "Unable to export #{batch.size} spans")
191
193
  @metrics_reporter.add_to_counter('otel.bsp.export.failure')
192
194
  report_dropped_spans(batch.size, reason: 'export-failure')
193
195
  end
@@ -57,7 +57,7 @@ module OpenTelemetry
57
57
 
58
58
  @span_exporter&.export([span.to_span_data])
59
59
  rescue => e # rubocop:disable Style/RescueStandardError
60
- OpenTelemetry.logger.error("unexpected error in span.on_finish - #{e}")
60
+ OpenTelemetry.handle_error(exception: e, message: 'unexpected error in span.on_finish')
61
61
  end
62
62
 
63
63
  # Export all ended spans to the configured `Exporter` that have not yet
@@ -19,12 +19,20 @@ module OpenTelemetry
19
19
  @description = description
20
20
  end
21
21
 
22
+ def ==(other)
23
+ @decision == other.decision && @description == other.description
24
+ end
25
+
22
26
  # @api private
23
27
  #
24
28
  # See {Samplers}.
25
29
  def should_sample?(trace_id:, parent_context:, links:, name:, kind:, attributes:)
26
30
  Result.new(decision: @decision, tracestate: OpenTelemetry::Trace.current_span(parent_context).context.tracestate)
27
31
  end
32
+
33
+ protected
34
+
35
+ attr_reader :decision
28
36
  end
29
37
  end
30
38
  end
@@ -26,6 +26,14 @@ module OpenTelemetry
26
26
  @local_parent_not_sampled = local_parent_not_sampled
27
27
  end
28
28
 
29
+ def ==(other)
30
+ @root == other.root &&
31
+ @remote_parent_sampled == other.remote_parent_sampled &&
32
+ @remote_parent_not_sampled == other.remote_parent_not_sampled &&
33
+ @local_parent_sampled == other.local_parent_sampled &&
34
+ @local_parent_not_sampled == other.local_parent_not_sampled
35
+ end
36
+
29
37
  # @api private
30
38
  #
31
39
  # See {Samplers}.
@@ -47,6 +55,10 @@ module OpenTelemetry
47
55
  end
48
56
  delegate.should_sample?(trace_id: trace_id, parent_context: parent_context, links: links, name: name, kind: kind, attributes: attributes)
49
57
  end
58
+
59
+ protected
60
+
61
+ attr_reader :root, :remote_parent_sampled, :remote_parent_not_sampled, :local_parent_sampled, :local_parent_not_sampled
50
62
  end
51
63
  end
52
64
  end
@@ -20,6 +20,10 @@ module OpenTelemetry
20
20
  @description = format('TraceIdRatioBased{%.6f}', probability)
21
21
  end
22
22
 
23
+ def ==(other)
24
+ @description == other.description
25
+ end
26
+
23
27
  # @api private
24
28
  #
25
29
  # See {Samplers}.
@@ -120,15 +120,20 @@ module OpenTelemetry
120
120
  # can be recorded on a span.
121
121
  #
122
122
  # @param [Exception] exception The exception to be recorded
123
+ # @param [optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
124
+ # attributes One or more key:value pairs, where the keys must be
125
+ # strings and the values may be (array of) string, boolean or numeric
126
+ # type.
123
127
  #
124
128
  # @return [void]
125
- def record_exception(exception)
126
- add_event('exception',
127
- attributes: {
128
- 'exception.type' => exception.class.to_s,
129
- 'exception.message' => exception.message,
130
- 'exception.stacktrace' => exception.full_message(highlight: false, order: :top)
131
- })
129
+ def record_exception(exception, attributes: nil)
130
+ event_attributes = {
131
+ 'exception.type' => exception.class.to_s,
132
+ 'exception.message' => exception.message,
133
+ 'exception.stacktrace' => exception.full_message(highlight: false, order: :top)
134
+ }
135
+ event_attributes.merge!(attributes) unless attributes.nil?
136
+ add_event('exception', attributes: event_attributes)
132
137
  end
133
138
 
134
139
  # Sets the Status to the Span
@@ -199,7 +204,7 @@ module OpenTelemetry
199
204
  return self
200
205
  end
201
206
  @end_timestamp = end_timestamp || Time.now
202
- @attributes.freeze
207
+ @attributes = validated_attributes(@attributes).freeze
203
208
  @events.freeze
204
209
  @ended = true
205
210
  end
@@ -269,12 +274,16 @@ module OpenTelemetry
269
274
 
270
275
  private
271
276
 
277
+ def validated_attributes(attrs)
278
+ return attrs if Internal.valid_attributes?(attrs)
279
+
280
+ attrs.keep_if { |key, value| Internal.valid_key?(key) && Internal.valid_value?(value) }
281
+ end
282
+
272
283
  def trim_span_attributes(attrs)
273
284
  return if attrs.nil?
274
285
 
275
286
  excess = attrs.size - @trace_config.max_attributes_count
276
- # TODO: with Ruby 2.5, replace with the more efficient
277
- # attrs.shift(excess) if excess.positive?
278
287
  excess.times { attrs.shift } if excess.positive?
279
288
  nil
280
289
  end
@@ -301,11 +310,12 @@ module OpenTelemetry
301
310
  def append_event(events, event) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
302
311
  max_events_count = @trace_config.max_events_count
303
312
  max_attributes_per_event = @trace_config.max_attributes_per_event
313
+ valid_attributes = Internal.valid_attributes?(event.attributes)
304
314
 
305
315
  # Fast path (likely) common case.
306
316
  if events.size < max_events_count &&
307
317
  event.attributes.size <= max_attributes_per_event &&
308
- Internal.valid_attributes?(event.attributes)
318
+ valid_attributes
309
319
  return events << event
310
320
  end
311
321
 
@@ -314,7 +324,7 @@ module OpenTelemetry
314
324
  events.shift(excess) if excess.positive?
315
325
 
316
326
  excess = event.attributes.size - max_attributes_per_event
317
- if excess.positive? || !Internal.valid_attributes?(event.attributes)
327
+ if excess.positive? || !valid_attributes
318
328
  attrs = Hash[event.attributes] # event.attributes is frozen, so we need an unfrozen copy to adjust.
319
329
  attrs.keep_if { |key, value| Internal.valid_key?(key) && Internal.valid_value?(value) }
320
330
  excess = attrs.size - max_attributes_per_event
@@ -42,7 +42,7 @@ module OpenTelemetry
42
42
  parent_span_id = parent_span_context.span_id
43
43
  trace_id = parent_span_context.trace_id
44
44
  end
45
- trace_id ||= OpenTelemetry::Trace.generate_trace_id
45
+ trace_id ||= tracer_provider.id_generator.generate_trace_id
46
46
  sampler = tracer_provider.active_trace_config.sampler
47
47
  result = sampler.should_sample?(trace_id: trace_id, parent_context: with_parent, links: links, name: name, kind: kind, attributes: attributes)
48
48
  internal_create_span(result, name, kind, trace_id, parent_span_id, attributes, links, start_timestamp, with_parent)
@@ -50,10 +50,11 @@ module OpenTelemetry
50
50
 
51
51
  private
52
52
 
53
- def internal_create_span(result, name, kind, trace_id, parent_span_id, attributes, links, start_timestamp, parent_context) # rubocop:disable Metrics/AbcSize
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
54
55
  if result.recording? && !tracer_provider.stopped?
55
56
  trace_flags = result.sampled? ? OpenTelemetry::Trace::TraceFlags::SAMPLED : OpenTelemetry::Trace::TraceFlags::DEFAULT
56
- context = OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id, trace_flags: trace_flags, tracestate: result.tracestate)
57
+ context = OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id, span_id: span_id, trace_flags: trace_flags, tracestate: result.tracestate)
57
58
  attributes = attributes&.merge(result.attributes) || result.attributes
58
59
  Span.new(
59
60
  context,
@@ -70,7 +71,7 @@ module OpenTelemetry
70
71
  @instrumentation_library
71
72
  )
72
73
  else
73
- OpenTelemetry::Trace::Span.new(span_context: OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id))
74
+ OpenTelemetry::Trace::Span.new(span_context: OpenTelemetry::Trace::SpanContext.new(trace_id: trace_id, span_id: span_id, tracestate: result.tracestate))
74
75
  end
75
76
  end
76
77
  end
@@ -12,7 +12,7 @@ module OpenTelemetry
12
12
  Key = Struct.new(:name, :version)
13
13
  private_constant(:Key)
14
14
 
15
- attr_accessor :active_trace_config
15
+ attr_accessor :active_trace_config, :id_generator
16
16
  attr_reader :active_span_processor, :stopped, :resource
17
17
  alias stopped? stopped
18
18
 
@@ -24,6 +24,7 @@ module OpenTelemetry
24
24
  @registry = {}
25
25
  @active_span_processor = NoopSpanProcessor.instance
26
26
  @active_trace_config = Config::TraceConfig::DEFAULT
27
+ @id_generator = OpenTelemetry::Trace
27
28
  @registered_span_processors = []
28
29
  @stopped = false
29
30
  @resource = resource
@@ -7,6 +7,6 @@
7
7
  module OpenTelemetry
8
8
  module SDK
9
9
  ## Current OpenTelemetry version
10
- VERSION = '0.11.1'
10
+ VERSION = '0.14.0'
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: 0.11.1
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenTelemetry Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-16 00:00:00.000000000 Z
11
+ date: 2021-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opentelemetry-api
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.11.0
19
+ version: 0.14.0
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: 0.11.0
26
+ version: 0.14.0
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.11.0
33
+ version: 0.14.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.11.0
40
+ version: 0.14.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -201,10 +201,10 @@ homepage: https://github.com/open-telemetry/opentelemetry-ruby
201
201
  licenses:
202
202
  - Apache-2.0
203
203
  metadata:
204
- changelog_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-sdk/v0.11.1/file.CHANGELOG.html
205
- source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/master/sdk
204
+ changelog_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-sdk/v0.14.0/file.CHANGELOG.html
205
+ source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/main/sdk
206
206
  bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby/issues
207
- documentation_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-sdk/v0.11.1
207
+ documentation_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-sdk/v0.14.0
208
208
  post_install_message:
209
209
  rdoc_options: []
210
210
  require_paths: