opentelemetry-api 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +9 -0
  3. data/OVERVIEW.md +66 -0
  4. data/lib/{opentelemetry/distributed_context/manager.rb → opentelemetry-api.rb} +1 -6
  5. data/lib/opentelemetry.rb +34 -16
  6. data/lib/opentelemetry/context.rb +138 -15
  7. data/lib/opentelemetry/context/key.rb +29 -0
  8. data/lib/opentelemetry/context/propagation.rb +22 -0
  9. data/lib/opentelemetry/context/propagation/composite_propagator.rb +77 -0
  10. data/lib/opentelemetry/context/propagation/default_getter.rb +26 -0
  11. data/lib/opentelemetry/context/propagation/default_setter.rb +26 -0
  12. data/lib/opentelemetry/context/propagation/noop_extractor.rb +26 -0
  13. data/lib/opentelemetry/context/propagation/noop_injector.rb +26 -0
  14. data/lib/opentelemetry/context/propagation/propagation.rb +27 -0
  15. data/lib/opentelemetry/context/propagation/propagator.rb +64 -0
  16. data/lib/opentelemetry/correlation_context.rb +16 -0
  17. data/lib/opentelemetry/correlation_context/builder.rb +18 -0
  18. data/lib/opentelemetry/correlation_context/manager.rb +36 -0
  19. data/lib/opentelemetry/correlation_context/propagation.rb +57 -0
  20. data/lib/opentelemetry/correlation_context/propagation/context_keys.rb +27 -0
  21. data/lib/opentelemetry/correlation_context/propagation/text_extractor.rb +60 -0
  22. data/lib/opentelemetry/correlation_context/propagation/text_injector.rb +55 -0
  23. data/lib/opentelemetry/instrumentation.rb +15 -0
  24. data/lib/opentelemetry/instrumentation/adapter.rb +244 -0
  25. data/lib/opentelemetry/instrumentation/registry.rb +87 -0
  26. data/lib/opentelemetry/metrics.rb +1 -1
  27. data/lib/opentelemetry/metrics/handles.rb +5 -15
  28. data/lib/opentelemetry/metrics/instruments.rb +18 -69
  29. data/lib/opentelemetry/metrics/meter.rb +2 -39
  30. data/lib/opentelemetry/metrics/{meter_factory.rb → meter_provider.rb} +2 -2
  31. data/lib/opentelemetry/trace.rb +2 -2
  32. data/lib/opentelemetry/trace/event.rb +4 -3
  33. data/lib/opentelemetry/trace/link.rb +4 -3
  34. data/lib/opentelemetry/trace/propagation.rb +17 -0
  35. data/lib/opentelemetry/trace/propagation/context_keys.rb +35 -0
  36. data/lib/opentelemetry/trace/propagation/trace_context.rb +59 -0
  37. data/lib/opentelemetry/trace/propagation/trace_context/text_extractor.rb +58 -0
  38. data/lib/opentelemetry/trace/propagation/trace_context/text_injector.rb +55 -0
  39. data/lib/opentelemetry/trace/propagation/trace_context/trace_parent.rb +126 -0
  40. data/lib/opentelemetry/trace/span.rb +14 -6
  41. data/lib/opentelemetry/trace/status.rb +7 -2
  42. data/lib/opentelemetry/trace/tracer.rb +47 -13
  43. data/lib/opentelemetry/trace/tracer_provider.rb +22 -0
  44. data/lib/opentelemetry/trace/util/http_to_status.rb +47 -0
  45. data/lib/opentelemetry/version.rb +1 -1
  46. metadata +33 -13
  47. data/lib/opentelemetry/distributed_context.rb +0 -19
  48. data/lib/opentelemetry/distributed_context/distributed_context.rb +0 -24
  49. data/lib/opentelemetry/distributed_context/entry.rb +0 -66
  50. data/lib/opentelemetry/distributed_context/propagation.rb +0 -19
  51. data/lib/opentelemetry/distributed_context/propagation/binary_format.rb +0 -26
  52. data/lib/opentelemetry/distributed_context/propagation/text_format.rb +0 -76
  53. data/lib/opentelemetry/distributed_context/propagation/trace_parent.rb +0 -124
  54. data/lib/opentelemetry/trace/sampling_hint.rb +0 -22
  55. data/lib/opentelemetry/trace/tracer_factory.rb +0 -45
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2020 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ require 'opentelemetry/instrumentation/registry'
8
+ require 'opentelemetry/instrumentation/adapter'
9
+
10
+ module OpenTelemetry
11
+ # The instrumentation module contains functionality to register and install
12
+ # instrumentation adapters
13
+ module Instrumentation
14
+ end
15
+ end
@@ -0,0 +1,244 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2020 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ module Instrumentation
9
+ # The Adapter class holds all metadata and configuration for an
10
+ # instrumentation adapter. All instrumentation adapter packages should
11
+ # include a subclass of +Instrumentation::Adapter+ that will register
12
+ # it with +OpenTelemetry.instrumentation_registry+ and make it available for
13
+ # discovery and installation by an SDK.
14
+ #
15
+ # A typical subclass of Adapter will provide an install block, a present
16
+ # block, and possibly a compatible block. Below is an
17
+ # example:
18
+ #
19
+ # module OpenTelemetry
20
+ # module Adapters
21
+ # module Sinatra
22
+ # class Adapter < OpenTelemetry::Instrumentation::Adapter
23
+ # install do |config|
24
+ # # install instrumentation, either by library hook or applying
25
+ # # a monkey patch
26
+ # end
27
+ #
28
+ # # determine if the target library is present
29
+ # present do
30
+ # defined?(::Sinatra)
31
+ # end
32
+ #
33
+ # # if the target library is present, is it compatible?
34
+ # compatible do
35
+ # Gem.loaded_specs['sinatra'].version > MIN_VERSION
36
+ # end
37
+ # end
38
+ # end
39
+ # end
40
+ # end
41
+ #
42
+ # The adapter name and version will be inferred from the namespace of the
43
+ # class. In this example, they'd be 'OpenTelemetry::Adapters::Sinatra' and
44
+ # OpenTelemetry::Adapters::Sinatra::VERSION, but can be explicitly set using
45
+ # the +adapter_name+ and +adapter_version+ methods if necessary.
46
+ #
47
+ # All subclasses of OpenTelemetry::Instrumentation::Adapter are automatically
48
+ # registered with OpenTelemetry.instrumentation_registry which is used by
49
+ # SDKs for instrumentation discovery and installation.
50
+ #
51
+ # Instrumentation libraries can use the adapter subclass to easily gain
52
+ # a reference to its named tracer. For example:
53
+ #
54
+ # OpenTelemetry::Adapters::Sinatra.instance.tracer
55
+ #
56
+ # The adapter class establishes a convention for disabling an adapter
57
+ # by environment variable and local configuration. An adapter disabled
58
+ # by environment variable will take precedence over local config. The
59
+ # convention for environment variable name is the library name, upcased with
60
+ # '::' replaced by underscores, and '_ENABLED' appended. For example:
61
+ # OPENTELEMETRY_ADAPTERS_SINATRA_ENABLED = false.
62
+ class Adapter
63
+ class << self
64
+ NAME_REGEX = /^(?:(?<namespace>[a-zA-Z0-9_:]+):{2})?(?<classname>[a-zA-Z0-9_]+)$/.freeze
65
+ private_constant :NAME_REGEX
66
+
67
+ private :new # rubocop:disable Style/AccessModifierDeclarations
68
+
69
+ def inherited(subclass)
70
+ OpenTelemetry.instrumentation_registry.register(subclass)
71
+ end
72
+
73
+ # Optionally set the name of this instrumentation adapter. If not
74
+ # explicitly set, the name will default to the namespace of the class,
75
+ # or the class name if it does not have a namespace. If there is not
76
+ # a namespace, or a class name, it will default to 'unknown'.
77
+ #
78
+ # @param [String] adapter_name The full name of the adapter package
79
+ def adapter_name(adapter_name = nil)
80
+ if adapter_name
81
+ @adapter_name = adapter_name
82
+ else
83
+ @adapter_name ||= infer_name || 'unknown'
84
+ end
85
+ end
86
+
87
+ # Optionally set the version of this adapter. If not explicitly set,
88
+ # the version will default to the VERSION constant under namespace of
89
+ # the class, or the VERSION constant under the class name if it does not
90
+ # have a namespace. If a VERSION constant cannot be found, it defaults
91
+ # to '0.0.0'.
92
+ #
93
+ # @param [String] adapter_version The version of the adapter package
94
+ def adapter_version(adapter_version = nil)
95
+ if adapter_version
96
+ @adapter_version = adapter_version
97
+ else
98
+ @adapter_version ||= infer_version || '0.0.0'
99
+ end
100
+ end
101
+
102
+ # The install block for this adapter. This will be where you install
103
+ # instrumentation, either by framework hook or applying a monkey patch.
104
+ #
105
+ # @param [Callable] blk The install block for this adapter
106
+ # @yieldparam [Hash] config The adapter config will be yielded to the
107
+ # install block
108
+ def install(&blk)
109
+ @install_blk = blk
110
+ end
111
+
112
+ # The present block for this adapter. This block is used to detect if
113
+ # target library is present on the system. Typically this will involve
114
+ # checking to see if the target gem spec was loaded or if expected
115
+ # constants from the target library are present.
116
+ #
117
+ # @param [Callable] blk The present block for this adapter
118
+ def present(&blk)
119
+ @present_blk = blk
120
+ end
121
+
122
+ # The compatible block for this adapter. This check will be run if the
123
+ # target library is present to determine if it's compatible. It's not
124
+ # required, but a common use case will be to check to target library
125
+ # version for compatibility.
126
+ #
127
+ # @param [Callable] blk The compatibility block for this adapter
128
+ def compatible(&blk)
129
+ @compatible_blk = blk
130
+ end
131
+
132
+ def instance
133
+ @instance ||= new(adapter_name, adapter_version, install_blk,
134
+ present_blk, compatible_blk)
135
+ end
136
+
137
+ private
138
+
139
+ attr_reader :install_blk, :present_blk, :compatible_blk
140
+
141
+ def infer_name
142
+ @inferred_name ||= if (md = name.match(NAME_REGEX)) # rubocop:disable Naming/MemoizedInstanceVariableName
143
+ md['namespace'] || md['classname']
144
+ end
145
+ end
146
+
147
+ def infer_version
148
+ return unless (inferred_name = infer_name)
149
+
150
+ mod = inferred_name.split('::').map(&:to_sym).inject(Object) do |object, const|
151
+ object.const_get(const)
152
+ end
153
+ mod.const_get(:VERSION)
154
+ rescue NameError
155
+ nil
156
+ end
157
+ end
158
+
159
+ attr_reader :name, :version, :config, :installed, :tracer
160
+
161
+ alias installed? installed
162
+
163
+ def initialize(name, version, install_blk, present_blk,
164
+ compatible_blk)
165
+ @name = name
166
+ @version = version
167
+ @install_blk = install_blk
168
+ @present_blk = present_blk
169
+ @compatible_blk = compatible_blk
170
+ @config = {}
171
+ @installed = false
172
+ end
173
+
174
+ # Install adapter with the given config. The present? and compatible?
175
+ # will be run first, and install will return false if either fail. Will
176
+ # return true if install was completed successfully.
177
+ #
178
+ # @param [Hash] config The config for this adapter
179
+ def install(config = {})
180
+ return true if installed?
181
+ return false unless installable?(config)
182
+
183
+ @config = config unless config.nil?
184
+ instance_exec(@config, &@install_blk)
185
+ @tracer ||= OpenTelemetry.tracer_provider.tracer(name, version)
186
+ @installed = true
187
+ end
188
+
189
+ # Whether or not this adapter is installable in the current process. Will
190
+ # be true when the adapter defines an install block, is not disabled
191
+ # by environment or config, and the target library present and compatible.
192
+ #
193
+ # @param [Hash] config The config for this adapter
194
+ def installable?(config = {})
195
+ @install_blk && enabled?(config) && present? && compatible?
196
+ end
197
+
198
+ # Calls the present block of the Adapter subclasses, if no block is provided
199
+ # it's assumed the adapter is not present
200
+ def present?
201
+ return false unless @present_blk
202
+
203
+ instance_exec(&@present_blk)
204
+ end
205
+
206
+ # Calls the compatible block of the Adapter subclasses, if no block is provided
207
+ # it's assumed to be compatible
208
+ def compatible?
209
+ return true unless @compatible_blk
210
+
211
+ instance_exec(&@compatible_blk)
212
+ end
213
+
214
+ # Whether this adapter is enabled. It first checks to see if it's enabled
215
+ # by an environment variable and will proceed to check if it's enabled
216
+ # by local config, if given.
217
+ #
218
+ # @param [optional Hash] config The local config
219
+ def enabled?(config = nil)
220
+ return false unless enabled_by_env_var?
221
+ return config[:enabled] if config&.key?(:enabled)
222
+
223
+ true
224
+ end
225
+
226
+ private
227
+
228
+ # Checks to see if this adapter is enabled by env var. By convention, the
229
+ # environment variable will be the adapter name upper cased, with '::'
230
+ # replaced by underscores and _ENABLED appended. For example, the
231
+ # environment variable name for OpenTelemetry::Adapter::Sinatra will be
232
+ # OPENTELEMETRY_ADAPTERS_SINATRA_ENABLED. A value of 'false' will disable
233
+ # the adapter, all other values will enable it.
234
+ def enabled_by_env_var?
235
+ var_name = name.dup.tap do |n|
236
+ n.upcase!
237
+ n.gsub!('::', '_')
238
+ n << '_ENABLED'
239
+ end
240
+ ENV[var_name] != 'false'
241
+ end
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2020 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ module Instrumentation
9
+ # The instrumentation Registry contains information about instrumentation
10
+ # adapters available and facilitates discovery, installation and
11
+ # configuration. This functionality is primarily useful for SDK
12
+ # implementors.
13
+ class Registry
14
+ def initialize
15
+ @lock = Mutex.new
16
+ @adapters = []
17
+ end
18
+
19
+ # @api private
20
+ def register(adapter)
21
+ @lock.synchronize do
22
+ @adapters << adapter
23
+ end
24
+ end
25
+
26
+ # Lookup an adapter definition by name. Returns nil if +adapter_name+
27
+ # is not found.
28
+ #
29
+ # @param [String] adapter_name A stringified class name for an adapter
30
+ # @return [Adapter]
31
+ def lookup(adapter_name)
32
+ @lock.synchronize do
33
+ find_adapter(adapter_name)
34
+ end
35
+ end
36
+
37
+ # Install the specified adapters with optionally specified configuration.
38
+ #
39
+ # @param [Array<String>] adapter_names An array of adapter names to
40
+ # install
41
+ # @param [optional Hash<String, Hash>] adapter_config_map A map of
42
+ # adapter_name to config. This argument is optional and config can be
43
+ # passed for as many or as few adapters as desired.
44
+ def install(adapter_names, adapter_config_map = {})
45
+ @lock.synchronize do
46
+ adapter_names.each do |adapter_name|
47
+ adapter = find_adapter(adapter_name)
48
+ OpenTelemetry.logger.warn "Could not install #{adapter_name} because it was not found" unless adapter
49
+
50
+ install_adapter(adapter, adapter_config_map[adapter.name])
51
+ end
52
+ end
53
+ end
54
+
55
+ # Install all instrumentation available and installable in this process.
56
+ #
57
+ # @param [optional Hash<String, Hash>] adapter_config_map A map of
58
+ # adapter_name to config. This argument is optional and config can be
59
+ # passed for as many or as few adapters as desired.
60
+ def install_all(adapter_config_map = {})
61
+ @lock.synchronize do
62
+ @adapters.map(&:instance).each do |adapter|
63
+ install_adapter(adapter, adapter_config_map[adapter.name])
64
+ end
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def find_adapter(adapter_name)
71
+ @adapters.detect { |a| a.instance.name == adapter_name }
72
+ &.instance
73
+ end
74
+
75
+ def install_adapter(adapter, config)
76
+ if adapter.install(config)
77
+ OpenTelemetry.logger.info "Adapter: #{adapter.name} was successfully installed"
78
+ else
79
+ OpenTelemetry.logger.warn "Adapter: #{adapter.name} failed to install"
80
+ end
81
+ rescue => e # rubocop:disable Style/RescueStandardError
82
+ OpenTelemetry.logger.warn "Adapter: #{adapter.name} unhandled exception" \
83
+ "during install #{e}: #{e.backtrace}"
84
+ end
85
+ end
86
+ end
87
+ end
@@ -7,7 +7,7 @@
7
7
  require 'opentelemetry/metrics/handles'
