opentelemetry-api 0.13.0 → 1.0.0.rc1

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -0
  3. data/README.md +2 -2
  4. data/lib/opentelemetry.rb +24 -20
  5. data/lib/opentelemetry/baggage.rb +4 -1
  6. data/lib/opentelemetry/baggage/builder.rb +30 -4
  7. data/lib/opentelemetry/baggage/entry.rb +20 -0
  8. data/lib/opentelemetry/baggage/manager.rb +76 -13
  9. data/lib/opentelemetry/baggage/noop_builder.rb +18 -0
  10. data/lib/opentelemetry/baggage/noop_manager.rb +45 -0
  11. data/lib/opentelemetry/baggage/propagation.rb +9 -38
  12. data/lib/opentelemetry/baggage/propagation/text_map_propagator.rb +109 -0
  13. data/lib/opentelemetry/context/propagation.rb +62 -7
  14. data/lib/opentelemetry/context/propagation/composite_text_map_propagator.rb +105 -0
  15. data/lib/opentelemetry/context/propagation/noop_text_map_propagator.rb +51 -0
  16. data/lib/opentelemetry/context/propagation/rack_env_getter.rb +48 -0
  17. data/lib/opentelemetry/context/propagation/text_map_getter.rb +27 -0
  18. data/lib/opentelemetry/context/propagation/text_map_propagator.rb +71 -0
  19. data/lib/opentelemetry/context/propagation/text_map_setter.rb +21 -0
  20. data/lib/opentelemetry/internal.rb +17 -0
  21. data/lib/opentelemetry/internal/proxy_tracer.rb +38 -0
  22. data/lib/opentelemetry/internal/proxy_tracer_provider.rb +59 -0
  23. data/lib/opentelemetry/trace/propagation/trace_context.rb +7 -37
  24. data/lib/opentelemetry/trace/propagation/trace_context/text_map_propagator.rb +73 -0
  25. data/lib/opentelemetry/trace/span.rb +20 -0
  26. data/lib/opentelemetry/trace/tracer.rb +2 -2
  27. data/lib/opentelemetry/version.rb +1 -1
  28. metadata +21 -26
  29. data/lib/opentelemetry/baggage/propagation/text_map_extractor.rb +0 -60
  30. data/lib/opentelemetry/baggage/propagation/text_map_injector.rb +0 -55
  31. data/lib/opentelemetry/context/propagation/composite_propagator.rb +0 -73
  32. data/lib/opentelemetry/context/propagation/default_getter.rb +0 -26
  33. data/lib/opentelemetry/context/propagation/default_setter.rb +0 -26
  34. data/lib/opentelemetry/context/propagation/noop_extractor.rb +0 -26
  35. data/lib/opentelemetry/context/propagation/noop_injector.rb +0 -26
  36. data/lib/opentelemetry/context/propagation/propagation.rb +0 -27
  37. data/lib/opentelemetry/context/propagation/propagator.rb +0 -64
  38. data/lib/opentelemetry/instrumentation.rb +0 -15
  39. data/lib/opentelemetry/instrumentation/base.rb +0 -245
  40. data/lib/opentelemetry/instrumentation/registry.rb +0 -86
  41. data/lib/opentelemetry/metrics.rb +0 -16
  42. data/lib/opentelemetry/metrics/handles.rb +0 -44
  43. data/lib/opentelemetry/metrics/instruments.rb +0 -105
  44. data/lib/opentelemetry/metrics/meter.rb +0 -72
  45. data/lib/opentelemetry/metrics/meter_provider.rb +0 -22
  46. data/lib/opentelemetry/trace/propagation/trace_context/text_map_extractor.rb +0 -57
  47. data/lib/opentelemetry/trace/propagation/trace_context/text_map_injector.rb +0 -54
