opentelemetry-api 0.11.0 → 0.15.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: 5b7fecd268c9efe43c452847e831bf1456d502c8531e589691b865bd1264b53f
4
- data.tar.gz: d8b33160247e5d8c94b248f607b621333112cda1a6fc7af00ce68ef1caed1cb0
3
+ metadata.gz: d9a70b684347cdc76e7cc5654e09ad01eb406cb415006b8f9418ff5c421521cf
4
+ data.tar.gz: 818b8c0cd95656898d0ce0eb4cf44d5fcc15ad7dd86e88b43b8aa1dc920dc05d
5
5
  SHA512:
6
- metadata.gz: 06e4bda488c11623f710a74288de802c8af5fbb879bb52edbd003dd10159ff443bde7c9d6f511915e0ecdaaf54244f7b8897c4137b466bd11bdc87f51b87d337
7
- data.tar.gz: 8466f42436e3e89e0a4339699887b3eae95551dd601f66be5b3f9ffc76f3aaad2075e95cb6aeed945422e0ea998148b769dc2781d3095a67c2051c2cc52068a7
6
+ metadata.gz: 3823e1d3a42b7cf8fcab40b5d2eb42f1fa312639175f8b57fef4ea5452451d8b358439424dc8da1825dbbb61e38c9a987c5996144d927bf6cb883a38f9dbaba0
7
+ data.tar.gz: 24365bbb7500da52d4b07ae1a54996d86a4ee98db465f15fe9b93aef4d6911ca072b1f48b1c1977351f0326607c271536b2b2b1df98b4831c70912be5adf0e65
data/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # Release History: opentelemetry-api
2
2
 
3
+ ### v0.15.0 / 2021-02-18
4
+
5
+ * ADDED: Add instrumentation config validation
6
+ * DOCS: Clarify nil attribute values not allowed
7
+
8
+ ### v0.14.0 / 2021-02-03
9
+
10
+ * BREAKING CHANGE: Replace getter and setter callables and remove rack specific propagators
11
+
12
+ * ADDED: Replace getter and setter callables and remove rack specific propagators
13
+
14
+ ### v0.13.0 / 2021-01-29
15
+
16
+ * ADDED: Add optional attributes to record_exception
17
+ * FIXED: Small test fixes.
18
+
19
+ ### v0.12.1 / 2021-01-13
20
+
21
+ * FIXED: Eliminate warning about Random::DEFAULT on Ruby 3.0
22
+
23
+ ### v0.12.0 / 2020-12-24
24
+
25
+ * ADDED: Structured error handling
26
+
3
27
  ### v0.11.0 / 2020-12-11
4
28
 
5
29
  * BREAKING CHANGE: Implement tracestate