8
8
  require 'opentelemetry/metrics/instruments'
9
9
  require 'opentelemetry/metrics/meter'
10
- require 'opentelemetry/metrics/meter_factory'
10
+ require 'opentelemetry/metrics/meter_provider'
11
11
 
12
12
  module OpenTelemetry
13
13
  # The Metrics API allows reporting raw measurements as well as metrics with known aggregation and labels.
@@ -7,29 +7,19 @@
7
7
  module OpenTelemetry
8
8
  module Metrics
9
9
  # In situations where performance is a requirement and a metric is
10
- # repeatedly used with the same set of labels, the developer may elect to
10
+ # repeatedly used with the same labels, the developer may elect to
11
11
  # use instrument {Handles} as an optimization. For handles to be a benefit,
12
12
  # it requires that a specific instrument will be re-used with specific
13
- # labels. If an instrument will be used with the same label set more than
14
- # once, obtaining an instrument handle corresponding to the label set
13
+ # labels. If an instrument will be used with the same labels more than
14
+ # once, obtaining an instrument handle corresponding to the labels
15
15
  # ensures the highest performance available.
16
16
  #
17
- # To obtain a handle given an instrument and label set, use the #handle
18
- # method to return an interface that supports the #add, #set, or #record
17
+ # To obtain a handle given an instrument and labels, use the #handle
18
+ # method to return an interface that supports the #add or #record
19
19
  # method of the instrument in question.
