opentelemetry-sdk 0.12.1 → 0.16.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: '079e4ea0a93345e6e014c3f7760425e042544ae619cf5761cb08813dac99a728'
4
- data.tar.gz: f36464e88c42bd56a60060854da46daa42b35b720619201ed30e8a038ea567c7
3
+ metadata.gz: 0231dc6f06956325ffb14fc4a209f579001c7cc059659da14d4a4790fd07efeb
4
+ data.tar.gz: 676299747265e10f02eb15ffda455bfcd70155a9969e1f021804fb37c26ba768
5
5
  SHA512:
6
- metadata.gz: 7305bdedc102299c04c3c0798d9137fc74919e4edd3eb37a4b239c739218274427b82f925d97cdcdebd192559033f025a6cad2f729f5d05c5856b6aa6e9e2170
7
- data.tar.gz: efcd32dc9aa6c9e260b05829d790c294308e08bc7ca275647c33f54b03ac463a63da7962a9038917c6fe3571ae10dc61efaa09dfc17eb5bfae4ed040719a8c80
6
+ metadata.gz: ea3a1003fd132137846cbf7957da2524e21dca19d0899c9663cebbc5836bd5ce1adafe4b0ecf8f899600a94701b410534ea1eca56409da9e2dc3de658b0cb4c7
7
+ data.tar.gz: ee4b4487c397cee00f0d40854c3c19b7e405bfff70f145ee8520f1ceb924ac7a99cb8b15a43af30c826f59d08028345ab62535d5fef0164c89e43bd6b221d43c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,51 @@
1
1
  # Release History: opentelemetry-sdk
2
2
 
3
+ ### v0.16.0 / 2021-03-17
4
+
5
+ * BREAKING CHANGE: Update SDK BaggageManager to match API
6
+ * BREAKING CHANGE: Implement Exporter#force_flush
7
+
8
+ * ADDED: Add force_flush to SDK's TracerProvider
9
+ * ADDED: Add k8s node to gcp resource detector
10
+ * ADDED: Add console option for OTEL_TRACES_EXPORTER
11
+ * ADDED: Span#add_attributes
12
+ * ADDED: Implement Exporter#force_flush
13
+ * FIXED: Update SDK BaggageManager to match API
14
+ * DOCS: Replace Gitter with GitHub Discussions
15
+
16
+ ### v0.15.0 / 2021-02-18
17
+
18
+ * BREAKING CHANGE: Streamline processor pipeline
19
+
20
+ * ADDED: Add instrumentation config validation
21
+ * FIXED: Streamline processor pipeline
22
+ * FIXED: OTEL_TRACE -> OTEL_TRACES env vars
23
+ * FIXED: Change limits from 1000 to 128
24
+ * FIXED: OTEL_TRACES_EXPORTER and OTEL_PROPAGATORS
25
+ * FIXED: Add thread error handling to the BSP
26
+ * DOCS: Clarify nil attribute values not allowed
27
+
28
+ ### v0.14.0 / 2021-02-03
29
+
30
+ * BREAKING CHANGE: Replace getter and setter callables and remove rack specific propagators
31
+
32
+ * ADDED: Replace getter and setter callables and remove rack specific propagators
33
+
34
+ ### v0.13.1 / 2021-02-01
35
+
36
+ * FIXED: Leaky test
37
+ * FIXED: Allow env var override of service.name
38
+
39
+ ### v0.13.0 / 2021-01-29
40
+
41
+ * BREAKING CHANGE: Remove MILLIS from BatchSpanProcessor vars
42
+
43
+ * ADDED: Process.runtime resource
44
+ * ADDED: Provide default resource in SDK
45
+ * ADDED: Add optional attributes to record_exception
46
+ * FIXED: Resource.merge consistency
47
+ * FIXED: Remove MILLIS from BatchSpanProcessor vars
48
+
3
49
  ### v0.12.1 / 2021-01-13
4
50
 
5
51
  * FIXED: Fix several BatchSpanProcessor errors related to fork safety
data/README.md CHANGED
@@ -56,7 +56,7 @@ For additional examples, see the [examples on github][examples-github].
56
56
 