data/README.md CHANGED
@@ -59,8 +59,8 @@ The `opentelemetry-api` gem is distributed under the Apache 2.0 license. See [LI
59
59
  [opentelemetry-home]: https://opentelemetry.io
60
60
  [bundler-home]: https://bundler.io
61
61
  [repo-github]: https://github.com/open-telemetry/opentelemetry-ruby
62
- [license-github]: https://github.com/open-telemetry/opentelemetry-ruby/blob/master/LICENSE
63
- [examples-github]: https://github.com/open-telemetry/opentelemetry-ruby/tree/master/examples
62
+ [license-github]: https://github.com/open-telemetry/opentelemetry-ruby/blob/main/LICENSE
63
+ [examples-github]: https://github.com/open-telemetry/opentelemetry-ruby/tree/main/examples
64
64
  [ruby-sig]: https://github.com/open-telemetry/community#ruby-sig
65
65
  [community-meetings]: https://github.com/open-telemetry/community#community-meetings
66
66
  [ruby-gitter]: https://gitter.im/open-telemetry/opentelemetry-ruby
data/lib/opentelemetry.rb CHANGED
@@ -22,13 +22,28 @@ require 'opentelemetry/version'
22
22
  module OpenTelemetry
23
23
  extend self
24
24
 
25
- attr_writer :tracer_provider, :meter_provider, :baggage, :logger
25
+ attr_writer :tracer_provider, :meter_provider, :propagation, :baggage,
26
+ :logger, :error_handler
26
27
 
27
28
  # @return [Object, Logger] configured Logger or a default STDOUT Logger.
28
29
  def logger
29
30
  @logger ||= Logger.new(STDOUT, level: ENV['OTEL_LOG_LEVEL'] || Logger::INFO)
30
31
  end
31
32
 
33
+ # @return [Callable] configured error handler or a default that logs the
34
+ # exception and message at ERROR level.
35
+ def error_handler
36
+ @error_handler ||= ->(exception: nil, message: nil) { logger.error("OpenTelemetry error: #{[message, exception&.message].compact.join(' - ')}") }
37
+ end
38
+
39
+ # Handles an error by calling the configured error_handler.
40
+ #
41
+ # @param [optional Exception] exception The exception to be handled
42
+ # @param [optional String] message An error message.
43
+ def handle_error(exception: nil, message: nil)
44
+ error_handler.call(exception: exception, message: message)
45
+ end
46
+
32
47
  # @return [Object, Trace::TracerProvider] registered tracer provider or a
33
48
  # default no-op implementation of the tracer provider.
34
49
  def tracer_provider
@@ -54,8 +69,11 @@ module OpenTelemetry
54
69
  @baggage ||= Baggage::Manager.new
55
70
  end
56
71
 
57
- # @return [Context::Propagation::Propagation] an instance of the propagation API
72
+ # @return [Context::Propagation::Propagator] a propagator instance
58
73
  def propagation
59
- @propagation ||= Context::Propagation::Propagation.new
74
+ @propagation ||= Context::Propagation::Propagator.new(
75
+ Context::Propagation::NoopInjector.new,
76
+ Context::Propagation::NoopExtractor.new
77
+ )
60
78
  end
61
79
  end
@@ -15,17 +15,11 @@ module OpenTelemetry
15
15
  module Propagation
16
16
  extend self
17
17
 
18
+ BAGGAGE_KEY = 'baggage'
18
19
  TEXT_MAP_EXTRACTOR = TextMapExtractor.new
19
20
  TEXT_MAP_INJECTOR = TextMapInjector.new
20
- RACK_EXTRACTOR = TextMapExtractor.new(
21
- baggage_key: 'HTTP_BAGGAGE'
22
- )
23
- RACK_INJECTOR = TextMapInjector.new(
24
- baggage_key: 'HTTP_BAGGAGE'
25
- )
26
21
 
27
- private_constant :TEXT_MAP_INJECTOR, :TEXT_MAP_EXTRACTOR, :RACK_INJECTOR,
28
- :RACK_EXTRACTOR
22
+ private_constant :BAGGAGE_KEY, :TEXT_MAP_INJECTOR, :TEXT_MAP_EXTRACTOR
29
23
 
30
24
  # Returns an extractor that extracts context using the W3C Baggage
31
25
  # format
@@ -38,20 +32,6 @@ module OpenTelemetry
38
32
  def text_map_extractor
39
33
  TEXT_MAP_EXTRACTOR
40
34
  end
41
-
42
- # Returns an extractor that extracts context using the W3C Baggage
43
- # format with Rack normalized keys (upcased and prefixed with
44
- # HTTP_)
45
- def rack_injector
46
- RACK_INJECTOR
47
- end
48
-
49
- # Returns an injector that injects context using the W3C Baggage
50
- # format with Rack normalized keys (upcased and prefixed with
51
- # HTTP_)
52
- def rack_extractor
53
- RACK_EXTRACTOR
54
- end
55
35
  end
56
36
  end
57
37
  end
@@ -11,16 +11,15 @@ module OpenTelemetry
11
11
  module Propagation
12
12
  # Extracts baggage from carriers in the W3C Baggage format
13
13
  class TextMapExtractor
14
- include Context::Propagation::DefaultGetter
15
-
16
14
  # Returns a new TextMapExtractor that extracts context using the specified
17
- # header key
15
+ # getter
18
16
  #
19
- # @param [String] baggage_key The baggage header
20
- # key used in the carrier
17
+ # @param [optional Getter] default_getter The default getter used to read
18
+ # headers from a carrier during extract. Defaults to a
19
+ # {OpenTelemetry::Context::Propagation::TextMapGetter} instance.
21
20
  # @return [TextMapExtractor]
22
- def initialize(baggage_key: 'baggage')
23
- @baggage_key = baggage_key
21
+ def initialize(default_getter = Context::Propagation.text_map_getter)
22
+ @default_getter = default_getter
24
23
  end
25
24
 
26
25
  # Extract remote baggage from the supplied carrier.
@@ -28,16 +27,14 @@ module OpenTelemetry
28
27
  #
29
28
  # @param [Carrier] carrier The carrier to get the header from
30
29
  # @param [Context] context The context to be updated with extracted baggage
31
- # @param [optional Callable] getter An optional callable that takes a carrier and a key and
32
- # returns the value associated with the key. If omitted the default getter will be used
33
- # which expects the carrier to respond to [] and []=.
34
- # @yield [Carrier, String] if an optional getter is provided, extract will yield the carrier
35
- # and the header key to the getter.
30
+ # @param [optional Getter] getter If the optional getter is provided, it
31
+ # will be used to read the header from the carrier, otherwise the default
32
+ # getter will be used.
36
33
  # @return [Context] context updated with extracted baggage, or the original context
37
34
  # if extraction fails
38
- def extract(carrier, context, &getter)
39
- getter ||= default_getter
40
- header = getter.call(carrier, @baggage_key)
35
+ def extract(carrier, context, getter = nil)
36
+ getter ||= @default_getter
37
+ header = getter.get(carrier, BAGGAGE_KEY)
41
38
 
42
39
  entries = header.gsub(/\s/, '').split(',')
43
40
 
@@ -11,33 +11,30 @@ module OpenTelemetry
11
11
  module Propagation
12
12
  # Injects baggage using the W3C Baggage format
13
13
  class TextMapInjector
14
- include Context::Propagation::DefaultSetter
15
-
16
14
  # Returns a new TextMapInjector that injects context using the specified
17
- # header key
15
+ # setter
18
16
  #
19
- # @param [String] baggage_key The baggage header
20
- # key used in the carrier
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.
21
20
  # @return [TextMapInjector]
22
- def initialize(baggage_key: 'baggage')
23
- @baggage_key = baggage_key
21
+ def initialize(default_setter = Context::Propagation.text_map_setter)
22
+ @default_setter = default_setter
24
23
  end
25
24
 
26
25
  # Inject in-process baggage into the supplied carrier.
27
26
  #
28
27
  # @param [Carrier] carrier The carrier to inject baggage into
29
28
  # @param [Context] context The context to read baggage from
30
- # @param [optional Callable] getter An optional callable that takes a carrier and a key and
31
- # returns the value associated with the key. If omitted the default getter will be used
32
- # which expects the carrier to respond to [] and []=.
33
- # @yield [Carrier, String] if an optional getter is provided, inject will yield the carrier
34
- # and the header key to the getter.
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.
35
32
  # @return [Object] carrier with injected baggage
36
- def inject(carrier, context, &setter)
33
+ def inject(carrier, context, setter = nil)
37
34
  return carrier unless (baggage = context[ContextKeys.baggage_key]) && !baggage.empty?
38
35
 
39
- setter ||= default_setter
40
- setter.call(carrier, @baggage_key, encode(baggage))
36
+ setter ||= @default_setter
37
+ setter.set(carrier, BAGGAGE_KEY, encode(baggage))
41
38
 
42
39
  carrier
43
40
  end
@@ -5,18 +5,43 @@
5
5
  # SPDX-License-Identifier: Apache-2.0
6
6
 
7
7
  require 'opentelemetry/context/propagation/composite_propagator'
8
- require 'opentelemetry/context/propagation/default_getter'
9
- require 'opentelemetry/context/propagation/default_setter'
10
8
  require 'opentelemetry/context/propagation/noop_extractor'
11
9
  require 'opentelemetry/context/propagation/noop_injector'
12
- require 'opentelemetry/context/propagation/propagation'
13
10
  require 'opentelemetry/context/propagation/propagator'
11
+ require 'opentelemetry/context/propagation/text_map_getter'
12
+ require 'opentelemetry/context/propagation/text_map_setter'
13
+ require 'opentelemetry/context/propagation/rack_env_getter'
14
14
 
15
15
  module OpenTelemetry
16
16
  class Context
17
17
  # The propagation module contains APIs and utilities to interact with context
18
18
  # and propagate across process boundaries.
19
19
  module Propagation
20
+ extend self
21
+
22
+ TEXT_MAP_GETTER = TextMapGetter.new
23
+ TEXT_MAP_SETTER = TextMapSetter.new
24
+ RACK_ENV_GETTER = RackEnvGetter.new
25
+
26
+ private_constant :TEXT_MAP_GETTER, :TEXT_MAP_SETTER, :RACK_ENV_GETTER
27
+
28
+ # Returns a {TextMapGetter} instance suitable for reading values from a
29
+ # hash-like carrier
30
+ def text_map_getter
31
+ TEXT_MAP_GETTER
32
+ end
33
+
34
+ # Returns a {TextMapSetter} instance suitable for writing values into a
35
+ # hash-like carrier
36
+ def text_map_setter
37
+ TEXT_MAP_SETTER
38
+ end
39
+
40
+ # Returns a {RackEnvGetter} instance suitable for reading values from a
41
+ # Rack environment.
42
+ def rack_env_getter
43
+ RACK_ENV_GETTER
44
+ end
20
45
  end
21
46
  end
22
47
  end
@@ -30,15 +30,14 @@ module OpenTelemetry
30
30
  # context into
31
31
  # @param [optional Context] context Context to be injected into carrier.
32
32
  # Defaults to +Context.current+
33
- # @param [optional Callable] setter An optional callable that takes a
34
- # carrier, a key and a value and assigns the key-value pair in the
35
- # carrier. If omitted the default setter will be used which expects
36
- # the carrier to respond to [] and []=.
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.
37
36
  #
38
37
  # @return [Object] carrier
39
- def inject(carrier, context = Context.current, &setter)
38
+ def inject(carrier, context: Context.current, setter: Context::Propagation.text_map_setter)
40
39
  @injectors.inject(carrier) do |memo, injector|
41
- injector.inject(memo, context, &setter)
40
+ injector.inject(memo, context, setter)
42
41
  rescue => e # rubocop:disable Style/RescueStandardError
43
42
  OpenTelemetry.logger.warn "Error in CompositePropagator#inject #{e.message}"
44
43
  carrier
@@ -53,15 +52,15 @@ module OpenTelemetry
53
52
  # @param [Object] carrier The carrier to extract context from
54
53
  # @param [optional Context] context Context to be updated with the state
55
54
  # extracted from the carrier. Defaults to +Context.current+
56
- # @param [optional Callable] getter An optional callable that takes a carrier and a key and
57
- # returns the value associated with the key. If omitted the default getter will be used
58
- # which expects the carrier to respond to [] and []=.
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.
59
58
  #
60
59
  # @return [Context] a new context updated with state extracted from the
61
60
  # carrier
62
- def extract(carrier, context = Context.current, &getter)
61
+ def extract(carrier, context: Context.current, getter: Context::Propagation.text_map_getter)
63
62
  @extractors.inject(context) do |ctx, extractor|
64
- extractor.extract(carrier, ctx, &getter)
63
+ extractor.extract(carrier, ctx, getter)
65
64
  rescue => e # rubocop:disable Style/RescueStandardError
66
65
  OpenTelemetry.logger.warn "Error in CompositePropagator#extract #{e.message}"
67
66
  ctx
@@ -17,7 +17,7 @@ module OpenTelemetry
17
17
  # @param [optional Callable] getter An optional callable that takes a carrier and a key and
18
18
  # and returns the value associated with the key
19
19
  # @return [Context]
20
- def extract(carrier, context, &getter)
20
+ def extract(carrier, context, getter = nil)
21
21
  context
22
22
  end
23
23
  end
@@ -28,13 +28,13 @@ module OpenTelemetry
28
28
  # context into
29
29
  # @param [optional Context] context Context to be injected into carrier. Defaults
30
30
  # to +Context.current+
31
- # @param [optional Callable] setter An optional callable that takes a carrier, a key and
32
- # a value and assigns the key-value pair in the carrier. If omitted the default setter
33
- # will be used which expects the carrier to respond to [] and []=.
31
+ # @param [optional Setter] setter If the optional setter is provided, it
32
+ # will be used to write context into the carrier, otherwise the default
33
+ # setter will be used.
34
34
  #
35
35
  # @return [Object] carrier
36
- def inject(carrier, context = Context.current, &setter)
37
- @injector.inject(carrier, context, &setter)
36
+ def inject(carrier, context: Context.current, setter: Context::Propagation.text_map_setter)
37
+ @injector.inject(carrier, context, setter)
38
38
  rescue => e # rubocop:disable Style/RescueStandardError
39
39
  OpenTelemetry.logger.warn "Error in Propagator#inject #{e.message}"
40
40
  carrier
@@ -46,14 +46,14 @@ module OpenTelemetry
46
46
  # @param [Object] carrier The carrier to extract context from
47
47
  # @param [optional Context] context Context to be updated with the state
48
48
  # extracted from the carrier. Defaults to +Context.current+
49
- # @param [optional Callable] getter An optional callable that takes a carrier and a key and
50
- # returns the value associated with the key. If omitted the default getter will be used
51
- # which expects the carrier to respond to [] and []=.
49
+ # @param [optional Getter] getter If the optional getter is provided, it
50
+ # will be used to read the header from the carrier, otherwise the default
51
+ # getter will be used.
52
52
  #
53
53
  # @return [Context] a new context updated with state extracted from the
54
54
  # carrier
55
- def extract(carrier, context = Context.current, &getter)
56
- @extractor.extract(carrier, context, &getter)
55
+ def extract(carrier, context: Context.current, getter: Context::Propagation.text_map_getter)
56
+ @extractor.extract(carrier, context, getter)
57
57
  rescue => e # rubocop:disable Style/RescueStandardError
58
58
  OpenTelemetry.logger.warn "Error in Propagator#extract #{e.message}"
59
59
  context
@@ -0,0 +1,46 @@
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
+ # The RackEnvGetter class provides a common methods for reading
11
+ # keys from a rack environment. It abstracts away the rack-normalization
12
+ # process so that keys can be looked up without having to transform them
13
+ # first. With this class you can get +traceparent+ instead of
14
+ # +HTTP_TRACEPARENT+
15
+ class RackEnvGetter
16
+ # Converts key into a rack-normalized key and reads it from the carrier.
17
+ # Useful for extract operations.
18
+ def get(carrier, key)
19
+ carrier[to_rack_key(key)]
20
+ end
21
+
22
+ # Reads all keys from a carrier and converts them from the rack-normalized
23
+ # form to the original. The resulting keys will be lowercase and
24
+ # underscores will be replaced with dashes.
25
+ def keys(carrier)
26
+ carrier.keys.map(&method(:from_rack_key))
27
+ end
28
+
29
+ private
30
+
31
+ def to_rack_key(key)
32
+ ret = 'HTTP_' + key
33
+ ret.tr!('-', '_')
34
+ ret.upcase!
35
+ end
36
+
37
+ def from_rack_key(key)
38
+ start = key.start_with?('HTTP_') ? 5 : 0
39
+ ret = key[start..-1]
40
+ ret.tr!('_', '-')
41
+ ret.downcase!
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,27 @@
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
+ # The default getter module provides a common methods for reading
11
+ # key from a carrier that implements +[]+ and a +keys+ method
12
+ class TextMapGetter
13
+ # Reads a key from a carrier that implements +[]+. Useful for extract
14
+ # operations.
15
+ def get(carrier, key)
16
+ carrier[key]
17
+ end
18
+
19
+ # Reads all keys from a carrier. Useful for iterating over a carrier's
20
+ # keys.
21
+ def keys(carrier)
22
+ carrier.keys
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
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
+ # The default setter module provides a common method for writing
11
+ # a key into a carrier that implements +[]=+
12
+ class TextMapSetter
13
+ # Writes key into a carrier that implements +[]=+. Useful for inject
14
+ # operations.
15
+ def set(carrier, key, value)
16
+ carrier[key] = value
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -59,10 +59,18 @@ module OpenTelemetry
59
59
  # convention for environment variable name is the library name, upcased with
60
60
  # '::' replaced by underscores, OPENTELEMETRY shortened to OTEL_{LANG}, and '_ENABLED' appended.
61
61
  # For example: OTEL_RUBY_INSTRUMENTATION_SINATRA_ENABLED = false.
62
- class Base
62
+ class Base # rubocop:disable Metrics/ClassLength
63
63
  class << self
64
64
  NAME_REGEX = /^(?:(?<namespace>[a-zA-Z0-9_:]+):{2})?(?<classname>[a-zA-Z0-9_]+)$/.freeze
65
- private_constant :NAME_REGEX
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
66
74
 
67
75
  private :new # rubocop:disable Style/AccessModifierDeclarations
68
76
 
@@ -129,14 +137,30 @@ module OpenTelemetry
129
137
  @compatible_blk = blk
130
138
  end
131
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
+
132
156
  def instance
133
157
  @instance ||= new(instrumentation_name, instrumentation_version, install_blk,
134
- present_blk, compatible_blk)
158
+ present_blk, compatible_blk, options)
135
159
  end
