opentelemetry-api 0.16.0 → 1.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +57 -0
  3. data/README.md +3 -3
  4. data/lib/opentelemetry.rb +21 -28
  5. data/lib/opentelemetry/baggage.rb +95 -2
  6. data/lib/opentelemetry/baggage/builder.rb +30 -4
  7. data/lib/opentelemetry/baggage/entry.rb +20 -0
  8. data/lib/opentelemetry/baggage/propagation.rb +9 -18
  9. data/lib/opentelemetry/baggage/propagation/text_map_propagator.rb +111 -0
  10. data/lib/opentelemetry/context.rb +48 -33
  11. data/lib/opentelemetry/context/propagation.rb +35 -5
  12. data/lib/opentelemetry/context/propagation/composite_text_map_propagator.rb +105 -0
  13. data/lib/opentelemetry/context/propagation/noop_text_map_propagator.rb +27 -0
  14. data/lib/opentelemetry/context/propagation/{propagator.rb → text_map_propagator.rb} +23 -16
  15. data/lib/opentelemetry/internal.rb +17 -0
  16. data/lib/opentelemetry/internal/proxy_tracer.rb +38 -0
  17. data/lib/opentelemetry/internal/proxy_tracer_provider.rb +59 -0
  18. data/lib/opentelemetry/trace.rb +10 -0
  19. data/lib/opentelemetry/trace/propagation/trace_context.rb +7 -18
  20. data/lib/opentelemetry/trace/propagation/trace_context/text_map_propagator.rb +73 -0
  21. data/lib/opentelemetry/trace/status.rb +34 -5
  22. data/lib/opentelemetry/trace/tracer.rb +8 -9
  23. data/lib/opentelemetry/version.rb +1 -1
  24. metadata +16 -25
  25. data/lib/opentelemetry/baggage/manager.rb +0 -41
  26. data/lib/opentelemetry/baggage/propagation/text_map_extractor.rb +0 -57
  27. data/lib/opentelemetry/baggage/propagation/text_map_injector.rb +0 -52
  28. data/lib/opentelemetry/context/propagation/composite_propagator.rb +0 -72
  29. data/lib/opentelemetry/context/propagation/noop_extractor.rb +0 -26
  30. data/lib/opentelemetry/context/propagation/noop_injector.rb +0 -26
  31. data/lib/opentelemetry/instrumentation.rb +0 -15
  32. data/lib/opentelemetry/instrumentation/base.rb +0 -307
  33. data/lib/opentelemetry/instrumentation/registry.rb +0 -86
  34. data/lib/opentelemetry/metrics.rb +0 -16
  35. data/lib/opentelemetry/metrics/handles.rb +0 -44
  36. data/lib/opentelemetry/metrics/instruments.rb +0 -105
  37. data/lib/opentelemetry/metrics/meter.rb +0 -72
  38. data/lib/opentelemetry/metrics/meter_provider.rb +0 -22
  39. data/lib/opentelemetry/trace/propagation/trace_context/text_map_extractor.rb +0 -52
  40. data/lib/opentelemetry/trace/propagation/trace_context/text_map_injector.rb +0 -49
  41. data/lib/opentelemetry/trace/util/http_to_status.rb +0 -28
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright The OpenTelemetry Authors
4
- #
5
- # SPDX-License-Identifier: Apache-2.0
6
-
7
- require 'cgi'
8
-
9
- module OpenTelemetry
10
- module Baggage
11
- module Propagation
12
- # Injects baggage using the W3C Baggage format
13
- class TextMapInjector
14
- # Returns a new TextMapInjector that injects context using the specified
15
- # setter
16
- #
17
- # @param [optional Setter] default_setter The default setter used to
18
- # write context into a carrier during inject. Defaults to a
19
- # {OpenTelemetry::Context::Propagation::TextMapSetter} instance.
20
- # @return [TextMapInjector]
21
- def initialize(default_setter = Context::Propagation.text_map_setter)
22
- @default_setter = default_setter
23
- end
24
-
25
- # Inject in-process baggage into the supplied carrier.
26
- #
27
- # @param [Carrier] carrier The carrier to inject baggage into
28
- # @param [Context] context The context to read baggage from
29
- # @param [optional Setter] setter If the optional setter is provided, it
30
- # will be used to write context into the carrier, otherwise the default
31
- # setter will be used.
32
- # @return [Object] carrier with injected baggage
33
- def inject(carrier, context, setter = nil)
34
- return carrier unless (baggage = context[ContextKeys.baggage_key]) && !baggage.empty?
35
-
36
- setter ||= @default_setter
37
- setter.set(carrier, BAGGAGE_KEY, encode(baggage))
38
-
39
- carrier
40
- end
41
-
42
- private
43
-
44
- def encode(baggage)
45
- baggage.inject(+'') do |memo, (k, v)|
46
- memo << CGI.escape(k.to_s) << '=' << CGI.escape(v.to_s) << ','
47
- end.chop!
48
- end
49
- end
50
- end
51
- end
52
- end
@@ -1,72 +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
- class Context
9
- module Propagation
10
- # A composite propagator composes a list of injectors and extractors into
11
- # single interface exposing inject and extract methods. Injection and
12
- # extraction will preserve the order of the injectors and extractors
13
- # passed in during initialization.
14
- class CompositePropagator
15
- # Returns a Propagator that extracts using the provided extractors
16
- # and injectors.
17
- #
18
- # @param [Array<#inject>] injectors
19
- # @param [Array<#extract>] extractors
20
- def initialize(injectors, extractors)
21
- @injectors = injectors
22
- @extractors = extractors
23
- end
24
-
25
- # Runs injectors in order and returns a carrier. If an injection fails
26
- # a warning will be logged and remaining injectors will be executed.
27
- # Always returns a valid carrier.
28
- #
29
- # @param [Object] carrier A carrier to inject context into
30
- # context into
31
- # @param [optional Context] context Context to be injected into carrier.
32
- # Defaults to +Context.current+
33
- # @param [optional Setter] setter If the optional setter is provided, it
34
- # will be used to write context into the carrier, otherwise the default
35
- # setter will be used.
36
- #
37
- # @return [Object] carrier
38
- def inject(carrier, context: Context.current, setter: Context::Propagation.text_map_setter)
39
- @injectors.inject(carrier) do |memo, injector|
40
- injector.inject(memo, context, setter)
41
- rescue => e # rubocop:disable Style/RescueStandardError
42
- OpenTelemetry.logger.warn "Error in CompositePropagator#inject #{e.message}"
43
- carrier
44
- end
45
- end
46
-
47
- # Runs extractors in order and returns a Context updated with the
48
- # results of each extraction. If an extraction fails, a warning will be
49
- # logged and remaining extractors will continue to be executed. Always
50
- # returns a valid context.
51
- #
52
- # @param [Object] carrier The carrier to extract context from
53
- # @param [optional Context] context Context to be updated with the state
54
- # extracted from the carrier. Defaults to +Context.current+
55
- # @param [optional Getter] getter If the optional getter is provided, it
56
- # will be used to read the header from the carrier, otherwise the default
57
- # getter will be used.
58
- #
59
- # @return [Context] a new context updated with state extracted from the
60
- # carrier
61
- def extract(carrier, context: Context.current, getter: Context::Propagation.text_map_getter)
62
- @extractors.inject(context) do |ctx, extractor|
63
- extractor.extract(carrier, ctx, getter)
64
- rescue => e # rubocop:disable Style/RescueStandardError
65
- OpenTelemetry.logger.warn "Error in CompositePropagator#extract #{e.message}"
66
- ctx
67
- end
68
- end
69
- end
70
- end
71
- end
72
- end
@@ -1,26 +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
- class Context
9
- module Propagation
10
- # A no-op extractor implementation
11
- class NoopExtractor
12
- # Extract a context from the given carrier
13
- #
14
- # @param [Object] carrier The carrier to extract the context from
15
- # @param [Context] context The context to be upated with the extracted
16
- # context
17
- # @param [optional Callable] getter An optional callable that takes a carrier and a key and
18
- # and returns the value associated with the key
19
- # @return [Context]
20
- def extract(carrier, context, getter = nil)
21
- context
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,26 +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
- class Context
9
- module Propagation
10
- # A no-op injector implementation
11
- class NoopInjector
12
- # Inject the given context into the specified carrier
13
- #
14
- # @param [Object] carrier The carrier to inject the provided context
15
- # into
16
- # @param [Context] context The context to be injected
17
- # @param [optional Callable] setter An optional callable that takes a carrier and a key and
18
- # a value and assigns the key-value pair in the carrier
19
- # @return [Object] carrier
20
- def inject(carrier, context, &setter)
21
- carrier
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright The OpenTelemetry Authors
4
- #
5
- # SPDX-License-Identifier: Apache-2.0
6
-
7
- require 'opentelemetry/instrumentation/registry'
8
- require 'opentelemetry/instrumentation/base'
9
-
10
- module OpenTelemetry
11
- # The instrumentation module contains functionality to register and install
12
- # instrumentation
13
- module Instrumentation
14
- end
15
- end
@@ -1,307 +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 Instrumentation
9
- # The Base class holds all metadata and configuration for an
10
- # instrumentation. All instrumentation packages should
11
- # include a subclass of +Instrumentation::Base+ that will register
12
- # it with +OpenTelemetry.instrumentation_registry+ and make it available for
13
- # discovery and installation by an SDK.
14
- #
15
- # A typical subclass of Base will provide an install block, a present
16
- # block, and possibly a compatible block. Below is an
17
- # example:
18
- #
19
- # module OpenTelemetry
20
- # module Instrumentation
21
- # module Sinatra
22
- # class Instrumentation < OpenTelemetry::Instrumentation::Base
23
- # install do |config|
24
- # # install instrumentation, either by library hook or applying
25
- # # a monkey patch
26
- # end
27
- #
28
- # # determine if the target library is present
29
- # present do
30
- # defined?(::Sinatra)
31
- # end
32
- #
33
- # # if the target library is present, is it compatible?
34
- # compatible do
35
- # Gem.loaded_specs['sinatra'].version > MIN_VERSION
36
- # end
37
- # end
38
- # end
39
- # end
40
- # end
41
- #
42
- # The instrumentation name and version will be inferred from the namespace of the
43
- # class. In this example, they'd be 'OpenTelemetry::Instrumentation::Sinatra' and
44
- # OpenTelemetry::Instrumentation::Sinatra::VERSION, but can be explicitly set using
45
- # the +instrumentation_name+ and +instrumetation_version+ methods if necessary.
46
- #
47
- # All subclasses of OpenTelemetry::Instrumentation::Base are automatically
48
- # registered with OpenTelemetry.instrumentation_registry which is used by
49
- # SDKs for instrumentation discovery and installation.
50
- #
51
- # Instrumentation libraries can use the instrumentation subclass to easily gain
52
- # a reference to its named tracer. For example:
53
- #
54
- # OpenTelemetry::Instrumentation::Sinatra.instance.tracer
55
- #
56
- # The instrumention class establishes a convention for disabling an instrumentation
57
- # by environment variable and local configuration. An instrumentation disabled
58
- # by environment variable will take precedence over local config. The
59
- # convention for environment variable name is the library name, upcased with
60
- # '::' replaced by underscores, OPENTELEMETRY shortened to OTEL_{LANG}, and '_ENABLED' appended.
61
- # For example: OTEL_RUBY_INSTRUMENTATION_SINATRA_ENABLED = false.
62
- class Base # rubocop:disable Metrics/ClassLength
63
- class << self
64
- NAME_REGEX = /^(?:(?<namespace>[a-zA-Z0-9_:]+):{2})?(?<classname>[a-zA-Z0-9_]+)$/.freeze
65
- VALIDATORS = {
66
- array: ->(v) { v.is_a?(Array) },
67
- boolean: ->(v) { v == true || v == false }, # rubocop:disable Style/MultipleComparison
68
- callable: ->(v) { v.respond_to?(:call) },
69
- integer: ->(v) { v.is_a?(Integer) },
70
- string: ->(v) { v.is_a?(String) }
71
- }.freeze
72
-
73
- private_constant :NAME_REGEX, :VALIDATORS
74
-
75
- private :new # rubocop:disable Style/AccessModifierDeclarations
76
-
77
- def inherited(subclass)
78
- OpenTelemetry.instrumentation_registry.register(subclass)
79
- end
80
-
81
- # Optionally set the name of this instrumentation. If not
82
- # explicitly set, the name will default to the namespace of the class,
83
- # or the class name if it does not have a namespace. If there is not
84
- # a namespace, or a class name, it will default to 'unknown'.
85
- #
86
- # @param [String] instrumentation_name The full name of the instrumentation package
87
- def instrumentation_name(instrumentation_name = nil)
88
- if instrumentation_name
89
- @instrumentation_name = instrumentation_name
90
- else
91
- @instrumentation_name ||= infer_name || 'unknown'
92
- end
93
- end
94
-
95
- # Optionally set the version of this instrumentation. If not explicitly set,
96
- # the version will default to the VERSION constant under namespace of
97
- # the class, or the VERSION constant under the class name if it does not
98
- # have a namespace. If a VERSION constant cannot be found, it defaults
99
- # to '0.0.0'.
100
- #
101
- # @param [String] instrumentation_version The version of the instrumentation package
102
- def instrumentation_version(instrumentation_version = nil)
103
- if instrumentation_version
104
- @instrumentation_version = instrumentation_version
105
- else
106
- @instrumentation_version ||= infer_version || '0.0.0'
107
- end
108
- end
109
-
110
- # The install block for this instrumentation. This will be where you install
111
- # instrumentation, either by framework hook or applying a monkey patch.
112
- #
113
- # @param [Callable] blk The install block for this instrumentation
114
- # @yieldparam [Hash] config The instrumentation config will be yielded to the
115
- # install block
116
- def install(&blk)
117
- @install_blk = blk
118
- end
119
-
120
- # The present block for this instrumentation. This block is used to detect if
121
- # target library is present on the system. Typically this will involve
122
- # checking to see if the target gem spec was loaded or if expected
123
- # constants from the target library are present.
124
- #
125
- # @param [Callable] blk The present block for this instrumentation
126
- def present(&blk)
127
- @present_blk = blk
128
- end
129
-
130
- # The compatible block for this instrumentation. This check will be run if the
131
- # target library is present to determine if it's compatible. It's not
132
- # required, but a common use case will be to check to target library
133
- # version for compatibility.
134
- #
135
- # @param [Callable] blk The compatibility block for this instrumentation
136
- def compatible(&blk)
137
- @compatible_blk = blk
138
- end
139
-
140
- # The option method is used to define default configuration options
141
- # for the instrumentation library. It requires a name, default value,
142
- # and a validation callable to be provided.
143
- # @param [String] name The name of the configuration option
144
- # @param default The default value to be used, or to used if validation fails
145
- # @param [Callable, Symbol] validate Accepts a callable or a symbol that matches
146
- # a key in the VALIDATORS hash. The supported keys are, :array, :boolean,
147
- # :callable, :integer, :string.
148
- def option(name, default:, validate:)
149
- validate = VALIDATORS[validate] || validate
150
- raise ArgumentError, "validate must be #{VALIDATORS.keys.join(', ')}, or a callable" unless validate.respond_to?(:call)
151
-
152
- @options ||= []
153
- @options << { name: name, default: default, validate: validate }
154
- end
155
-
156
- def instance
157
- @instance ||= new(instrumentation_name, instrumentation_version, install_blk,
158
- present_blk, compatible_blk, options)
159
- end
160
-
161
- private
162
-
163
- attr_reader :install_blk, :present_blk, :compatible_blk, :options
164
-
165
- def infer_name
166
- @inferred_name ||= if (md = name.match(NAME_REGEX)) # rubocop:disable Naming/MemoizedInstanceVariableName
167
- md['namespace'] || md['classname']
168
- end
169
- end
170
-
171
- def infer_version
172
- return unless (inferred_name = infer_name)
173
-
174
- mod = inferred_name.split('::').map(&:to_sym).inject(Object) do |object, const|
175
- object.const_get(const)
176
- end
177
- mod.const_get(:VERSION)
178
- rescue NameError
179
- nil
180
- end
181
- end
182
-
183
- attr_reader :name, :version, :config, :installed, :tracer
184
-
185
- alias installed? installed
186
-
187
- def initialize(name, version, install_blk, present_blk,
188
- compatible_blk, options)
189
- @name = name
190
- @version = version
191
- @install_blk = install_blk
192
- @present_blk = present_blk
193
- @compatible_blk = compatible_blk
194
- @config = {}
195
- @installed = false
196
- @options = options
197
- end
198
-
199
- # Install instrumentation with the given config. The present? and compatible?
200
- # will be run first, and install will return false if either fail. Will
201
- # return true if install was completed successfully.
202
- #
203
- # @param [Hash] config The config for this instrumentation
204
- def install(config = {})
205
- return true if installed?
206
- return false unless installable?(config)
207
-
208
- @config = config_options(config)
209
- instance_exec(@config, &@install_blk)
210
- @tracer ||= OpenTelemetry.tracer_provider.tracer(name, version)
211
- @installed = true
212
- end
213
-
214
- # Whether or not this instrumentation is installable in the current process. Will
215
- # be true when the instrumentation defines an install block, is not disabled
216
- # by environment or config, and the target library present and compatible.
217
- #
218
- # @param [Hash] config The config for this instrumentation
219
- def installable?(config = {})
220
- @install_blk && enabled?(config) && present? && compatible?
221
- end
222
-
223
- # Calls the present block of the Instrumentation subclasses, if no block is provided
224
- # it's assumed the instrumentation is not present
225
- def present?
226
- return false unless @present_blk
227
-
228
- instance_exec(&@present_blk)
229
- end
230
-
231
- # Calls the compatible block of the Instrumentation subclasses, if no block is provided
232
- # it's assumed to be compatible
233
- def compatible?
234
- return true unless @compatible_blk
235
-
236
- instance_exec(&@compatible_blk)
237
- end
238
-
239
- # Whether this instrumentation is enabled. It first checks to see if it's enabled
240
- # by an environment variable and will proceed to check if it's enabled
241
- # by local config, if given.
242
- #
243
- # @param [optional Hash] config The local config
244
- def enabled?(config = nil)
245
- return false unless enabled_by_env_var?
246
- return config[:enabled] if config&.key?(:enabled)
247
-
248
- true
249
- end
250
-
251
- private
252
-
253
- # The config_options method is responsible for validating that the user supplied
254
- # config hash is valid.
255
- # Unknown configuration keys are not included in the final config hash.
256
- # Invalid configuration values are logged, and replaced by the default.
257
- #
258
- # @param [Hash] user_config The user supplied configuration hash
259
- def config_options(user_config) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
260
- @options ||= {}
261
- user_config ||= {}
262
- validated_config = @options.each_with_object({}) do |option, h|
263
- option_name = option[:name]
264
- config_value = user_config[option_name]
265
-
266
- value = if config_value.nil?
267
- option[:default]
268
- elsif option[:validate].call(config_value)
269
- config_value
270
- else
271
- OpenTelemetry.logger.warn(
272
- "Instrumentation #{name} configuration option #{option_name} value=#{config_value} " \
273
- "failed validation, falling back to default value=#{option[:default]}"
274
- )
275
- option[:default]
276
- end
277
-
278
- h[option_name] = value
279
- rescue StandardError => e
280
- OpenTelemetry.handle_error(exception: e, message: "Instrumentation #{name} unexpected configuration error")
281
- h[option_name] = option[:default]
282
- end
283
-
284
- dropped_config_keys = user_config.keys - validated_config.keys
285
- OpenTelemetry.logger.warn("Instrumentation #{name} ignored the following unknown configuration options #{dropped_config_keys}") unless dropped_config_keys.empty?
286
-
287
- validated_config
288
- end
289
-
290
- # Checks to see if this instrumentation is enabled by env var. By convention, the
291
- # environment variable will be the instrumentation name upper cased, with '::'
292
- # replaced by underscores, OPENTELEMETRY shortened to OTEL_{LANG} and _ENABLED appended.
293
- # For example, the, environment variable name for OpenTelemetry::Instrumentation::Sinatra
294
- # will be OTEL_RUBY_INSTRUMENTATION_SINATRA_ENABLED. A value of 'false' will disable
295
- # the instrumentation, all other values will enable it.
296
- def enabled_by_env_var?
297
- var_name = name.dup.tap do |n|
298
- n.upcase!
299
- n.gsub!('::', '_')
300
- n.gsub!('OPENTELEMETRY_', 'OTEL_RUBY_')
301
- n << '_ENABLED'
302
- end
303
- ENV[var_name] != 'false'
304
- end
305
- end
306
- end
307
- end