57
57
  The `opentelemetry-sdk` gem source is [on github][repo-github], along with related gems including `opentelemetry-api`.
58
58
 
59
- The OpenTelemetry Ruby gems are maintained by the OpenTelemetry-Ruby special interest group (SIG). You can get involved by joining us on our [gitter channel][ruby-gitter] or attending our weekly meeting. See the [meeting calendar][community-meetings] for dates and times. For more information on this and other language SIGs, see the OpenTelemetry [community page][ruby-sig].
59
+ The OpenTelemetry Ruby gems are maintained by the OpenTelemetry-Ruby special interest group (SIG). You can get involved by joining us in [GitHub Discussions][discussions-url] or attending our weekly meeting. See the [meeting calendar][community-meetings] for dates and times. For more information on this and other language SIGs, see the OpenTelemetry [community page][ruby-sig].
60
60
 
61
61
  ## License
62
62
 
@@ -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
- [ruby-gitter]: https://gitter.im/open-telemetry/opentelemetry-ruby
73
+ [discussions-url]: https://github.com/open-telemetry/opentelemetry-ruby/discussions
@@ -22,7 +22,7 @@ module OpenTelemetry
22
22
  # @param [optional Context] context The context to update with with new
23
23
  # modified baggage. Defaults to +Context.current+
24
24
  # @return [Context]
25
- def build_context(context: Context.current)
25
+ def build(context: Context.current)
26
26
  builder = Builder.new(baggage_for(context).dup)
27
27
  yield builder
28
28
  context.set_value(BAGGAGE_KEY, builder.entries)
@@ -15,19 +15,17 @@ 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, :error_handler, :id_generator
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
31
29
  @id_generator = OpenTelemetry::Trace
32
30
  end
33
31
 
@@ -46,7 +44,7 @@ module OpenTelemetry
46
44
  #
47
45
  # @param [Resource] new_resource The resource to be merged
48
46
  def resource=(new_resource)
49
- @resource = new_resource.merge(@resource)
47
+ @resource = @resource.merge(new_resource)
50
48
  end
51
49
 
52
50
  # Accepts a string that is merged in as the service.name resource attribute.
@@ -54,9 +52,9 @@ module OpenTelemetry
54
52
  # calls to this setter.
55
53
  # @param [String] service_name The value to be used as the service name
56
54
  def service_name=(service_name)
57
- @resource = OpenTelemetry::SDK::Resources::Resource.create(
55
+ self.resource = OpenTelemetry::SDK::Resources::Resource.create(
58
56
  OpenTelemetry::SDK::Resources::Constants::SERVICE_RESOURCE[:name] => service_name
59
- ).merge(@resource)
57
+ )
60
58
  end
61
59
 
62
60
  # Accepts a string that is merged in as the service.version resource attribute.
@@ -64,9 +62,9 @@ module OpenTelemetry
64
62
  # calls to this setter.
65
63
  # @param [String] service_version The value to be used as the service version
66
64
  def service_version=(service_version)
67
- @resource = OpenTelemetry::SDK::Resources::Resource.create(
65
+ self.resource = OpenTelemetry::SDK::Resources::Resource.create(
68
66
  OpenTelemetry::SDK::Resources::Constants::SERVICE_RESOURCE[:version] => service_version
69
- ).merge(@resource)
67
+ )
70
68
  end
71
69
 
72
70
  # Install an instrumentation with specificied optional +config+.
@@ -145,54 +143,67 @@ module OpenTelemetry
145
143
  end
146
144
 
147
145
  def configure_span_processors
148
- processors = @span_processors.empty? ? [default_span_processor] : @span_processors
146
+ processors = @span_processors.empty? ? [wrapped_exporter_from_env].compact : @span_processors
149
147
  processors.each { |p| tracer_provider.add_span_processor(p) }
150
148
  end
151
149
 