136
160
 
137
161
  private
138
162
 
139
- attr_reader :install_blk, :present_blk, :compatible_blk
163
+ attr_reader :install_blk, :present_blk, :compatible_blk, :options
140
164
 
141
165
  def infer_name
142
166
  @inferred_name ||= if (md = name.match(NAME_REGEX)) # rubocop:disable Naming/MemoizedInstanceVariableName
@@ -161,7 +185,7 @@ module OpenTelemetry
161
185
  alias installed? installed
162
186
 
163
187
  def initialize(name, version, install_blk, present_blk,
164
- compatible_blk)
188
+ compatible_blk, options)
165
189
  @name = name
166
190
  @version = version
167
191
  @install_blk = install_blk
@@ -169,6 +193,7 @@ module OpenTelemetry
169
193
  @compatible_blk = compatible_blk
170
194
  @config = {}
171
195
  @installed = false
196
+ @options = options
172
197
  end
173
198
 
174
199
  # Install instrumentation with the given config. The present? and compatible?
@@ -180,7 +205,7 @@ module OpenTelemetry
180
205
  return true if installed?
181
206
  return false unless installable?(config)
182
207
 
183
- @config = config unless config.nil?
208
+ @config = config_options(config)
184
209
  instance_exec(@config, &@install_blk)