@@ -0,0 +1,109 @@
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
+ # Propagates baggage using the W3C Baggage format
13
+ class TextMapPropagator
14
+ # Maximums according to W3C Baggage spec
15
+ MAX_ENTRIES = 180
16
+ MAX_ENTRY_LENGTH = 4096
17
+ MAX_TOTAL_LENGTH = 8192
18
+
19
+ BAGGAGE_KEY = 'baggage'
20
+ FIELDS = [BAGGAGE_KEY].freeze
21
+
22
+ private_constant :BAGGAGE_KEY, :FIELDS, :MAX_ENTRIES, :MAX_ENTRY_LENGTH, :MAX_TOTAL_LENGTH
23
+
24
+ # Inject in-process baggage into the supplied carrier.
25
+ #
26
+ # @param [Carrier] carrier The mutable carrier to inject baggage into
27
+ # @param [Context] context The context to read baggage from
28
+ # @param [optional Setter] setter If the optional setter is provided, it
29
+ # will be used to write context into the carrier, otherwise the default
30
+ # text map setter will be used.
31
+ def inject(carrier, context: Context.current, setter: Context::Propagation.text_map_setter)
32
+ baggage = OpenTelemetry.baggage.raw_entries(context: context)
33
+
34
+ return if baggage.nil? || baggage.empty?
35
+
36
+ encoded_baggage = encode(baggage)
37
+ setter.set(carrier, BAGGAGE_KEY, encoded_baggage) unless encoded_baggage&.empty?
38
+ nil
39
+ end
40
+
41
+ # Extract remote baggage from the supplied carrier.
42
+ # If extraction fails, the original context will be returned
43
+ #
44
+ # @param [Carrier] carrier The carrier to get the header from
45
+ # @param [optional Context] context Context to be updated with the baggage
46
+ # extracted from the carrier. Defaults to +Context.current+.
47
+ # @param [optional Getter] getter If the optional getter is provided, it
48
+ # will be used to read the header from the carrier, otherwise the default
49
+ # text map getter will be used.
50
+ #
51
+ # @return [Context] context updated with extracted baggage, or the original context
52
+ # if extraction fails
53
+ def extract(carrier, context: Context.current, getter: Context::Propagation.text_map_getter)
54
+ header = getter.get(carrier, BAGGAGE_KEY)
55
+
56
+ entries = header.gsub(/\s/, '').split(',')
57
+
58
+ OpenTelemetry.baggage.build(context: context) do |builder|
59
+ entries.each do |entry|
60
+ # Note metadata is currently unused in OpenTelemetry, but is part
61
+ # the W3C spec where it's referred to as properties. We preserve
62
+ # the properties (as-is) so that they can be propagated elsewhere.
63
+ kv, meta = entry.split(';', 2)
64
+ k, v = kv.split('=').map!(&CGI.method(:unescape))
65
+ builder.set_value(k, v, metadata: meta)
66
+ end
67
+ end
68
+ rescue StandardError => e
69
+ OpenTelemetry.logger.debug "Error extracting W3C baggage: #{e.message}"
70
+ context
71
+ end
72
+
73
+ # Returns the predefined propagation fields. If your carrier is reused, you
74
+ # should delete the fields returned by this method before calling +inject+.
75
+ #
76
+ # @return [Array<String>] a list of fields that will be used by this propagator.
77
+ def fields
78
+ FIELDS
79
+ end
80
+
81
+ private
82
+
83
+ def encode(baggage)
84
+ result = +''
85
+ encoded_count = 0
86
+ baggage.each_pair do |key, entry|
87
+ break unless encoded_count < MAX_ENTRIES
88
+
89
+ encoded_entry = encode_value(key, entry)
90
+ next unless encoded_entry.size <= MAX_ENTRY_LENGTH &&
91
+ encoded_entry.size + result.size <= MAX_TOTAL_LENGTH
92
+
93
+ result << encoded_entry << ','
94
+ encoded_count += 1
95
+ end
96
+ result.chop!
97
+ end
98
+
99
+ def encode_value(key, entry)
100
+ result = +"#{CGI.escape(key.to_s)}=#{CGI.escape(entry.value.to_s)}"
101
+ # We preserve metadata recieved on extract and assume it's already formatted
102
+ # for transport. It's sent as-is without further processing.
103
+ result << ";#{entry.metadata}" if entry.metadata
104
+ result
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -4,19 +4,74 @@
4
4
  #
5
5
  # SPDX-License-Identifier: Apache-2.0
6
6
 