152
- def default_span_processor
153
- Trace::Export::SimpleSpanProcessor.new(
154
- Trace::Export::ConsoleSpanExporter.new
155
- )
150
+ def wrapped_exporter_from_env
151
+ exporter = ENV.fetch('OTEL_TRACES_EXPORTER', 'otlp')
152
+ case exporter
153
+ when 'none' then nil
154
+ when 'otlp' then fetch_exporter(exporter, 'OpenTelemetry::Exporter::OTLP::Exporter')
155
+ when 'jaeger' then fetch_exporter(exporter, 'OpenTelemetry::Exporter::Jaeger::CollectorExporter')
156
+ when 'zipkin' then fetch_exporter(exporter, 'OpenTelemetry::Exporter::Zipkin::Exporter')
157
+ when 'console' then Trace::Export::SimpleSpanProcessor.new(Trace::Export::ConsoleSpanExporter.new)
158
+ else
159
+ OpenTelemetry.logger.warn "The #{exporter} exporter is unknown and cannot be configured, spans will not be exported"
160
+ nil
161
+ end
156
162
  end
157
163
 
158
- def configure_propagation
159
- OpenTelemetry.propagation.http = create_propagator(@http_injectors || default_http_injectors,
160
- @http_extractors || default_http_extractors)
161
- OpenTelemetry.propagation.text = create_propagator(@text_map_injectors || default_text_map_injectors,
162
- @text_map_extractors || default_text_map_extractors)
164
+ def configure_propagation # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
165
+ propagators = ENV.fetch('OTEL_PROPAGATORS', 'tracecontext,baggage').split(',')
166
+ injectors, extractors = propagators.uniq.collect do |propagator|
167
+ case propagator
168
+ when 'tracecontext'
169
+ [OpenTelemetry::Trace::Propagation::TraceContext.text_map_injector, OpenTelemetry::Trace::Propagation::TraceContext.text_map_extractor]
170
+ when 'baggage'
171
+ [OpenTelemetry::Baggage::Propagation.text_map_injector, OpenTelemetry::Baggage::Propagation.text_map_extractor]
172
+ when 'b3' then fetch_propagator(propagator, 'OpenTelemetry::Propagator::B3::Single')
173
+ when 'b3multi' then fetch_propagator(propagator, 'OpenTelemetry::Propagator::B3::Multi', 'b3')
174
+ when 'jaeger' then fetch_propagator(propagator, 'OpenTelemetry::Propagator::Jaeger')
175
+ when 'xray' then fetch_propagator(propagator, 'OpenTelemetry::Propagator::XRay')
176
+ when 'ottrace' then fetch_propagator(propagator, 'OpenTelemetry::Propagator::OTTrace')
177
+ else
178
+ OpenTelemetry.logger.warn "The #{propagator} propagator is unknown and cannot be configured"
179
+ [Context::Propagation::NoopInjector.new, Context::Propagation::NoopExtractor.new]
180
+ end
181
+ end.transpose
182
+ OpenTelemetry.propagation = create_propagator(@injectors || injectors.compact,
183
+ @extractors || extractors.compact)
163
184
  end
164
185
 
165
186
  def create_propagator(injectors, extractors)
166
187
  if injectors.size > 1 || extractors.size > 1
167
188
  Context::Propagation::CompositePropagator.new(injectors, extractors)
168
189
  else
169
- Context::Propagation::Propagator.new(injectors, extractors)
190
+ Context::Propagation::Propagator.new(injectors.first, extractors.first)
170
191
  end
171
192
  end
172
193
 
173
- def default_http_injectors
174
- default_text_map_injectors
175
- end
176
-
177
- def default_http_extractors
178
- [
179
- OpenTelemetry::Trace::Propagation::TraceContext.rack_extractor,
180
- OpenTelemetry::Baggage::Propagation.rack_extractor
181
- ]
182
- end
183
-
184
- def default_text_map_injectors
185
- [
186
- OpenTelemetry::Trace::Propagation::TraceContext.text_map_injector,
187
- OpenTelemetry::Baggage::Propagation.text_map_injector
188
- ]
194
+ def fetch_propagator(name, class_name, gem_suffix = name)
195
+ propagator_class = Kernel.const_get(class_name)
196
+ [propagator_class.text_map_injector, propagator_class.text_map_extractor]
197
+ rescue NameError
198
+ OpenTelemetry.logger.warn "The #{name} propagator cannot be configured - please add opentelemetry-propagator-#{gem_suffix} to your Gemfile"
199
+ [nil, nil]
189
200
  end