185
210
  @tracer ||= OpenTelemetry.tracer_provider.tracer(name, version)
186
211
  @installed = true
@@ -225,6 +250,43 @@ module OpenTelemetry
225
250
 
226
251
  private
227
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
+
228
290
  # Checks to see if this instrumentation is enabled by env var. By convention, the
229
291
  # environment variable will be the instrumentation name upper cased, with '::'
230
292
  # replaced by underscores, OPENTELEMETRY shortened to OTEL_{LANG} and _ENABLED appended.
@@ -79,8 +79,7 @@ module OpenTelemetry
79
79
  OpenTelemetry.logger.warn "Instrumentation: #{instrumentation.name} failed to install"
80
80
  end
81
81
  rescue => e # rubocop:disable Style/RescueStandardError
82
- OpenTelemetry.logger.warn "Instrumentation: #{instrumentation.name} unhandled exception " \
83
- "during install #{e}: #{e.backtrace}"
82
+ OpenTelemetry.handle_error(exception: e, message: "Instrumentation: #{instrumentation.name} unhandled exception during install: #{e.backtrace}")
84
83
  end
85
84
  end
86
85
  end
@@ -13,7 +13,17 @@ module OpenTelemetry
13
13
 
14
14
  CURRENT_SPAN_KEY = Context.create_key('current-span')