20
20
  #
21
21
  # Instrument handles may consume SDK resources indefinitely.
22
22
  module Handles
23
- # A float gauge handle.
24
- class FloatGauge
25
- def set(value); end
26
- end
27
-
28
- # An integer gauge handle.
29
- class IntegerGauge
30
- def set(value); end
31
- end
32
-
33
23
  # A float counter handle.
34
24
  class FloatCounter
35
25
  def add(value); end
@@ -13,67 +13,19 @@ module OpenTelemetry
13
13
  # program to record observations about their behavior. Therefore, we use
14
14
  # "metric instrument" to refer to a program object, allocated through the
15
15
  # API, used for recording metrics. There are three distinct instruments in
16
- # the Metrics API, commonly known as Counters, Gauges, and Measures.
16
+ # the Metrics API, commonly known as Counters, Observers, and Measures.
17
17
  module Instruments
18
- # A float gauge instrument.
19
- class FloatGauge
20
- # Set the value of the gauge.
21
- #
22
- # @param [Float] value The value to set.
23
- # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
24
- # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
25
- def set(value, labels_or_label_set = {}); end
26
-
27
- # Obtain a handle from the instrument and label set.
28
- #
29
- # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
30
- # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
31
- # @return [Handles::FloatGauge]
32
- def handle(labels_or_label_set = {})
33
- Handles::FloatGauge.new
34
- end
35
-
36
- # Return a measurement to be recorded via {Meter#record_batch}.
37
- #
38
- # @param [Float] value
39
- # @return [Object, Measurement]
40
- def measurement(value)
41
- NOOP_MEASUREMENT
42
- end
43
- end
44
-
45
- # An integer gauge instrument.
46
- class IntegerGauge
47
- def set(value, labels_or_label_set = {}); end
48
-
49
- # Obtain a handle from the instrument and label set.
50
- #
51
- # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
52
- # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
53
- # @return [Handles::IntegerGauge]
54
- def handle(labels_or_label_set = {})
55
- Handles::IntegerGauge.new
56
- end
57
-
58
- # Return a measurement to be recorded via {Meter#record_batch}.
59
- #
60
- # @param [Integer] value
61
- # @return [Object, Measurement]
62
- def measurement(value)
63
- NOOP_MEASUREMENT
64
- end
65
- end
18
+ # TODO: Observers.
66
19
 