7
- require 'opentelemetry/context/propagation/composite_propagator'
8
- require 'opentelemetry/context/propagation/default_getter'
9
- require 'opentelemetry/context/propagation/default_setter'
10
- require 'opentelemetry/context/propagation/noop_extractor'
11
- require 'opentelemetry/context/propagation/noop_injector'
12
- require 'opentelemetry/context/propagation/propagation'
13
- require 'opentelemetry/context/propagation/propagator'
7
+ require 'opentelemetry/context/propagation/composite_text_map_propagator'
8
+ require 'opentelemetry/context/propagation/noop_text_map_propagator'
9
+ require 'opentelemetry/context/propagation/rack_env_getter'
10
+ require 'opentelemetry/context/propagation/text_map_getter'
11
+ require 'opentelemetry/context/propagation/text_map_propagator'
12
+ require 'opentelemetry/context/propagation/text_map_setter'
14
13
 
15
14
  module OpenTelemetry
16
15
  class Context
17
16
  # The propagation module contains APIs and utilities to interact with context
18
17
  # and propagate across process boundaries.
18
+ #
19
+ # The API implicitly defines 3 interfaces: TextMapPropagator, TextMapInjector
20
+ # and TextMapExtractor. Concrete implementations of TextMapPropagator are
21
+ # provided. Custom text map propagators can leverage these implementations
22
+ # or simply implement the expected interface. The interfaces are described
23
+ # below.
24
+ #
25
+ # The TextMapPropagator interface:
26
+ #
27
+ # inject(carrier, context:, setter:)
28
+ # extract(carrier, context:, getter:) -> Context
29
+ # fields -> Array<String>
30
+ #
31
+ # The TextMapInjector interface:
32
+ #
33
+ # inject(carrier, context:, setter:)
34
+ # fields -> Array<String>
35
+ #
36
+ # The TextMapExtractor interface:
37
+ #
38
+ # extract(carrier, context:, getter:) -> Context
39
+ #
40
+ # The API provides 3 TextMapPropagator implementations:
41
+ # - A default NoopTextMapPropagator that implements +inject+ and +extract+
42
+ # methods as no-ops. Its +fields+ method returns an empty list.
43
+ # - A TextMapPropagator that composes an Injector and an Extractor. Its
44
+ # +fields+ method delegates to the provided Injector.
45
+ # - A CompositeTextMapPropagator that wraps either a list of text map
46
+ # propagators or a list of Injectors and a list of Extractors. Its
47
+ # +fields+ method returns the union of fields returned by the Injectors
48
+ # it wraps.
19
49
  module Propagation
50
+ extend self
51
+
52
+ TEXT_MAP_GETTER = TextMapGetter.new
53
+ TEXT_MAP_SETTER = TextMapSetter.new
54
+ RACK_ENV_GETTER = RackEnvGetter.new
55
+
56
+ private_constant :TEXT_MAP_GETTER, :TEXT_MAP_SETTER, :RACK_ENV_GETTER
57
+
58
+ # Returns a {TextMapGetter} instance suitable for reading values from a
59
+ # hash-like carrier
60
+ def text_map_getter
61
+ TEXT_MAP_GETTER
62
+ end
63
+
64
+ # Returns a {TextMapSetter} instance suitable for writing values into a
65
+ # hash-like carrier
66
+ def text_map_setter
67
+ TEXT_MAP_SETTER
68
+ end
69
+
70
+ # Returns a {RackEnvGetter} instance suitable for reading values from a
71
+ # Rack environment.
72
+ def rack_env_getter
73
+ RACK_ENV_GETTER
74
+ end
20
75
  end
21
76
  end
22
77
  end