15
15
 
16
- private_constant :CURRENT_SPAN_KEY
16
+ # Random number generator for generating IDs. This is an object that can
17
+ # respond to `#bytes` and uses the system PRNG. The current logic is
18
+ # compatible with Ruby 2.5 (which does not implement the `Random.bytes`
19
+ # class method) and with Ruby 3.0+ (which deprecates `Random::DEFAULT`).
20
+ # When we drop support for Ruby 2.5, this can simply be replaced with
21
+ # the class `Random`.
22
+ #
23
+ # @return [#bytes]
24
+ RANDOM = Random.respond_to?(:bytes) ? Random : Random::DEFAULT
25
+
26
+ private_constant :CURRENT_SPAN_KEY, :RANDOM
17
27
 
18
28
  # An invalid trace identifier, a 16-byte string with all zero bytes.
19
29
  INVALID_TRACE_ID = ("\0" * 16).b
@@ -27,7 +37,7 @@ module OpenTelemetry
27
37
  # @return [String] a valid trace ID.
28
38
  def generate_trace_id
29
39
  loop do
30
- id = Random::DEFAULT.bytes(16)
40
+ id = RANDOM.bytes(16)
31
41
  return id unless id == INVALID_TRACE_ID
32
42
  end
33
43
  end
@@ -38,7 +48,7 @@ module OpenTelemetry
38
48
  # @return [String] a valid span ID.