190
201
 
191
- def default_text_map_extractors
192
- [
193
- OpenTelemetry::Trace::Propagation::TraceContext.text_map_extractor,
194
- OpenTelemetry::Baggage::Propagation.text_map_extractor
195
- ]
202
+ def fetch_exporter(name, class_name)
203
+ Trace::Export::BatchSpanProcessor.new(Kernel.const_get(class_name).new)
204
+ rescue NameError
205
+ OpenTelemetry.logger.warn "The #{name} exporter cannot be configured - please add opentelemetry-exporter-#{name} to your Gemfile, spans will not be exported"
206
+ nil
196
207
  end
197
208
  end
198
209
  end
@@ -67,14 +67,99 @@ module OpenTelemetry
67
67
  # The name of the cluster that the pod is running in.
68
68
  cluster_name: 'k8s.cluster.name',
69
69
 
70
+ # The name of the Node.
71
+ node_name: 'k8s.node.name',
72
+
73
+ # The UID of the Node.
74
+ node_uid: 'k8s.node.uid',
75
+
70
76
  # The name of the namespace that the pod is running in.
71
77
  namespace_name: 'k8s.namespace.name',
72
78
 
73
79
  # The name of the pod.
74
80
  pod_name: 'k8s.pod.name',
75
81
 
82
+ # The UID of the Pod.
83
+ pod_uid: 'k8s.pod.uid',
84
+
85
+ # The name of the Container in a Pod template.
86
+ container_name: 'k8s.container.name',
87
+
88
+ # The UID of the ReplicaSet.
89
+ replicaset_uid: 'k8s.replicaset.uid',
90
+
91
+ # The name of the ReplicaSet.
92
+ replicaset_name: 'k8s.replicaset.name',
93
+
94
+ # The UID of the Deployment.
95
+ deployment_uid: 'k8s.deployment.uid',
96
+
76
97
  # The name of the deployment.
77
- deployment_name: 'k8s.deployment.name'
98
+ deployment_name: 'k8s.deployment.name',
99
+
100
+ # The UID of the StatefulSet.
101
+ statefulset_uid: 'k8s.statefulset.uid',
102
+
103
+ # The name of the StatefulSet.
104
+ statefulset_name: 'k8s.statefulset.name',
105
+
106
+ # The UID of the DaemonSet.
107
+ daemonset_uid: 'k8s.daemonset.uid',
108
+
109
+ # The name of the DaemonSet.
110
+ daemonset_name: 'k8s.daemonset.name',
111
+
112
+ # The UID of the Job.
113
+ job_uid: 'k8s.job.uid',
114
+
115
+ # The name of the Job.
116
+ job_name: 'k8s.job.name',
117
+
118
+ # The UID of the CronJob.
119
+ cronjob_uid: 'k8s.cronjob.uid',
120
+
121
+ # The name of the CronJob.
122
+ cronjob_name: 'k8s.cronjob.name'
123
+ }.freeze
124
+
125
+ # Attributes defining an operating system process.
126
+ PROCESS_RESOURCE = {
127
+ # Process identifier (PID).
128
+ pid: 'process.pid',
129
+
130
+ # The name of the process executable.
131
+ executable_name: 'process.executable.name',
132
+
133
+ # The full path to the process executable.
134
+ executable_path: 'process.executable.path',
135
+
136
+ # The command used to launch the process (i.e. the command name).
137
+ command: 'process.command',
138
+
139
+ # The full command used to launch the process as a single string
140
+ # representing the full command.
141
+ command_line: 'process.command_line',
142
+
143
+ # All the command arguments (including the command/executable itself)
144
+ # as received by the process.
145
+ command_args: 'process.command_args',
146
+
147
+ # The username of the user that owns the process.
148
+ owner: 'process.owner'
149
+ }.freeze
150
+
151
+ # Attributes defining the single (language) runtime instance which is monitored.
152
+ PROCESS_RUNTIME_RESOURCE = {
153
+ # The name of the runtime of this process.
154
+ name: 'process.runtime.name',
155
+
156
+ # The version of the runtime of this process, as returned by the runtime
157
+ # without modification.
158
+ version: 'process.runtime.version',
159
+
160
+ # An additional description about the runtime of the process, for example
161
+ # a specific vendor customization of the runtime environment.
162
+ description: 'process.runtime.description'
78
163
  }.freeze