@@ -0,0 +1,105 @@
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 text map propagator either composes a list of injectors and a
11
+ # list of extractors, or wraps a list of propagators, into a single interface
12
+ # exposing inject and extract methods. Injection and extraction will preserve
13
+ # the order of the injectors and extractors (or propagators) passed in during
14
+ # initialization.
15
+ class CompositeTextMapPropagator
16
+ class << self
17
+ private :new # rubocop:disable Style/AccessModifierDeclarations
18
+
19
+ # Returns a Propagator that extracts using the provided extractors
20
+ # and injectors.
21
+ #
22
+ # @param [Array<#inject, #fields>] injectors An array of text map injectors
23
+ # @param [Array<#extract>] extractors An array of text map extractors
24
+ def compose(injectors:, extractors:)
25
+ raise ArgumentError, 'injectors and extractors must both be non-nil arrays' unless injectors.is_a?(Array) && extractors.is_a?(Array)
26
+
27
+ new(injectors: injectors, extractors: extractors)
28
+ end
29
+
30
+ # Returns a Propagator that extracts using the provided propagators.
31
+ #
32
+ # @param [Array<#inject, #extract, #fields>] propagators An array of
33
+ # text map propagators
34
+ def compose_propagators(propagators)
35
+ raise ArgumentError, 'propagators must be a non-nil array' unless propagators.is_a?(Array)
36
+ return NoopTextMapPropagator.new if propagators.empty?
37
+ return propagators.first if propagators.size == 1
38
+
39
+ new(propagators: propagators)
40
+ end
41
+ end
42
+
43
+ # @api private
44
+ def initialize(injectors: nil, extractors: nil, propagators: nil)
45
+ @injectors = injectors
46
+ @extractors = extractors
47
+ @propagators = propagators
48
+ end
49
+
50
+ # Runs injectors or propagators in order. If an injection fails
51
+ # a warning will be logged and remaining injectors will be executed.
52
+ #
53
+ # @param [Object] carrier A mutable carrier to inject context into.
54
+ # @param [optional Context] context Context to be injected into carrier. Defaults
55
+ # to +Context.current+.
56
+ # @param [optional Setter] setter If the optional setter is provided, it
57
+ # will be used to write context into the carrier, otherwise the default
58
+ # setter will be used.
59
+ def inject(carrier, context: Context.current, setter: Context::Propagation.text_map_setter)
60
+ injectors = @injectors || @propagators
61
+ injectors.each do |injector|
62
+ injector.inject(carrier, context: context, setter: setter)
63
+ rescue StandardError => e
64
+ OpenTelemetry.logger.warn "Error in CompositePropagator#inject #{e.message}"
65
+ end
66
+ nil
67
+ end
68
+
69
+ # Runs extractors or propagators in order and returns a Context updated
70
+ # with the results of each extraction. If an extraction fails, a warning
71
+ # will be logged and remaining extractors will continue to be executed. Always
72
+ # returns a valid context.
73
+ #
74
+ # @param [Object] carrier The carrier to extract context from.
75
+ # @param [optional Context] context Context to be updated with the state
76
+ # extracted from the carrier. Defaults to +Context.current+.
77
+ # @param [optional Getter] getter If the optional getter is provided, it
78
+ # will be used to read the header from the carrier, otherwise the default
79
+ # getter will be used.
80
+ #
81
+ # @return [Context] a new context updated with state extracted from the
82
+ # carrier
83
+ def extract(carrier, context: Context.current, getter: Context::Propagation.text_map_getter)
84
+ extractors = @extractors || @propagators
85
+ extractors.inject(context) do |ctx, extractor|
86
+ extractor.extract(carrier, context: ctx, getter: getter)
87
+ rescue StandardError => e
88
+ OpenTelemetry.logger.warn "Error in CompositePropagator#extract #{e.message}"
89
+ ctx
90
+ end
91
+ end
92
+
93
+ # Returns the union of the propagation fields returned by the composed injectors
94
+ # or propagators. If your carrier is reused, you should delete the fields returned
95
+ # by this method before calling +inject+.
96
+ #
97
+ # @return [Array<String>] a list of fields that will be used by this propagator.
98
+ def fields
99
+ injectors = @injectors || @propagators
100
+ injectors.flat_map(&fields).uniq
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,51 @@
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 text map propagator implementation
11
+ class NoopTextMapPropagator
12
+ EMPTY_LIST = [].freeze
13
+ private_constant(:EMPTY_LIST)
14
+
15
+ # Injects the provided context into a carrier.
16
+ #
17
+ # @param [Object] carrier A mutable carrier to inject context into.
18
+ # @param [optional Context] context Context to be injected into carrier. Defaults
19
+ # to +Context.current+.
20
+ # @param [optional Setter] setter If the optional setter is provided, it
21
+ # will be used to write context into the carrier, otherwise the default
22
+ # setter will be used.
23
+ def inject(carrier, context: Context.current, setter: Context::Propagation.text_map_setter); end
24
+
25
+ # Extracts and returns context from a carrier. Returns the provided
26
+ # context and logs a warning if an error if extraction fails.
27
+ #
28
+ # @param [Object] carrier The carrier to extract context from.
29
+ # @param [optional Context] context Context to be updated with the state
30
+ # extracted from the carrier. Defaults to +Context.current+.
31
+ # @param [optional Getter] getter If the optional getter is provided, it
32
+ # will be used to read the header from the carrier, otherwise the default
33
+ # getter will be used.
34
+ #
35
+ # @return [Context] a new context updated with state extracted from the
36
+ # carrier
37
+ def extract(carrier, context: Context.current, getter: Context::Propagation.text_map_getter)
38
+ context
39
+ end
40
+
41
+ # Returns the predefined propagation fields. If your carrier is reused, you
42
+ # should delete the fields returned by this method before calling +inject+.
43
+ #
44
+ # @return [Array<String>] a list of fields that will be used by this propagator.
45
+ def fields
46
+ EMPTY_LIST
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,48 @@
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)] || carrier[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
+ ret
36
+ end
37
+
38
+ def from_rack_key(key)
39
+ start = key.start_with?('HTTP_') ? 5 : 0
40
+ ret = key[start..-1]
41
+ ret.tr!('_', '-')
42
+ ret.downcase!
43
+ ret
44
+ end
45
+ end
46
+ end
47
+ end
48
+ 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,71 @@
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 text map propagator that composes an extractor and injector into a
11
+ # single interface exposing inject and extract methods.
12
+ class TextMapPropagator
13
+ # Returns a Propagator that delegates inject and extract to the provided
14
+ # injector and extractor
15
+ #
16
+ # @param [#inject] injector
17
+ # @param [#extract] extractor
18
+ def initialize(injector, extractor)
19
+ raise ArgumentError, 'injector and extractor must both be non-nil' if injector.nil? || extractor.nil?
20
+
21
+ @injector = injector
22
+ @extractor = extractor
23
+ end
24
+
25
+ # Injects the provided context into a carrier using the underlying
26
+ # injector. Logs a warning if injection fails.
27
+ #
28
+ # @param [Object] carrier A mutable carrier to inject context into.
29
+ # @param [optional Context] context Context to be injected into carrier. Defaults
30
+ # to +Context.current+.
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
+ def inject(carrier, context: Context.current, setter: Context::Propagation.text_map_setter)
35
+ @injector.inject(carrier, context, setter)
36
+ nil
37
+ rescue StandardError => e
38
+ OpenTelemetry.logger.warn "Error in Propagator#inject #{e.message}"
39
+ nil
40
+ end
41
+
42
+ # Extracts and returns context from a carrier. Returns the provided
43
+ # context and logs a warning if an error if extraction fails.
44
+ #
45
+ # @param [Object] carrier The carrier to extract context from.
46
+ # @param [optional Context] context Context to be updated with the state
47
+ # extracted from the carrier. Defaults to +Context.current+.
48
+ # @param [optional Getter] getter If the optional getter is provided, it
49
+ # will be used to read the header from the carrier, otherwise the default
50
+ # getter will be used.
51
+ #
52
+ # @return [Context] a new context updated with state extracted from the
53
+ # carrier
54
+ def extract(carrier, context: Context.current, getter: Context::Propagation.text_map_getter)
55
+ @extractor.extract(carrier, context, getter)
56
+ rescue StandardError => e
57
+ OpenTelemetry.logger.warn "Error in Propagator#extract #{e.message}"
58
+ context
59
+ end
60
+
61
+ # Returns the predefined propagation fields. If your carrier is reused, you
62
+ # should delete the fields returned by this method before calling +inject+.
63
+ #
64
+ # @return [Array<String>] a list of fields that will be used by this propagator.
65
+ def fields
66
+ @injector.fields
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end