opentelemetry-metrics-api 0.7.1 → 0.9.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: ea4f3c76493a7fd16c6c17457eadc82abde93f7124ec22c5697c8e6eb38fc932
4
- data.tar.gz: 8fbeff160a5f21e9641fd0d4007ab1b9cd020f81fe08794f88bc3b0ce2ae4b15
3
+ metadata.gz: '01447149549ce311507e50a73b1c25962ea229f9d30fee3878ca09b519e278ba'
4
+ data.tar.gz: c7cf8d92fd0a56ee620a0c465f10178dde5773652482ca02b607fd3db06d4884
5
5
  SHA512:
6
- metadata.gz: 1f042a80106a1445534b5f9f7e17dbbf99f773898827d3877aed6e984653cff26b5c9c61abc64db2467d2fc3752602af286ae2635ffdf39ab525558f0d6908c5
7
- data.tar.gz: a0c2d36c901f160ba9f426f969a1e43127624f3d286f013252fa68cdc2c3f80abc1a483e9da40720669e1c706c3acfc34faaaaa18612bb47662fdcbe8630999f
6
+ metadata.gz: fb53b43bcbce42330ba77fc382e398f6972cbe7b643d346bd6afe63fc7e354fac8f0874bb56858fea667e5015e21a5c8ac2dcb15cb67a34b0da847b2f7b5d9e0
7
+ data.tar.gz: 6ffc9da9c4603ded64ba39f805bc73f4bd37dea3044e306e97f6a217e2efca1823801331c07083b146b2dd1807f42a95142ef8966811df6aba7d8b6443064bae
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Release History: opentelemetry-metrics-api
2
2
 