67
20
  # A float counter instrument.
68
21
  class FloatCounter
69
- def add(value, labels_or_label_set = {}); end
22
+ def add(value, labels = {}); end
70
23
 
71
- # Obtain a handle from the instrument and label set.
24
+ # Obtain a handle from the instrument and labels.
72
25
  #
73
- # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
74
- # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
26
+ # @param [optional Hash<String, String>] labels A Hash of Strings.
75
27
  # @return [Handles::FloatCounter]
76
- def handle(labels_or_label_set = {})
28
+ def handle(labels = {})
77
29
  Handles::FloatCounter.new
78
30
  end
79
31
 
@@ -88,14 +40,13 @@ module OpenTelemetry
88
40
 
89
41
  # An integer counter instrument.
90
42
  class IntegerCounter
91
- def add(value, labels_or_label_set = {}); end
43
+ def add(value, labels = {}); end
92
44
 
93
- # Obtain a handle from the instrument and label set.
45
+ # Obtain a handle from the instrument and labels.
94
46
  #
95
- # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
96
- # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
47
+ # @param [optional Hash<String, String>] labels A Hash of Strings.
97
48
  # @return [Handles::IntegerCounter]
98
- def handle(labels_or_label_set = {})
49
+ def handle(labels = {})
99
50
  Handles::IntegerCounter.new