79
164
 
80
165
  # Attributes defining a computing instance (e.g. host).
@@ -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
@@ -33,9 +33,9 @@ module OpenTelemetry
33
33
  # @return [TraceConfig] with the desired values.
34
34
  # @raise [ArgumentError] if any of the max numbers are not positive.
35
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)),
36
+ max_attributes_count: Integer(ENV.fetch('OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT', 128)),
37
+ max_events_count: Integer(ENV.fetch('OTEL_SPAN_EVENT_COUNT_LIMIT', 128)),
38
+ max_links_count: Integer(ENV.fetch('OTEL_SPAN_LINK_COUNT_LIMIT', 128)),
39
39
  max_attributes_per_event: max_attributes_count,
40
40
  max_attributes_per_link: max_attributes_count)
41
41
  raise ArgumentError, 'max_attributes_count must be positive' unless max_attributes_count.positive?
@@ -56,13 +56,13 @@ module OpenTelemetry
56
56
  private
57
57
 
58
58
  def sampler_from_environment(default_sampler) # rubocop:disable Metrics/CyclomaticComplexity
59
- case ENV['OTEL_TRACE_SAMPLER']
59
+ case ENV['OTEL_TRACES_SAMPLER']
60
60
  when 'always_on' then Samplers::ALWAYS_ON
61
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)))
62
+ when 'traceidratio' then Samplers.trace_id_ratio_based(Float(ENV.fetch('OTEL_TRACES_SAMPLER_ARG', 1.0)))
63
63
  when 'parentbased_always_on' then Samplers.parent_based(root: Samplers::ALWAYS_ON)
64
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))))
65
+ when 'parentbased_traceidratio' then Samplers.parent_based(root: Samplers.trace_id_ratio_based(Float(ENV.fetch('OTEL_TRACES_SAMPLER_ARG', 1.0))))
66
66
  else default_sampler
67
67
  end
68
68
  rescue StandardError => e
@@ -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
@@ -28,12 +28,13 @@ module OpenTelemetry
28
28
  class BatchSpanProcessor # rubocop:disable Metrics/ClassLength
29
29
  # Returns a new instance of the {BatchSpanProcessor}.
30
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
31
+ # @param [SpanExporter] exporter the (duck type) SpanExporter to where the
32
+ # recorded Spans are pushed after batching.
33
+ # @param [Numeric] exporter_timeout the delay interval between two
34
+ # consecutive exports. Defaults to the value of the OTEL_BSP_EXPORT_TIMEOUT
34
35
  # 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
36
+ # @param [Numeric] schedule_delay the maximum allowed time to export data.
37
+ # Defaults to the value of the OTEL_BSP_SCHEDULE_DELAY environment
37
38
  # variable, if set, or 5,000 (5 seconds).
38
39
  # @param [Integer] max_queue_size the maximum queue size in spans.
39
40
  # Defaults to the value of the OTEL_BSP_MAX_QUEUE_SIZE environment
@@ -43,9 +44,9 @@ module OpenTelemetry
43
44
  # variable, if set, or 512.
44
45
  #