39
49
  def generate_span_id
40
50
  loop do
41
- id = Random::DEFAULT.bytes(8)
51
+ id = RANDOM.bytes(8)
42
52
  return id unless id == INVALID_SPAN_ID
43
53
  end
44
54
  end
@@ -15,20 +15,13 @@ module OpenTelemetry
15
15
  # for context propagation in the W3C Trace Context format.
16
16
  module TraceContext
17
17
  extend self
18
-
18
+ TRACEPARENT_KEY = 'traceparent'
19
+ TRACESTATE_KEY = 'tracestate'
19
20
  TEXT_MAP_EXTRACTOR = TextMapExtractor.new
20
21
  TEXT_MAP_INJECTOR = TextMapInjector.new
21
- RACK_EXTRACTOR = TextMapExtractor.new(
22
- traceparent_key: 'HTTP_TRACEPARENT',
23
- tracestate_key: 'HTTP_TRACESTATE'
24
- )
25
- RACK_INJECTOR = TextMapInjector.new(
26
- traceparent_key: 'HTTP_TRACEPARENT',
27
- tracestate_key: 'HTTP_TRACESTATE'
28
- )
29
22
 
30
- private_constant :TEXT_MAP_INJECTOR, :TEXT_MAP_EXTRACTOR,
31
- :RACK_INJECTOR, :RACK_EXTRACTOR
23
+ private_constant :TRACEPARENT_KEY, :TRACESTATE_KEY,
24
+ :TEXT_MAP_INJECTOR, :TEXT_MAP_EXTRACTOR
32
25
 
33
26
  # Returns an extractor that extracts context using the W3C Trace Context
34
27
  # format
@@ -41,18 +34,6 @@ module OpenTelemetry
41
34
  def text_map_injector
42
35
  TEXT_MAP_INJECTOR
43
36
  end
44
-
45
- # Returns an extractor that extracts context using the W3C Trace Context
46
- # with Rack normalized keys (upcased and prefixed with HTTP_)
47
- def rack_extractor
48
- RACK_EXTRACTOR
49
- end
50
-
51
- # Returns an injector that injects context using the W3C Trace Context
52
- # format with Rack normalized keys (upcased and prefixed with HTTP_)
53
- def rack_injector
54
- RACK_INJECTOR
55
- end
56
37
  end
57
38
  end
58
39
  end
@@ -9,18 +9,15 @@ module OpenTelemetry
9
9
  module TraceContext
10
10
  # Extracts context from carriers in the W3C Trace Context format
11
11
  class TextMapExtractor
12
- include Context::Propagation::DefaultGetter
13
-
14
12
  # Returns a new TextMapExtractor that extracts context using the
15
- # specified header keys
13
+ # specified getter
16
14
  #