100
51
  end
101
52
 
@@ -110,14 +61,13 @@ module OpenTelemetry
110
61
 
111
62
  # A float measure instrument.
112
63
  class FloatMeasure
113
- def record(value, labels_or_label_set = {}); end
64
+ def record(value, labels = {}); end
114
65
 
115
- # Obtain a handle from the instrument and label set.
66
+ # Obtain a handle from the instrument and labels.
116
67
  #
117
- # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
118
- # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
68
+ # @param [optional Hash<String, String>] labels A Hash of Strings.
119
69
  # @return [Handles::FloatMeasure]
120
- def handle(labels_or_label_set = {})
70
+ def handle(labels = {})
121
71
  Handles::FloatMeasure.new
122
72
  end
123
73
 
@@ -132,14 +82,13 @@ module OpenTelemetry
132
82
 
133
83
  # An integer measure instrument.
134
84
  class IntegerMeasure
135
- def record(value, labels_or_label_set = {}); end
85
+ def record(value, labels = {}); end
136
86
 
137
- # Obtain a handle from the instrument and label set.
87
+ # Obtain a handle from the instrument and labels.
138
88
  #
139
- # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
140
- # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
89
+ # @param [optional Hash<String, String>] labels A Hash of Strings.
141
90
  # @return [Handles::IntegerMeasure]
142
- def handle(labels_or_label_set = {})
91
+ def handle(labels = {})
143
92
  Handles::IntegerMeasure.new
144
93
  end
145
94