45
46
  # @return a new instance of the {BatchSpanProcessor}.
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
+ def initialize(exporter,
48
+ exporter_timeout: Float(ENV.fetch('OTEL_BSP_EXPORT_TIMEOUT', 30_000)),
49
+ schedule_delay: Float(ENV.fetch('OTEL_BSP_SCHEDULE_DELAY', 5_000)),
49
50
  max_queue_size: Integer(ENV.fetch('OTEL_BSP_MAX_QUEUE_SIZE', 2048)),
50
51
  max_export_batch_size: Integer(ENV.fetch('OTEL_BSP_MAX_EXPORT_BATCH_SIZE', 512)),
51
52
  start_thread_on_boot: String(ENV['OTEL_RUBY_BSP_START_THREAD_ON_BOOT']) !~ /false/i,
@@ -53,12 +54,12 @@ module OpenTelemetry
53
54
  raise ArgumentError if max_export_batch_size > max_queue_size
54
55
 
55
56
  @exporter = exporter
56
- @exporter_timeout_seconds = exporter_timeout_millis / 1000.0
57
+ @exporter_timeout_seconds = exporter_timeout / 1000.0
57
58
  @mutex = Mutex.new
58
59
  @export_mutex = Mutex.new
59
60
  @condition = ConditionVariable.new
60
61
  @keep_running = true
61
- @delay_seconds = schedule_delay_millis / 1000.0
62
+ @delay_seconds = schedule_delay / 1000.0
62
63
  @max_queue_size = max_queue_size
63
64
  @batch_size = max_export_batch_size
64
65
  @metrics_reporter = metrics_reporter || OpenTelemetry::SDK::Trace::Export::MetricsReporter
@@ -113,7 +114,7 @@ module OpenTelemetry
113
114
  return result_code unless result_code == SUCCESS
114
115
  end
115
116
 
116
- SUCCESS
117
+ @exporter.force_flush(timeout: OpenTelemetry::Common::Utilities.maybe_timeout(timeout, start_time))
117
118
  ensure
118
119
  # Unshift the remaining spans if we timed out. We drop excess spans from
119
120
  # the snapshot because they're older than any spans in the spans buffer.
@@ -176,6 +177,9 @@ module OpenTelemetry
176
177
  @pid = pid
177
178
  spans.clear
178
179
  @thread = restart_thread ? Thread.new { work } : nil
180
+ rescue ThreadError => e
181
+ @metrics_reporter.add_to_counter('otel.bsp.error', labels: { 'reason' => 'ThreadError' })
182
+ OpenTelemetry.handle_error(exception: e, message: 'unexpected error in BatchSpanProcessor#reset_on_fork')
179
183
  end
180
184
 
181
185
  def export_batch(batch, timeout: @exporter_timeout_seconds)
@@ -26,6 +26,10 @@ module OpenTelemetry
26
26
  SUCCESS
27
27
  end
28
28
 
29
+ def force_flush(timeout: nil)
30
+ SUCCESS
31
+ end
32
+
29
33
  def shutdown(timeout: nil)
30
34
  @stopped = true
31
35
  SUCCESS
@@ -72,6 +72,16 @@ module OpenTelemetry
72
72
  SUCCESS
73
73
  end
74
74
 
75
+ # Called when {TracerProvider#force_flush} is called, if this exporter is
76
+ # registered to a {TracerProvider} object.
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 force_flush(timeout: nil)
82
+ SUCCESS
83
+ end
84
+
75
85
  # Called when {TracerProvider#shutdown} is called, if this exporter is
76
86
  # registered to a {TracerProvider} object.
77
87
  #
@@ -36,6 +36,23 @@ module OpenTelemetry
36
36
  results.uniq.max || SUCCESS
37
37
  end
38
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 = 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?
50
+
51
+ processor.force_flush(timeout: remaining_timeout)
52
+ end
53
+ results.uniq.max || SUCCESS
54
+ end
55
+
39
56
  # Called when {TracerProvider#shutdown} is called, if this exporter is
40
57
  # registered to a {TracerProvider} object.
41
58
  #
@@ -31,6 +31,16 @@ module OpenTelemetry
31
31
  FAILURE
32
32
  end
33
33
 
34
+ # Called when {TracerProvider#force_flush} is called, if this exporter is
35
+ # registered to a {TracerProvider} object.
36
+ #
37
+ # @param [optional Numeric] timeout An optional timeout in seconds.
38
+ # @return [Integer] SUCCESS if no error occurred, FAILURE if a
39
+ # non-specific failure occurred, TIMEOUT if a timeout occurred.
40
+ def force_flush(timeout: nil)
41
+ SUCCESS
42
+ end
43
+
34
44
  # Called when {TracerProvider#shutdown} is called, if this exporter is
35
45
  # registered to a {TracerProvider} object.
36
46
  #
@@ -61,7 +61,7 @@ module OpenTelemetry
61
61
  end
62
62
 
63
63
  # Export all ended spans to the configured `Exporter` that have not yet
64
- # been exported.
64
+ # been exported, then call {Exporter#force_flush}.
65
65
  #
66
66
  # This method should only be called in cases where it is absolutely
67
67
  # necessary, such as when using some FaaS providers that may suspend
@@ -72,7 +72,7 @@ module OpenTelemetry
72
72
  # @return [Integer] SUCCESS if no error occurred, FAILURE if a
73
73
  # non-specific failure occurred, TIMEOUT if a timeout occurred.
74
74
  def force_flush(timeout: nil)
75
- SUCCESS
75
+ @span_exporter&.force_flush(timeout: timeout) || SUCCESS
76
76
  end
77
77
 
78
78
  # Called when {TracerProvider#shutdown} is called.
@@ -64,6 +64,9 @@ module OpenTelemetry
64
64
  #
65
65
  # @param [String] key
66
66
  # @param [String, Boolean, Numeric, Array<String, Numeric, Boolean>] value
67
+ # Values must be non-nil and (array of) string, boolean or numeric type.
68
+ # Array values must not contain nil elements and all elements must be of
69
+ # the same basic type (string, numeric, boolean).
67
70
  #
68
71
  # @return [self] returns itself
69
72
  def set_attribute(key, value)
@@ -82,6 +85,34 @@ module OpenTelemetry
82
85
  end
83
86
  alias []= set_attribute
84
87
 
88
+ # Add attributes
89
+ #
90
+ # Note that the OpenTelemetry project
91
+ # {https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-semantic-conventions.md
92
+ # documents} certain "standard attributes" that have prescribed semantic
93
+ # meanings.
94
+ #
95
+ # @param [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}] attributes
96
+ # Values must be non-nil and (array of) string, boolean or numeric type.
97
+ # Array values must not contain nil elements and all elements must be of
98
+ # the same basic type (string, numeric, boolean).
99
+ #
100
+ # @return [self] returns itself
101
+ def add_attributes(attributes)
102
+ super
103
+ @mutex.synchronize do
104
+ if @ended
105
+ OpenTelemetry.logger.warn('Calling add_attributes on an ended Span.')
106
+ else
107
+ @attributes ||= {}
108
+ @attributes.merge!(attributes)
109
+ trim_span_attributes(@attributes)
110
+ @total_recorded_attributes += attributes.size
111
+ end
112
+ end
113
+ self
114
+ end
115
+
85
116
  # Add an Event to a {Span}.
86
117
  #
87
118
  # Example:
@@ -96,7 +127,7 @@ module OpenTelemetry
96
127
  # @param [String] name Name of the event.
97
128
  # @param [optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}] attributes
98
129
  # One or more key:value pairs, where the keys must be strings and the
99
- # values may be string, boolean or numeric type.
130
+ # values may be (array of) string, boolean or numeric type.
100
131
  # @param [optional Time] timestamp Optional timestamp for the event.
101
132
  #
102
133
  # @return [self] returns itself
@@ -120,15 +151,20 @@ module OpenTelemetry
120
151
  # can be recorded on a span.
121
152
  #
122
153
  # @param [Exception] exception The exception to be recorded
154
+ # @param [optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
155
+ # attributes One or more key:value pairs, where the keys must be
156
+ # strings and the values may be (array of) string, boolean or numeric
157
+ # type.
123
158
  #
124
159
  # @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
- })
160
+ def record_exception(exception, attributes: nil)
161
+ event_attributes = {
162
+ 'exception.type' => exception.class.to_s,
163
+ 'exception.message' => exception.message,
164
+ 'exception.stacktrace' => exception.full_message(highlight: false, order: :top)
165
+ }
166
+ event_attributes.merge!(attributes) unless attributes.nil?
167
+ add_event('exception', attributes: event_attributes)
132
168
  end