17
- # @param [String] traceparent_key The traceparent header key used in the carrier
18
- # @param [String] tracestate_key The tracestate header key used in the carrier
15
+ # @param [optional Getter] default_getter The default getter used to read
16
+ # headers from a carrier during extract. Defaults to a +TextMapGetter+
17
+ # instance.
19
18
  # @return [TextMapExtractor]
20
- def initialize(traceparent_key: 'traceparent',
21
- tracestate_key: 'tracestate')
22
- @traceparent_key = traceparent_key
23
- @tracestate_key = tracestate_key
19
+ def initialize(default_getter = Context::Propagation.text_map_getter)
20
+ @default_getter = default_getter
24
21
  end
25
22
 
26
23
  # Extract a remote {Trace::SpanContext} from the supplied carrier.
@@ -28,17 +25,15 @@ module OpenTelemetry
28
25
  #
29
26
  # @param [Carrier] carrier The carrier to get the header from.
30
27
  # @param [Context] context The context to be updated with extracted context
31
- # @param [optional Callable] getter An optional callable that takes a carrier and a key and
32
- # returns the value associated with the key. If omitted the default getter will be used
33
- # which expects the carrier to respond to [] and []=.
34
- # @yield [Carrier, String] if an optional getter is provided, extract will yield the carrier
35
- # and the header key to the getter.
28
+ # @param [optional Getter] getter If the optional getter is provided, it
29
+ # will be used to read the header from the carrier, otherwise the default
30
+ # getter will be used.
36
31
  # @return [Context] Updated context with span context from the header, or the original
37
32
  # context if parsing fails.
38
- def extract(carrier, context, &getter)
39
- getter ||= default_getter
40
- tp = TraceParent.from_string(getter.call(carrier, @traceparent_key))
41
- tracestate = Tracestate.from_string(getter.call(carrier, @tracestate_key))
33
+ def extract(carrier, context, getter = nil)
34
+ getter ||= @default_getter
35
+ tp = TraceParent.from_string(getter.get(carrier, TRACEPARENT_KEY))
36
+ tracestate = Tracestate.from_string(getter.get(carrier, TRACESTATE_KEY))
42
37
 