3
+ ### v0.9.0 / 2026-10-05
4
+
5
+ * BREAKING CHANGE: Move the global meter provider behind an opt-in require (#2416)
6
+ * ADDED: Move the global meter provider behind an opt-in require (#2416)
7
+
8
+ ### v0.8.0 / 2026-09-29
9
+
10
+ * BREAKING CHANGE: Update api for spec compliance (#2309)
11
+ * ADDED: Update api for spec compliance (#2309)
12
+
3
13
  ### v0.7.1 / 2026-09-15
4
14
 
5
15
  * FIXED: Pass the callback through when upgrading a proxy instrument (#2377)
data/README.md CHANGED
@@ -22,18 +22,24 @@ This code is still under development and is not a complete implementation of the
22
22
 
23
23
  ## How do I get started?
24
24
 
25
- Install the gem using:
25
+ Install the gems using:
26
26
 
27
27
  ```sh
28
- gem install opentelemetry-metrics-api
28
+ gem install opentelemetry-sdk
29
+ gem install opentelemetry-metrics-sdk
29
30
  ```
30
31
 
31
- Or, if you use [bundler][bundler-home], include `opentelemetry-metrics-api` in your `Gemfile`.
32
+ Or, if you use [bundler][bundler-home], include `opentelemetry-sdk` and `opentelemetry-metrics-sdk` in your `Gemfile`. The SDK depends on `opentelemetry-metrics-api`.
32
33
 
33
- Then, use the OpenTelemetry interfaces to produces traces and other telemetry data. Following is a basic example.
34
+ Requiring `opentelemetry-metrics-sdk` defines the global `OpenTelemetry.meter_provider` accessor. Requiring `opentelemetry-metrics-api` on its own does not. See [Upgrading to 0.9.0](#upgrading-to-090).
35
+
36
+ Then, use the OpenTelemetry interfaces to produce metrics and other telemetry data. Following is a basic example.
34
37
 
35
38
  ```ruby
36
- require 'opentelemetry-metrics-api'
39
+ require 'opentelemetry/sdk'
40
+ require 'opentelemetry-metrics-sdk'
41
+
42
+ OpenTelemetry::SDK.configure
37
43
 
38
44
  # Obtain the current default meter provider
39
45
  provider = OpenTelemetry.meter_provider
@@ -50,6 +56,20 @@ histogram.record(123, attributes: {'foo' => 'bar'})
50
56
 
51
57
  For additional examples, see the [examples on github][examples-github].
52
58
 
59
+ ## Upgrading to 0.9.0
60
+
61
+ The Metrics API is experimental. To keep it off the public `OpenTelemetry` module until it stabilizes, `opentelemetry-metrics-api` 0.9.0 no longer defines `OpenTelemetry.meter_provider` or `OpenTelemetry.meter_provider=`. `opentelemetry-metrics-sdk` 0.20.0 and later define both when required.
62
+
63
+ - **Applications using `opentelemetry-metrics-sdk`:** Upgrade the SDK to 0.20.0 or later. No code changes are needed.
64
+ - **Code that requires only `opentelemetry-metrics-api`:** Calling `OpenTelemetry.meter_provider` raises `NoMethodError`. Require `opentelemetry-metrics-sdk`, or `opentelemetry/metrics/global` to define the accessors without the SDK.
65
+ - **Applications on `opentelemetry-metrics-sdk` 0.19.0 or earlier:** These versions allow `opentelemetry-metrics-api` 0.9.0, so bundler can pair them. A compatibility shim in the API keeps them working and logs this warning:
66
+
67
+ ```text
68
+ opentelemetry-metrics-sdk 0.19.0 and earlier register the global meter provider through a compatibility shim in opentelemetry-metrics-api. Upgrade to opentelemetry-metrics-sdk 0.20.0 or later.
69
+ ```
70
+
71
+ The shim will be removed in a future release ([#2414][2414]). Upgrade the SDK to clear the warning.
72
+
53
73
  ## How can I get involved?
54
74
 
55
75
  The `opentelemetry-metrics-api` gem source is [on github][repo-github], along with related gems including `opentelemetry-metrics-sdk`.
@@ -76,3 +96,4 @@ The `opentelemetry-api` gem is distributed under the Apache 2.0 license. See [LI
76
96
  [community-meetings]: https://github.com/open-telemetry/community#community-meetings
77
97
  [discussions-url]: https://github.com/open-telemetry/opentelemetry-ruby/discussions
78
98
  [1662]: https://github.com/open-telemetry/opentelemetry-ruby/issues/1662
99
+ [2414]: https://github.com/open-telemetry/opentelemetry-ruby/issues/2414
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright The OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ # @api private
9
+ module Internal
10
+ @meter_provider = ProxyMeterProvider.new
11
+ @meter_provider_mutex = Mutex.new
12
+
13
+ class << self
14
+ # Registers the process-wide meter provider that instrumentation reads
15
+ # from. The public +OpenTelemetry.meter_provider+ accessor, defined in
16
+ # +opentelemetry/metrics/global+, delegates here.
17
+ #
18
+ # @param [MeterProvider] provider A meter provider to register as the
19
+ # global instance.
20
+ def meter_provider=(provider)
21
+ @meter_provider_mutex.synchronize do
22
+ if @meter_provider.instance_of?(ProxyMeterProvider)
23
+ OpenTelemetry.logger.debug("Upgrading default proxy meter provider to #{provider.class}")
24
+ @meter_provider.delegate = provider
25
+ end
26
+ @meter_provider = provider
27
+ end
28
+ end
29
+
30
+ # @return [Object, Metrics::MeterProvider] registered meter provider or a
31
+ # default no-op implementation of the meter provider.
32
+ def meter_provider
33
+ @meter_provider_mutex.synchronize { @meter_provider }
34
+ end
35
+ end
36
+ end
37
+ end
@@ -8,25 +8,30 @@ module OpenTelemetry
8
8
  module Internal
9
9
  # @api private
10
10
  class ProxyInstrument
11
- def initialize(kind, name, unit, desc, callback, exemplar_filter, exemplar_reservoir)
11
+ def initialize(kind, name, unit, desc, callback, exemplar_filter, exemplar_reservoir, advisory = nil)
12
12
  @kind = kind
13
13
  @name = name
14
14
  @unit = unit
15
15
  @desc = desc
16
16
  @callback = callback
17
- @exemplar_filter = exemplar_filter
18
- @exemplar_reservoir = exemplar_reservoir
17
+ @exemplar_filter = exemplar_filter
18
+ @exemplar_reservoir = exemplar_reservoir
19
+ @advisory = advisory
20
+ @registered_callbacks = []
19
21
  @delegate = nil
20
22
  end
21
23
 
22
24
  # Replaces the no-op delegate with a real instrument from the given meter.
23
25
  def upgrade_with(meter)
24
26
  @delegate = case @kind
25
- when :counter, :histogram, :up_down_counter
26
- meter.send("create_#{@kind}", @name, unit: @unit, description: @desc, exemplar_filter: @exemplar_filter, exemplar_reservoir: @exemplar_reservoir)
27
+ when :counter, :histogram, :up_down_counter, :gauge
28
+ meter.send("create_#{@kind}", @name, unit: @unit, description: @desc, exemplar_filter: @exemplar_filter, exemplar_reservoir: @exemplar_reservoir, advisory: @advisory)
27
29
  when :observable_counter, :observable_gauge, :observable_up_down_counter
28
- meter.send("create_#{@kind}", @name, unit: @unit, description: @desc, exemplar_filter: @exemplar_filter, exemplar_reservoir: @exemplar_reservoir, callback: @callback)
30
+ meter.send("create_#{@kind}", @name, unit: @unit, description: @desc, exemplar_filter: @exemplar_filter, exemplar_reservoir: @exemplar_reservoir, callback: @callback, advisory: @advisory)
29
31
  end
32
+ @registered_callbacks.each do |callback|
33
+ @delegate.register_callback(callback) if @delegate.respond_to?(:register_callback)
34
+ end
30
35
  end
31
36
 
32
37
  # Delegates to the upgraded instrument's #add, if any.
@@ -38,6 +43,34 @@ module OpenTelemetry
38
43
  def record(amount, attributes: nil)
39
44
  @delegate&.record(amount, attributes: attributes)
40
45
  end
46
+
47
+ # Delegates to the upgraded instrument's #enabled?, false (disabled) until upgraded.
48
+ def enabled?
49
+ @delegate ? @delegate.enabled? : false
50
+ end
51
+
52
+ # Delegates to the upgraded instrument's #bind, if any; returns self (no-op) until upgraded.
53
+ def bind(attributes: {})
54
+ @delegate ? @delegate.bind(attributes: attributes) : self
55
+ end
56
+
57
+ # Delegates to the underlying instrument, or queues the callback until the delegate is set.
58
+ def register_callback(callback)
59
+ if @delegate
60
+ @delegate.register_callback(callback)
61
+ else
62
+ @registered_callbacks << callback
63
+ end
64
+ end
65
+
66
+ # Delegates to the underlying instrument, or removes the callback from the queue.
67
+ def unregister(callback)
68
+ if @delegate
69
+ @delegate.unregister(callback)
70
+ else
71
+ @registered_callbacks.delete(callback)
72
+ end
73
+ end
41
74
  end
42
75
  end
43
76
  end
@@ -38,18 +38,18 @@ module OpenTelemetry
38
38
 
39
39
  private
40
40
 
41
- def create_instrument(kind, name, unit, description, callback, exemplar_filter, exemplar_reservoir)
41
+ def create_instrument(kind, name, unit, description, callback, exemplar_filter, exemplar_reservoir, advisory)
42
42
  super do
43
- next ProxyInstrument.new(kind, name, unit, description, callback, exemplar_filter, exemplar_reservoir) if @delegate.nil?
43
+ next ProxyInstrument.new(kind, name, unit, description, callback, exemplar_filter, exemplar_reservoir, advisory) if @delegate.nil?
44
44
 
45
45
  case kind
46
- when :counter then @delegate.create_counter(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir)
47
- when :histogram then @delegate.create_histogram(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir)
48
- when :up_down_counter then @delegate.create_up_down_counter(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir)
49
- when :gauge then @delegate.create_gauge(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir)
50
- when :observable_counter then @delegate.create_observable_counter(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir, callback: callback)
51
- when :observable_gauge then @delegate.create_observable_gauge(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir, callback: callback)
52
- when :observable_up_down_counter then @delegate.create_observable_up_down_counter(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir, callback: callback)
46
+ when :counter then @delegate.create_counter(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir, advisory: advisory)
47
+ when :histogram then @delegate.create_histogram(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir, advisory: advisory)
48
+ when :up_down_counter then @delegate.create_up_down_counter(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir, advisory: advisory)
49
+ when :gauge then @delegate.create_gauge(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir, advisory: advisory)
50
+ when :observable_counter then @delegate.create_observable_counter(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir, callback: callback, advisory: advisory)
51
+ when :observable_gauge then @delegate.create_observable_gauge(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir, callback: callback, advisory: advisory)
52
+ when :observable_up_down_counter then @delegate.create_observable_up_down_counter(name, unit: unit, description: description, exemplar_filter: exemplar_filter, exemplar_reservoir: exemplar_reservoir, callback: callback, advisory: advisory)
53
53
  end
54
54
  end
55
55
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright The OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ require 'opentelemetry-metrics-api'
8
+
9
+ # Defines the top-level accessors for the global meter provider. The Metrics
10
+ # API is unstable, so requiring +opentelemetry-metrics-api+ does not define
11
+ # these. Requiring +opentelemetry-metrics-sdk+ does.
12
+ #
13
+ # These are delegators. The provider itself lives in
14
+ # {OpenTelemetry::Internal}, so this file can be required at any point,
15
+ # before or after the SDK is configured.
16
+ module OpenTelemetry
17
+ # Register the global meter provider.
18
+ #
19
+ # @param [MeterProvider] provider A meter provider to register as the
20
+ # global instance.
21
+ def meter_provider=(provider)
22
+ Internal.meter_provider = provider
23
+ end
24
+
25
+ # @return [Object, Metrics::MeterProvider] registered meter provider or a
26
+ # default no-op implementation of the meter provider.
27
+ def meter_provider
28
+ Internal.meter_provider
29
+ end
30
+ end
@@ -17,6 +17,32 @@ module OpenTelemetry
17
17
  # Array values must not contain nil elements and all elements must be of
18
18
  # the same basic type (string, numeric, boolean).
19
19
  def add(increment, attributes: {}); end
20
+
21
+ # Returns whether this Counter is enabled for recording measurements.
22
+ #
23
+ # Instrumentation authors need to call this API each time
24
+ # they record a measurement to ensure they have the most
25
+ # up-to-date value.
26
+ #
27
+ # @return [Boolean] default to true in noop implementation
28
+ def enabled?
29
+ true
30
+ end
31
+
32
+ # (Development) Binds a fixed set of attributes to this Counter, returning an instrument
33
+ # whose #add calls associate every measurement with those attributes. Attributes are resolved
34
+ # once at bind time rather than on every recording, avoiding repeated attribute processing and
35
+ # lookup. Passing attributes to #add on the returned bound instrument negates this benefit.
36
+ #
37
+ # @param [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}] attributes
38
+ # Values must be non-nil and (array of) string, boolean or numeric type.
39
+ # Array values must not contain nil elements and all elements must be of
40
+ # the same basic type (string, numeric, boolean).
41
+ #
42
+ # @return [Counter] a bound instrument supporting #add; the no-op implementation returns self.
43
+ def bind(attributes: {})
44
+ self
45
+ end
20
46
  end
21
47
  end
22
48
  end
@@ -17,6 +17,33 @@ module OpenTelemetry
17
17
  # Array values must not contain nil elements and all elements must be of
18
18
  # the same basic type (string, numeric, boolean).
19
19
  def record(amount, attributes: {}); end
20
+
21
+ # Returns whether this Gauge is enabled for recording measurements.
22
+ #
23
+ # Instrumentation authors need to call this API each time
24
+ # they record a measurement to ensure they have the most
25
+ # up-to-date value.
26
+ #
27
+ # @return [Boolean] default to true in noop implementation
28
+ def enabled?
29
+ true
30
+ end
31
+
32
+ # (Development) Binds a fixed set of attributes to this Gauge, returning an instrument
33
+ # whose #record calls associate every measurement with those attributes. Attributes are
34
+ # resolved once at bind time rather than on every recording, avoiding repeated attribute
35
+ # processing and lookup. Passing attributes to #record on the returned bound instrument
36
+ # negates this benefit.
37
+ #
38
+ # @param [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}] attributes
39
+ # Values must be non-nil and (array of) string, boolean or numeric type.
40
+ # Array values must not contain nil elements and all elements must be of
41
+ # the same basic type (string, numeric, boolean).
42
+ #
43
+ # @return [Gauge] a bound instrument supporting #record; the no-op implementation returns self.
44
+ def bind(attributes: {})
45
+ self
46
+ end
20
47
  end
21
48
  end
22
49
  end
@@ -17,6 +17,33 @@ module OpenTelemetry
17
17
  # Array values must not contain nil elements and all elements must be of
18
18
  # the same basic type (string, numeric, boolean).
19
19
  def record(amount, attributes: {}); end
20
+
21
+ # Returns whether this Histogram is enabled for recording measurements.
22
+ #
23
+ # Instrumentation authors need to call this API each time
24
+ # they record a measurement to ensure they have the most
25
+ # up-to-date value.
26
+ #
27
+ # @return [Boolean] default to true in noop implementation
28
+ def enabled?
29
+ true
30
+ end
31
+
32
+ # (Development) Binds a fixed set of attributes to this Histogram, returning an instrument
33
+ # whose #record calls associate every measurement with those attributes. Attributes are
34
+ # resolved once at bind time rather than on every recording, avoiding repeated attribute
35
+ # processing and lookup. Passing attributes to #record on the returned bound instrument
36
+ # negates this benefit.
37
+ #
38
+ # @param [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}] attributes
39
+ # Values must be non-nil and (array of) string, boolean or numeric type.
40
+ # Array values must not contain nil elements and all elements must be of
41
+ # the same basic type (string, numeric, boolean).
42
+ #
43
+ # @return [Histogram] a bound instrument supporting #record; the no-op implementation returns self.
44
+ def bind(attributes: {})
45
+ self
46
+ end
20
47
  end
21
48
  end
22
49
  end
@@ -17,6 +17,16 @@ module OpenTelemetry
17
17
  # Array values must not contain nil elements and all elements must be of
18
18
  # the same basic type (string, numeric, boolean).
19
19
  def observe(timeout: nil, attributes: {}); end
20
+
21
+ # Registers a callback function to report Measurements for this instrument.
22
+ #
23
+ # @param [Proc] callback the callback function
24
+ def register_callback(callback); end
25
+
26
+ # Unregisters a callback function previously registered via {#register_callback}.
27
+ #
28
+ # @param [Proc] callback the callback function
29
+ def unregister(callback); end
20
30
  end
21
31
  end
22
32
  end
@@ -17,6 +17,16 @@ module OpenTelemetry
17
17
  # Array values must not contain nil elements and all elements must be of
18
18
  # the same basic type (string, numeric, boolean).
19
19
  def observe(timeout: nil, attributes: {}); end
20
+
21
+ # Registers a callback function to report Measurements for this instrument.
22
+ #
23
+ # @param [Proc] callback the callback function
24
+ def register_callback(callback); end
25
+
26
+ # Unregisters a callback function previously registered via {#register_callback}.
27
+ #
28
+ # @param [Proc] callback the callback function
29
+ def unregister(callback); end
20
30
  end
21
31
  end
22
32
  end
@@ -17,6 +17,16 @@ module OpenTelemetry
17
17
  # Array values must not contain nil elements and all elements must be of
18
18
  # the same basic type (string, numeric, boolean).
19
19
  def observe(timeout: nil, attributes: {}); end
20
+
21
+ # Registers a callback function to report Measurements for this instrument.
22
+ #
23
+ # @param [Proc] callback the callback function
24
+ def register_callback(callback); end
25
+
26
+ # Unregisters a callback function previously registered via {#register_callback}.
27
+ #
28
+ # @param [Proc] callback the callback function
29
+ def unregister(callback); end
20
30
  end
21
31
  end
22
32
  end
@@ -17,6 +17,33 @@ module OpenTelemetry
17
17
  # Array values must not contain nil elements and all elements must be of
18
18
  # the same basic type (string, numeric, boolean).
19
19
  def add(amount, attributes: {}); end
20
+
21
+ # Returns whether this UpDownCounter is enabled for recording
22
+ # measurements.
23
+ #
24
+ # Instrumentation authors need to call this API each time
25
+ # they record a measurement to ensure they have the most
26
+ # up-to-date value.
27
+ #
28
+ # @return [Boolean] default to true in noop implementation
29
+ def enabled?
30
+ true
31
+ end
32
+
33
+ # (Development) Binds a fixed set of attributes to this UpDownCounter, returning an instrument
34
+ # whose #add calls associate every measurement with those attributes. Attributes are resolved
35
+ # once at bind time rather than on every recording, avoiding repeated attribute processing and
36
+ # lookup. Passing attributes to #add on the returned bound instrument negates this benefit.
37
+ #
38
+ # @param [Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}] attributes
39
+ # Values must be non-nil and (array of) string, boolean or numeric type.
40
+ # Array values must not contain nil elements and all elements must be of
41
+ # the same basic type (string, numeric, boolean).
42
+ #
43
+ # @return [UpDownCounter] a bound instrument supporting #add; the no-op implementation returns self.
44
+ def bind(attributes: {})
45
+ self
46
+ end
20
47
  end
21
48
  end
22
49
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright The OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ # Installs the top-level meter provider accessors on behalf of metrics SDKs
8
+ # released before those accessors moved out of this gem. Those versions assign
9
+ # and read +OpenTelemetry.meter_provider+ while configuring and after forking,
10
+ # and have no way to require +opentelemetry/metrics/global+ themselves.
11
+ #
12
+ # Such an SDK is always loaded by the time it reaches for the accessor, so the
13
+ # check cannot happen at require time. It happens on the miss instead.
14
+ #
15
+ # Removal is tracked in #2414.
16
+ module OpenTelemetry
17
+ module Metrics
18
+ # Detects a metrics SDK that predates {OpenTelemetry::Metrics::Global} and
19
+ # installs the accessors it expects. With no SDK loaded, +super+ raises
20
+ # NoMethodError, which is what a caller holding only the API is meant to
21
+ # get.
22
+ #
23
+ # @api private
24
+ module LegacyGlobalCompat
25
+ ACCESSORS = %i[meter_provider meter_provider=].freeze
26
+
27
+ WARNING = 'opentelemetry-metrics-sdk 0.19.0 and earlier register the global meter ' \
28
+ 'provider through a compatibility shim in opentelemetry-metrics-api. ' \
29
+ 'Upgrade to opentelemetry-metrics-sdk 0.20.0 or later.'
30
+
31
+ # Keyed on MeterProvider rather than the SDK's Metrics namespace, which
32
+ # another gem could plausibly define without the SDK being present.
33
+ def self.handles?(name)
34
+ ACCESSORS.include?(name) && defined?(OpenTelemetry::SDK::Metrics::MeterProvider)
35
+ end
36
+
37
+ private
38
+
39
+ def method_missing(name, *, &)
40
+ return super unless LegacyGlobalCompat.handles?(name)
41
+
42
+ require 'opentelemetry/metrics/global'
43
+ return super unless singleton_class.method_defined?(name)
44
+
45
+ OpenTelemetry.logger.warn(WARNING)
46
+ public_send(name, *, &)
47
+ end
48
+
49
+ def respond_to_missing?(name, include_private = false)
50
+ LegacyGlobalCompat.handles?(name) || super
51
+ end
52
+ end
53
+ end
54
+
55
+ singleton_class.prepend(Metrics::LegacyGlobalCompat)
56
+ end
@@ -55,10 +55,14 @@ module OpenTelemetry
55
55
  # - `OpenTelemetry::SDK::Metrics::Exemplar::SimpleFixedSizeExemplarReservoir` - uniformly-weighted sampling
56
56
  # - `OpenTelemetry::SDK::Metrics::Exemplar::AlignedHistogramBucketExemplarReservoir` - one exemplar per histogram bucket (recommended for histograms)
57
57
  # - `OpenTelemetry::SDK::Metrics::Exemplar::NoopExemplarReservoir` - no-op, disables exemplar collection
58
+ # @param advisory [optional Hash] optional advisory parameters: recommendations from the
59
+ # instrument author that implementations MAY ignore. The API does not validate them.
60
+ # @option advisory [Array<String>] :attributes Recommended set of attribute keys for the resulting metrics.
61
+ # @option advisory [Array<Numeric>] :explicit_bucket_boundaries Applies to histograms only and has no effect here.
58
62
  #
59
63
  # @return [nil] after creation of counter, it will be stored in instrument_registry
60
- def create_counter(name, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil)
61
- create_instrument(:counter, name, unit, description, nil, exemplar_filter, exemplar_reservoir) { COUNTER }
64
+ def create_counter(name, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil, advisory: nil)
65
+ create_instrument(:counter, name, unit, description, nil, exemplar_filter, exemplar_reservoir, advisory) { COUNTER }
62
66
  end
63
67
 
64
68
  # Histogram is a synchronous Instrument which can be used to report arbitrary values that are likely
@@ -86,10 +90,15 @@ module OpenTelemetry
86
90
  # - `OpenTelemetry::SDK::Metrics::Exemplar::SimpleFixedSizeExemplarReservoir` - uniformly-weighted sampling
87
91
  # - `OpenTelemetry::SDK::Metrics::Exemplar::AlignedHistogramBucketExemplarReservoir` - one exemplar per histogram bucket (recommended for histograms)
88
92
  # - `OpenTelemetry::SDK::Metrics::Exemplar::NoopExemplarReservoir` - no-op, disables exemplar collection
93
+ # @param advisory [optional Hash] optional advisory parameters: recommendations from the
94
+ # instrument author that implementations MAY ignore. The API does not validate them.
95
+ # @option advisory [Array<Numeric>] :explicit_bucket_boundaries Recommended bucket boundaries when
96
+ # this instrument is aggregated to an explicit bucket histogram.
97
+ # @option advisory [Array<String>] :attributes Recommended set of attribute keys for the resulting metrics.
89
98
  #
90
99
  # @return [nil] after creation of histogram, it will be stored in instrument_registry
91
- def create_histogram(name, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil)
92
- create_instrument(:histogram, name, unit, description, nil, exemplar_filter, exemplar_reservoir) { HISTOGRAM }
100
+ def create_histogram(name, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil, advisory: nil)
101
+ create_instrument(:histogram, name, unit, description, nil, exemplar_filter, exemplar_reservoir, advisory) { HISTOGRAM }
93
102
  end
94
103
 
95
104
  # Gauge is an synchronous Instrument which reports non-additive value(s)
@@ -115,10 +124,14 @@ module OpenTelemetry
115
124
  # - `OpenTelemetry::SDK::Metrics::Exemplar::SimpleFixedSizeExemplarReservoir` - uniformly-weighted sampling
116
125
  # - `OpenTelemetry::SDK::Metrics::Exemplar::AlignedHistogramBucketExemplarReservoir` - one exemplar per histogram bucket (recommended for histograms)
117
126
  # - `OpenTelemetry::SDK::Metrics::Exemplar::NoopExemplarReservoir` - no-op, disables exemplar collection
127
+ # @param advisory [optional Hash] optional advisory parameters: recommendations from the
128
+ # instrument author that implementations MAY ignore. The API does not validate them.
129
+ # @option advisory [Array<String>] :attributes Recommended set of attribute keys for the resulting metrics.
130
+ # @option advisory [Array<Numeric>] :explicit_bucket_boundaries Applies to histograms only and has no effect here.
118
131
  #
119
132
  # @return [nil] after creation of gauge, it will be stored in instrument_registry
120
- def create_gauge(name, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil)
121
- create_instrument(:gauge, name, unit, description, nil, exemplar_filter, exemplar_reservoir) { GAUGE }
133
+ def create_gauge(name, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil, advisory: nil)
134
+ create_instrument(:gauge, name, unit, description, nil, exemplar_filter, exemplar_reservoir, advisory) { GAUGE }
122
135
  end
123
136
 
124
137
  # UpDownCounter is a synchronous Instrument which supports increments and decrements.
@@ -144,10 +157,14 @@ module OpenTelemetry
144
157
  # - `OpenTelemetry::SDK::Metrics::Exemplar::SimpleFixedSizeExemplarReservoir` - uniformly-weighted sampling
145
158
  # - `OpenTelemetry::SDK::Metrics::Exemplar::AlignedHistogramBucketExemplarReservoir` - one exemplar per histogram bucket (recommended for histograms)
146
159
  # - `OpenTelemetry::SDK::Metrics::Exemplar::NoopExemplarReservoir` - no-op, disables exemplar collection
160
+ # @param advisory [optional Hash] optional advisory parameters: recommendations from the
161
+ # instrument author that implementations MAY ignore. The API does not validate them.
162
+ # @option advisory [Array<String>] :attributes Recommended set of attribute keys for the resulting metrics.
163
+ # @option advisory [Array<Numeric>] :explicit_bucket_boundaries Applies to histograms only and has no effect here.
147
164
  #
148
165
  # @return [nil] after creation of up_down_counter, it will be stored in instrument_registry
149
- def create_up_down_counter(name, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil)
150
- create_instrument(:up_down_counter, name, unit, description, nil, exemplar_filter, exemplar_reservoir) { UP_DOWN_COUNTER }
166
+ def create_up_down_counter(name, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil, advisory: nil)
167
+ create_instrument(:up_down_counter, name, unit, description, nil, exemplar_filter, exemplar_reservoir, advisory) { UP_DOWN_COUNTER }
151
168
  end
152
169
 
153
170
  # ObservableCounter is an asynchronous Instrument which reports monotonically
@@ -164,7 +181,7 @@ module OpenTelemetry
164
181
  # exemplar_reservoir: OpenTelemetry::SDK::Metrics::Exemplar::SimpleFixedSizeExemplarReservoir.new)
165
182
  #
166
183
  # @param name [String] the name of the observable_counter
167
- # @param callback [Proc] the callback function that used to collect metrics
184
+ # @param callback [optional Proc, Array<Proc>] zero or more callback functions used to collect metrics
168
185
  # @param unit [optional String] an optional string provided by user.
169
186
  # @param description [optional String] an optional free-form text provided by user.
170
187
  # @param exemplar_filter [optional Object] an optional filter to control which measurements are
@@ -177,10 +194,14 @@ module OpenTelemetry
177
194
  # - `OpenTelemetry::SDK::Metrics::Exemplar::SimpleFixedSizeExemplarReservoir` - uniformly-weighted sampling
178
195
  # - `OpenTelemetry::SDK::Metrics::Exemplar::AlignedHistogramBucketExemplarReservoir` - one exemplar per histogram bucket (recommended for histograms)
179
196
  # - `OpenTelemetry::SDK::Metrics::Exemplar::NoopExemplarReservoir` - no-op, disables exemplar collection
197
+ # @param advisory [optional Hash] optional advisory parameters: recommendations from the
198
+ # instrument author that implementations MAY ignore. The API does not validate them.
199
+ # @option advisory [Array<String>] :attributes Recommended set of attribute keys for the resulting metrics.
200
+ # @option advisory [Array<Numeric>] :explicit_bucket_boundaries Applies to histograms only and has no effect here.
180
201
  #
181
202
  # @return [nil] after creation of observable_counter, it will be stored in instrument_registry
182
- def create_observable_counter(name, callback:, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil)
183
- create_instrument(:observable_counter, name, unit, description, callback, exemplar_filter, exemplar_reservoir) { OBSERVABLE_COUNTER }
203
+ def create_observable_counter(name, callback: nil, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil, advisory: nil)
204
+ create_instrument(:observable_counter, name, unit, description, callback, exemplar_filter, exemplar_reservoir, advisory) { OBSERVABLE_COUNTER }
184
205
  end
185
206
 
186
207
  # ObservableGauge is an asynchronous Instrument which reports non-additive value(s)
@@ -198,7 +219,7 @@ module OpenTelemetry
198
219
  # exemplar_reservoir: OpenTelemetry::SDK::Metrics::Exemplar::SimpleFixedSizeExemplarReservoir.new)
199
220
  #
200
221
  # @param name [String] the name of the observable_gauge
201
- # @param callback [Proc] the callback function that used to collect metrics
222
+ # @param callback [optional Proc, Array<Proc>] zero or more callback functions used to collect metrics
202
223
  # @param unit [optional String] an optional string provided by user.
203
224
  # @param description [optional String] an optional free-form text provided by user.
204
225
  # @param exemplar_filter [optional Object] an optional filter to control which measurements are
@@ -211,10 +232,14 @@ module OpenTelemetry
211
232
  # - `OpenTelemetry::SDK::Metrics::Exemplar::SimpleFixedSizeExemplarReservoir` - uniformly-weighted sampling
212
233
  # - `OpenTelemetry::SDK::Metrics::Exemplar::AlignedHistogramBucketExemplarReservoir` - one exemplar per histogram bucket (recommended for histograms)
213
234
  # - `OpenTelemetry::SDK::Metrics::Exemplar::NoopExemplarReservoir` - no-op, disables exemplar collection
235
+ # @param advisory [optional Hash] optional advisory parameters: recommendations from the
236
+ # instrument author that implementations MAY ignore. The API does not validate them.
237
+ # @option advisory [Array<String>] :attributes Recommended set of attribute keys for the resulting metrics.
238
+ # @option advisory [Array<Numeric>] :explicit_bucket_boundaries Applies to histograms only and has no effect here.
214
239
  #
215
240
  # @return [nil] after creation of observable_gauge, it will be stored in instrument_registry
216
- def create_observable_gauge(name, callback:, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil)
217
- create_instrument(:observable_gauge, name, unit, description, callback, exemplar_filter, exemplar_reservoir) { OBSERVABLE_GAUGE }
241
+ def create_observable_gauge(name, callback: nil, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil, advisory: nil)
242
+ create_instrument(:observable_gauge, name, unit, description, callback, exemplar_filter, exemplar_reservoir, advisory) { OBSERVABLE_GAUGE }
218
243
  end
219
244
 
220
245
  # ObservableUpDownCounter is an asynchronous Instrument which reports additive value(s)
@@ -232,7 +257,7 @@ module OpenTelemetry
232
257
  # exemplar_reservoir: OpenTelemetry::SDK::Metrics::Exemplar::SimpleFixedSizeExemplarReservoir.new)
233
258
  #
234
259
  # @param name [String] the name of the observable_up_down_counter
235
- # @param callback [Proc] the callback function that used to collect metrics
260
+ # @param callback [optional Proc, Array<Proc>] zero or more callback functions used to collect metrics
236
261
  # @param unit [optional String] an optional string provided by user.
237
262
  # @param description [optional String] an optional free-form text provided by user.
238
263
  # @param exemplar_filter [optional Object] an optional filter to control which measurements are
@@ -245,15 +270,39 @@ module OpenTelemetry
245
270
  # - `OpenTelemetry::SDK::Metrics::Exemplar::SimpleFixedSizeExemplarReservoir` - uniformly-weighted sampling
246
271
  # - `OpenTelemetry::SDK::Metrics::Exemplar::AlignedHistogramBucketExemplarReservoir` - one exemplar per histogram bucket (recommended for histograms)
247
272
  # - `OpenTelemetry::SDK::Metrics::Exemplar::NoopExemplarReservoir` - no-op, disables exemplar collection
273
+ # @param advisory [optional Hash] optional advisory parameters: recommendations from the
274
+ # instrument author that implementations MAY ignore. The API does not validate them.
275
+ # @option advisory [Array<String>] :attributes Recommended set of attribute keys for the resulting metrics.
276
+ # @option advisory [Array<Numeric>] :explicit_bucket_boundaries Applies to histograms only and has no effect here.
248
277
  #
249
278
  # @return [nil] after creation of observable_up_down_counter, it will be stored in instrument_registry
250
- def create_observable_up_down_counter(name, callback:, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil)
251
- create_instrument(:observable_up_down_counter, name, unit, description, callback, exemplar_filter, exemplar_reservoir) { OBSERVABLE_UP_DOWN_COUNTER }
279
+ def create_observable_up_down_counter(name, callback: nil, unit: nil, description: nil, exemplar_filter: nil, exemplar_reservoir: nil, advisory: nil)
280
+ create_instrument(:observable_up_down_counter, name, unit, description, callback, exemplar_filter, exemplar_reservoir, advisory) { OBSERVABLE_UP_DOWN_COUNTER }
281
+ end
282
+
283
+ # Registers a callback function against a declared set of asynchronous instruments from this Meter.
284
+ #
285
+ # @param [Array] instruments the asynchronous instruments the callback function reports Measurements for
286
+ # @param [Proc] callback the callback function
287
+ #
288
+ # @return [nil]
289
+ def register_callback(instruments, callback)
290
+ instruments.each { |instrument| instrument.register_callback(callback) }
291
+ end
292
+
293
+ # Unregisters a callback function previously registered via {#register_callback}.
294
+ #
295
+ # @param [Array] instruments the asynchronous instruments the callback function was registered against
296
+ # @param [Proc] callback the callback function
297
+ #
298
+ # @return [nil]
299
+ def unregister(instruments, callback)
300
+ instruments.each { |instrument| instrument.unregister(callback) }
252
301
  end
253
302
 
254
303
  private
255
304
 
256
- def create_instrument(kind, name, unit, description, callback, exemplar_filter, exemplar_reservoir)
305
+ def create_instrument(kind, name, unit, description, callback, exemplar_filter, exemplar_reservoir, advisory)
257
306
  @mutex.synchronize do
258
307
  OpenTelemetry.logger.warn("duplicate instrument registration occurred for instrument #{name}") if @instrument_registry.include? name
259
308
 
@@ -7,6 +7,6 @@
7
7
  module OpenTelemetry
8
8
  module Metrics
9
9
  ## Current OpenTelemetry metrics version
10
- VERSION = '0.7.1'
10
+ VERSION = '0.9.0'
11
11
  end
12
12
  end
@@ -10,32 +10,12 @@ require 'opentelemetry/metrics/version'
10
10
  require 'opentelemetry/internal/proxy_instrument'
11
11
  require 'opentelemetry/internal/proxy_meter_provider'
12
12
  require 'opentelemetry/internal/proxy_meter'
13
+ require 'opentelemetry/internal/global_meter_provider'
14
+ require 'opentelemetry/metrics/legacy_global_compat'
13
15
 
14
16
  # OpenTelemetry is an open source observability framework, providing a
15
17
  # general-purpose API, SDK, and related tools required for the instrumentation
16
18
  # of cloud-native software, frameworks, and libraries.
17
19
  #
18
- # The OpenTelemetry module provides global accessors for telemetry objects.
19
- module OpenTelemetry
20
- @meter_provider = Internal::ProxyMeterProvider.new
21
-
22
- # Register the global meter provider.
23
- #
24
- # @param [MeterProvider] provider A meter provider to register as the
25
- # global instance.
26
- def meter_provider=(provider)
27
- @mutex.synchronize do
28
- if @meter_provider.instance_of? Internal::ProxyMeterProvider
29
- logger.debug("Upgrading default proxy meter provider to #{provider.class}")
30
- @meter_provider.delegate = provider
31
- end
32
- @meter_provider = provider
33
- end
34
- end
35
-
36
- # @return [Object, Metrics::MeterProvider] registered meter provider or a
37
- # default no-op implementation of the meter provider.
38
- def meter_provider
39
- @mutex.synchronize { @meter_provider }
40
- end
41
- end
20
+ # Requiring this gem makes the Metrics API available to instrumentation through
21
+ # {OpenTelemetry::Internal.meter_provider}.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opentelemetry-metrics-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenTelemetry Authors
@@ -34,10 +34,12 @@ files:
34
34
  - LICENSE
35
35
  - README.md
36
36
  - lib/opentelemetry-metrics-api.rb
37
+ - lib/opentelemetry/internal/global_meter_provider.rb
37
38
  - lib/opentelemetry/internal/proxy_instrument.rb
38
39
  - lib/opentelemetry/internal/proxy_meter.rb
39
40
  - lib/opentelemetry/internal/proxy_meter_provider.rb
40
41
  - lib/opentelemetry/metrics.rb
42
+ - lib/opentelemetry/metrics/global.rb
41
43
  - lib/opentelemetry/metrics/instrument.rb
42
44
  - lib/opentelemetry/metrics/instrument/counter.rb
43
45
  - lib/opentelemetry/metrics/instrument/gauge.rb
@@ -46,6 +48,7 @@ files:
46
48
  - lib/opentelemetry/metrics/instrument/observable_gauge.rb
47
49
  - lib/opentelemetry/metrics/instrument/observable_up_down_counter.rb
48
50
  - lib/opentelemetry/metrics/instrument/up_down_counter.rb
51
+ - lib/opentelemetry/metrics/legacy_global_compat.rb
49
52
  - lib/opentelemetry/metrics/measurement.rb
50
53
  - lib/opentelemetry/metrics/meter.rb
51
54
  - lib/opentelemetry/metrics/meter_provider.rb
@@ -54,10 +57,10 @@ homepage: https://github.com/open-telemetry/opentelemetry-ruby
54
57
  licenses:
55
58
  - Apache-2.0
56
59
  metadata:
57
- changelog_uri: https://rubydoc.info/gems/opentelemetry-metrics-api/0.7.1/file/CHANGELOG.md
58
- source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/opentelemetry-metrics-api/v0.7.1/metrics_api
60
+ changelog_uri: https://rubydoc.info/gems/opentelemetry-metrics-api/0.9.0/file/CHANGELOG.md
61
+ source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/opentelemetry-metrics-api/v0.9.0/metrics_api
59
62
  bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby/issues
60
- documentation_uri: https://rubydoc.info/gems/opentelemetry-metrics-api/0.7.1
63
+ documentation_uri: https://rubydoc.info/gems/opentelemetry-metrics-api/0.9.0
61
64
  rdoc_options: []
62
65
  require_paths:
63
66
  - lib
@@ -72,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
75
  - !ruby/object:Gem::Version
73
76
  version: '0'
74
77
  requirements: []
75
- rubygems_version: 4.0.16
78
+ rubygems_version: 4.0.20
76
79
  specification_version: 4
77
80
  summary: A stats collection and distributed tracing framework
78
81
  test_files: []