133
169
 
134
170
  # Sets the Status to the Span
@@ -42,7 +42,7 @@ module OpenTelemetry
42
42
  @mutex.synchronize { @registry[Key.new(name, version)] ||= Tracer.new(name, version, self) }
43
43
  end
44
44
 
45
- # Attempts to stop all the activity for this {Tracer}. Calls
45
+ # Attempts to stop all the activity for this {TracerProvider}. Calls
46
46
  # SpanProcessor#shutdown for all registered SpanProcessors.
47
47
  #
48
48
  # This operation may block until all the Spans are processed. Must be
@@ -63,12 +63,26 @@ module OpenTelemetry
63
63
  end
64
64
  end
65
65
 
66
- # Adds a new SpanProcessor to this {Tracer}.
66
+ # Immediately export all spans that have not yet been exported for all the
67
+ # registered SpanProcessors.
68
+ #
69
+ # This method should only be called in cases where it is absolutely
70
+ # necessary, such as when using some FaaS providers that may suspend
71
+ # the process after an invocation, but before the `Processor` exports
72
+ # the completed spans.
67
73
  #
68
- # Any registered processor causes overhead, consider to use an
69
- # async/batch processor especially for span exporting, and export to
70
- # multiple backends using the
71
- # {io.opentelemetry.sdk.trace.export.MultiSpanExporter}.
74
+ # @param [optional Numeric] timeout An optional timeout in seconds.
75
+ # @return [Integer] Export::SUCCESS if no error occurred, Export::FAILURE if
76
+ # a non-specific failure occurred, Export::TIMEOUT if a timeout occurred.
77
+ def force_flush(timeout: nil)
78
+ @mutex.synchronize do
79
+ return Export::SUCCESS if @stopped
80
+
81
+ @active_span_processor.force_flush(timeout: timeout)
82
+ end
83
+ end
84
+
85
+ # Adds a new SpanProcessor to this {Tracer}.
72
86
  #