43
38
  span_context = Trace::SpanContext.new(trace_id: tp.trace_id,
44
39
  span_id: tp.span_id,
@@ -9,35 +9,30 @@ module OpenTelemetry
9
9
  module TraceContext
10
10
  # Injects context into carriers using the W3C Trace Context format
11
11
  class TextMapInjector
12
- include Context::Propagation::DefaultSetter
13
-
14
12
  # Returns a new TextMapInjector that injects context using the
15
- # specified header keys
13
+ # specified setter
16
14
  #
17
- # @param [String] traceparent_key The traceparent header key used in the carrier
18
- # @param [String] tracestate_key The tracestate header key used in the carrier
15
+ # @param [optional Setter] default_setter The default setter used to
16
+ # write context into a carrier during inject. Defaults to a
17
+ # {TextMapSetter} instance.
19
18
  # @return [TextMapInjector]
20
- def initialize(traceparent_key: 'traceparent',
21
- tracestate_key: 'tracestate')
22
- @traceparent_key = traceparent_key
23
- @tracestate_key = tracestate_key
19
+ def initialize(default_setter = Context::Propagation.text_map_setter)
20
+ @default_setter = default_setter
24
21
  end
25
22
 
26
23
  # Set the span context on the supplied carrier.
27
24
  #
28
25
  # @param [Context] context The active {Context}.
29
- # @param [optional Callable] setter An optional callable that takes a carrier and a key and
30
- # a value and assigns the key-value pair in the carrier. If omitted the default setter
31
- # will be used which expects the carrier to respond to [] and []=.
32
- # @yield [Carrier, String, String] if an optional setter is provided, inject will yield
33
- # carrier, header key, header value to the setter.
26
+ # @param [optional Setter] setter If the optional setter is provided, it
27
+ # will be used to write context into the carrier, otherwise the default
28
+ # setter will be used.
34
29
  # @return [Object] the carrier with context injected
35
- def inject(carrier, context, &setter)
30
+ def inject(carrier, context, setter = nil)
36
31
  return carrier unless (span_context = span_context_from(context))
37
32
 
38
- setter ||= DEFAULT_SETTER
39
- setter.call(carrier, @traceparent_key, TraceParent.from_span_context(span_context).to_s)
40
- setter.call(carrier, @tracestate_key, span_context.tracestate.to_s) unless span_context.tracestate.empty?
33
+ setter ||= @default_setter
34
+ setter.set(carrier, TRACEPARENT_KEY, TraceParent.from_span_context(span_context).to_s)
35
+ setter.set(carrier, TRACESTATE_KEY, span_context.tracestate.to_s) unless span_context.tracestate.empty?
41
36
 
42
37
  carrier
43
38
  end
@@ -51,6 +51,9 @@ module OpenTelemetry
51
51
  #
52
52
  # @param [String] key
53
53
  # @param [String, Boolean, Numeric, Array<String, Numeric, Boolean>] value
54
+ # Values must be non-nil and (array of) string, boolean or numeric type.
55
+ # Array values must not contain nil elements and all elements must be of
56
+ # the same basic type (string, numeric, boolean).
54
57
  #
55
58
  # @return [self] returns itself
56
59
  def set_attribute(key, value)
@@ -85,9 +88,13 @@ module OpenTelemetry
85
88
  # can be recorded on a span.
86
89
  #
87
90
  # @param [Exception] exception The exception to recorded
91
+ # @param [optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
92
+ # attributes One or more key:value pairs, where the keys must be
93
+ # strings and the values may be (array of) string, boolean or numeric
94
+ # type.
88
95
  #
89
96
  # @return [void]
90
- def record_exception(exception); end
97
+ def record_exception(exception, attributes: nil); end
91
98
 
92
99
  # Sets the Status to the Span
93
100
  #
@@ -6,5 +6,5 @@
6
6
 
7
7
  module OpenTelemetry
8
8
  ## Current OpenTelemetry version
9
- VERSION = '0.11.0'
9
+ VERSION = '0.15.0'
10
10
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opentelemetry-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.15.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-11 00:00:00.000000000 Z
11
+ date: 2021-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: benchmark-ipsa
@@ -160,12 +160,12 @@ files:
160
160
  - lib/opentelemetry/context/key.rb
161
161
  - lib/opentelemetry/context/propagation.rb
162
162
  - lib/opentelemetry/context/propagation/composite_propagator.rb
163
- - lib/opentelemetry/context/propagation/default_getter.rb
164
- - lib/opentelemetry/context/propagation/default_setter.rb
165
163
  - lib/opentelemetry/context/propagation/noop_extractor.rb
166
164
  - lib/opentelemetry/context/propagation/noop_injector.rb
167
- - lib/opentelemetry/context/propagation/propagation.rb
168
165
  - lib/opentelemetry/context/propagation/propagator.rb
166
+ - lib/opentelemetry/context/propagation/rack_env_getter.rb
167
+ - lib/opentelemetry/context/propagation/text_map_getter.rb
168
+ - lib/opentelemetry/context/propagation/text_map_setter.rb
169
169
  - lib/opentelemetry/error.rb
170
170
  - lib/opentelemetry/instrumentation.rb
171
171
  - lib/opentelemetry/instrumentation/base.rb
@@ -196,10 +196,10 @@ homepage: https://github.com/open-telemetry/opentelemetry-ruby
196
196
  licenses:
197
197
  - Apache-2.0
198
198
  metadata:
199
- changelog_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-api/v0.11.0/file.CHANGELOG.html
200
- source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/master/api
199
+ changelog_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-api/v0.15.0/file.CHANGELOG.html
200
+ source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/main/api
201
201
  bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby/issues
202
- documentation_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-api/v0.11.0
202
+ documentation_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-api/v0.15.0
203
203
  post_install_message:
204
204
  rdoc_options: []
205
205
  require_paths:
@@ -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
- # The default getter module provides a common method for reading
11
- # a key from a carrier that implements +[]+
12
- module DefaultGetter
13
- DEFAULT_GETTER = ->(carrier, key) { carrier[key] }
14
- private_constant :DEFAULT_GETTER
15
-
16
- # Returns a callable that can read a key from a carrier that implements
17
- # +[]+. Useful for extract operations.
18
- #
19
- # @return [Callable]
20
- def default_getter
21
- DEFAULT_GETTER
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
- # The default setter module provides a common method for writing
11
- # a key into a carrier that implements +[]=+
12
- module DefaultSetter
13
- DEFAULT_SETTER = ->(carrier, key, value) { carrier[key] = value }
14
- private_constant :DEFAULT_SETTER
15
-
16
- # Returns a callable that can write a key into a carrier that implements
17
- # +[]=+. Useful for inject operations.
18
- #
19
- # @return [Callable]
20
- def default_setter
21
- DEFAULT_SETTER
22
- end
23
- end
24
- end
25
- end
26
- end
@@ -1,27 +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
- # The Propagation class provides methods to inject and extract context
11
- # to pass across process boundaries
12
- class Propagation
13
- # Get or set the global http propagator. Use a CompositePropagator
14
- # to propagate multiple formats.
15
- attr_accessor :http
16
-
17
- # Get or set the global text propagator. Use a CompositePropagator
18
- # to propagate multiple formats.
19
- attr_accessor :text
20
-
21
- def initialize
22
- @http = @text = Propagator.new(NoopInjector.new, NoopExtractor.new)
23
- end
24
- end
25
- end
26
- end
27
- end