opentelemetry-api 0.11.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
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