73
87
  # @param span_processor the new SpanProcessor to be added.
74
88
  def add_span_processor(span_processor)
@@ -78,7 +92,11 @@ module OpenTelemetry
78
92
  return
79
93
  end
80
94
  @registered_span_processors << span_processor
81
- @active_span_processor = MultiSpanProcessor.new(@registered_span_processors.dup)
95
+ @active_span_processor = if @registered_span_processors.size == 1
96
+ span_processor
97
+ else
98
+ MultiSpanProcessor.new(@registered_span_processors.dup)
99
+ end
82
100
  end
83
101
  end
84
102
  end
@@ -7,6 +7,6 @@
7
7
  module OpenTelemetry
8
8
  module SDK
9
9
  ## Current OpenTelemetry version
10
- VERSION = '0.12.1'
10
+ VERSION = '0.16.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.12.1
4
+ version: 0.16.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: 2021-01-13 00:00:00.000000000 Z
11
+ date: 2021-03-22 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.12.0
19
+ version: 0.16.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.12.0
26
+ version: 0.16.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.12.0
33
+ version: 0.16.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.12.0
40
+ version: 0.16.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '5.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: opentelemetry-exporter-jaeger
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.16.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.16.0
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rake
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -201,10 +215,10 @@ homepage: https://github.com/open-telemetry/opentelemetry-ruby
201
215
  licenses:
202
216
  - Apache-2.0
203
217
  metadata:
204
- changelog_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-sdk/v0.12.1/file.CHANGELOG.html
205
- source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/master/sdk
218
+ changelog_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-sdk/v0.16.0/file.CHANGELOG.html
219
+ source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/main/sdk
206
220
  bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby/issues
207
- documentation_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-sdk/v0.12.1
221
+ documentation_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-sdk/v0.16.0
208
222
  post_install_message:
209
223
  rdoc_options: []
210
224
  require_paths: