opentelemetry-metrics-sdk 0.21.0 → 0.22.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: aaa97b8e63eb4737a973f36e8861a9884e7eccba6b3df0355b9074769a5d89c3
4
- data.tar.gz: 70fb46dfb922370d54a647e37b80608f6f2d237979cd9a7fe4d0c40cf7132aea
3
+ metadata.gz: 6eb7640bb97e64464de8e6496fe67028f989313651d9112544f9caa17bd1e3d2
4
+ data.tar.gz: 07ec1f7b6a9af36e6972a6f6a8a8b6561f791318e34b3164dc44e8e4f38206a4
5
5
  SHA512:
6
- metadata.gz: 673c6ce995204f0cba090c12cd7e841d75dd4766ffb44dee8d9690b938774c4889fd0c562f798281bc961085354d0146f983da55419499f683773c3f9a33071e
7
- data.tar.gz: 510c0413cd0c921193a068a9184c2ddb8f3c1618512fe6c7c88b010486a7fadc2c74ce37b1020fa63b94bc399c26428bbadfb0e7cf5050916937179d04e30c98
6
+ metadata.gz: 110b7d06b87b6b6d83267241dd77c835bcdbbe136e97ef7aaa08c43048fa538fea034475ef8cdad5dc99394dc6f086f397338a13592bb23afa58f7fdcafeb417
7
+ data.tar.gz: 8ca110b0164d1cf116e22013a1ebab15c5ad786e7947cdbcca372c9d3a9cb485ae8a4bd98c0d323e377ce2653d06c38cd07d416ce2936939b50d83450e92fc55
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Release History: opentelemetry-metrics-sdk
2
2
 
3
+ ### v0.22.0 / 2026-10-20
4
+
5
+ * ADDED: Support OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION env var (#2389)
6
+
3
7
  ### v0.21.0 / 2026-10-13
4
8
 
5
9
  * ADDED: Fix duplicate instrument registration warning (#2417)
@@ -12,7 +12,7 @@ module OpenTelemetry
12
12
  #
13
13
  # Potentially useful for exploratory purposes.
14
14
  class ConsoleMetricPullExporter < MetricReader
15
- def initialize(aggregation_cardinality_limit: nil)
15
+ def initialize(aggregation_cardinality_limit: nil, default_aggregation: nil)
16
16
  super
17
17
  @stopped = false
18
18
  end
@@ -13,7 +13,7 @@ module OpenTelemetry
13
13
  class InMemoryMetricPullExporter < MetricReader
14
14
  attr_reader :metric_snapshots
15
15
 
16
- def initialize(aggregation_cardinality_limit: nil)
16
+ def initialize(aggregation_cardinality_limit: nil, default_aggregation: nil)
17
17
  super
18
18
  @metric_snapshots = []
19
19
  @mutex = Mutex.new
@@ -17,10 +17,32 @@ module OpenTelemetry
17
17
 
18
18
  private_constant :SINGLE_PROVIDER_ERROR
19
19
 
20
+ # The default aggregation for each instrument kind, as defined by the
21
+ # metrics SDK specification.
22
+ # https://opentelemetry.io/docs/specs/otel/metrics/sdk/#default-aggregation
23
+ DEFAULT_AGGREGATION = {
24
+ counter: OpenTelemetry::SDK::Metrics::Aggregation::Sum,
25
+ up_down_counter: OpenTelemetry::SDK::Metrics::Aggregation::Sum,
26
+ observable_counter: OpenTelemetry::SDK::Metrics::Aggregation::Sum,
27
+ observable_up_down_counter: OpenTelemetry::SDK::Metrics::Aggregation::Sum,
28
+ gauge: OpenTelemetry::SDK::Metrics::Aggregation::LastValue,
29
+ observable_gauge: OpenTelemetry::SDK::Metrics::Aggregation::LastValue,
30
+ histogram: OpenTelemetry::SDK::Metrics::Aggregation::ExplicitBucketHistogram
31
+ }.freeze
32
+
20
33
  attr_reader :metric_store
21
34
 
22
- def initialize(aggregation_cardinality_limit: nil)
35
+ # @return [Hash{Symbol => Class}] the aggregation class to use for each
36
+ # instrument kind, resolved once at construction.
37
+ attr_reader :default_aggregation
38
+
39
+ # @param [optional Integer] aggregation_cardinality_limit the maximum number of
40
+ # data points to keep per metric stream.
41
+ # @param [optional Hash{Symbol => Class}] default_aggregation aggregation classes
42
+ # keyed by instrument kind, applied on top of {DEFAULT_AGGREGATION}.
43
+ def initialize(aggregation_cardinality_limit: nil, default_aggregation: nil)
23
44
  @mutex = Mutex.new
45
+ @default_aggregation = DEFAULT_AGGREGATION.merge(default_aggregation || {})
24
46
  @metric_store = OpenTelemetry::SDK::Metrics::State::MetricStore.new(cardinality_limit: aggregation_cardinality_limit)
25
47
  end
26
48
 
@@ -26,7 +26,9 @@ module OpenTelemetry
26
26
  export_timeout_millis: Float(ENV.fetch('OTEL_METRIC_EXPORT_TIMEOUT', 30_000)),
27
27
  exporter: nil,
28
28
  aggregation_cardinality_limit: nil)
29
- super(aggregation_cardinality_limit: aggregation_cardinality_limit)
29
+ # The exporter knows what the destination prefers, so this reader defers to it.
30
+ super(aggregation_cardinality_limit: aggregation_cardinality_limit,
31
+ default_aggregation: (exporter.default_aggregation if exporter.respond_to?(:default_aggregation)))
30
32
 
31
33
  @export_interval = export_interval_millis / 1000.0
32
34
  @export_timeout = export_timeout_millis / 1000.0
@@ -13,6 +13,8 @@ module OpenTelemetry
13
13
  class AsynchronousInstrument
14
14
  NOOP_EXEMPLAR_RESERVOIR = Exemplar::NoopExemplarReservoir.new
15
15
 
16
+ attr_reader :exemplar_reservoir
17
+
16
18
  def initialize(name, unit, description, callback, instrumentation_scope, meter_provider, exemplar_filter, exemplar_reservoir)
17
19
  @name = name
18
20
  @unit = unit
@@ -31,7 +33,7 @@ module OpenTelemetry
31
33
  end
32
34
 
33
35
  # @api private
34
- def register_with_new_metric_store(metric_store, aggregation: default_aggregation)
36
+ def register_with_new_metric_store(metric_store, aggregation: nil, default_aggregation: nil)
35
37
  ms = OpenTelemetry::SDK::Metrics::State::AsynchronousMetricStream.new(
36
38
  @name,
37
39
  @description,
@@ -44,7 +46,8 @@ module OpenTelemetry
44
46
  @timeout,
45
47
  @attributes,
46
48
  @exemplar_filter,
47
- @exemplar_reservoir
49
+ @exemplar_reservoir,
50
+ default_aggregation: default_aggregation
48
51
  )
49
52
  @metric_streams << ms
50
53
  metric_store.add_metric_stream(ms)
@@ -38,12 +38,6 @@ module OpenTelemetry
38
38
  OpenTelemetry.handle_error(exception: e)
39
39
  nil
40
40
  end
41
-
42
- private
43
-
44
- def default_aggregation
45
- OpenTelemetry::SDK::Metrics::Aggregation::Sum.new(exemplar_reservoir: @exemplar_reservoir, monotonic: true)
46
- end
47
41
  end
48
42
  end
49
43
  end
@@ -34,12 +34,6 @@ module OpenTelemetry
34
34
  OpenTelemetry.handle_error(exception: e)
35
35
  nil
36
36
  end
37
-
38
- private
39
-
40
- def default_aggregation
41
- OpenTelemetry::SDK::Metrics::Aggregation::LastValue.new(exemplar_reservoir: @exemplar_reservoir)
42
- end
43
37
  end
44
38
  end
45
39
  end
@@ -31,14 +31,6 @@ module OpenTelemetry
31
31
  OpenTelemetry.handle_error(exception: e)
32
32
  nil
33
33
  end
34
-
35
- private
36
-
37
- def default_aggregation
38
- # TODO: at this point, histogram always take the default DEFAULT_BOUNDARIES. In future, the histogram should be able to
39
- # define the custom boundaries so for exemplar_reservoir can also takes the bounaries as parameter
40
- OpenTelemetry::SDK::Metrics::Aggregation::ExplicitBucketHistogram.new(exemplar_reservoir: @exemplar_reservoir)
41
- end
42
34
  end
43
35
  end
44
36
  end
@@ -28,12 +28,6 @@ module OpenTelemetry
28
28
  def observe(timeout: nil, attributes: {})
29
29
  update(timeout, attributes)
30
30
  end
31
-
32
- private
33
-
34
- def default_aggregation
35
- OpenTelemetry::SDK::Metrics::Aggregation::Sum.new(exemplar_reservoir: @exemplar_reservoir, monotonic: true, instrument_kind: instrument_kind)
36
- end
37
31
  end
38
32
  end
39
33
  end
@@ -28,12 +28,6 @@ module OpenTelemetry
28
28
  def observe(timeout: nil, attributes: {})
29
29
  update(timeout, attributes)
30
30
  end
31
-
32
- private
33
-
34
- def default_aggregation
35
- OpenTelemetry::SDK::Metrics::Aggregation::LastValue.new(exemplar_reservoir: @exemplar_reservoir)
36
- end
37
31
  end
38
32
  end
39
33
  end
@@ -28,12 +28,6 @@ module OpenTelemetry
28
28
  def observe(timeout: nil, attributes: {})
29
29
  update(timeout, attributes)
30
30
  end
31
-
32
- private
33
-
34
- def default_aggregation
35
- OpenTelemetry::SDK::Metrics::Aggregation::Sum.new(aggregation_temporality: :cumulative, exemplar_reservoir: @exemplar_reservoir, monotonic: false)
36
- end
37
31
  end
38
32
  end
39
33
  end
@@ -11,6 +11,8 @@ module OpenTelemetry
11
11
  # {SynchronousInstrument} contains the common functionality shared across
12
12
  # the synchronous instruments SDK instruments.
13
13
  class SynchronousInstrument
14
+ attr_reader :exemplar_reservoir
15
+
14
16
  def initialize(name, unit, description, instrumentation_scope, meter_provider, exemplar_filter, exemplar_reservoir)
15
17
  @name = name
16
18
  @unit = unit
@@ -25,7 +27,7 @@ module OpenTelemetry
25
27
  end
26
28
 
27
29
  # @api private
28
- def register_with_new_metric_store(metric_store, aggregation: default_aggregation)
30
+ def register_with_new_metric_store(metric_store, aggregation: nil, default_aggregation: nil)
29
31
  ms = OpenTelemetry::SDK::Metrics::State::MetricStream.new(
30
32
  @name,
31
33
  @description,
@@ -35,7 +37,8 @@ module OpenTelemetry
35
37
  @instrumentation_scope,
36
38
  aggregation,
37
39
  @exemplar_filter,
38
- @exemplar_reservoir
40
+ @exemplar_reservoir,
41
+ default_aggregation: default_aggregation
39
42
  )
40
43
  @metric_streams << ms
41
44
  metric_store.add_metric_stream(ms)
@@ -31,12 +31,6 @@ module OpenTelemetry
31
31
  OpenTelemetry.handle_error(exception: e)
32
32
  nil
33
33
  end
34
-
35
- private
36
-
37
- def default_aggregation
38
- OpenTelemetry::SDK::Metrics::Aggregation::Sum.new(aggregation_temporality: :cumulative, exemplar_reservoir: @exemplar_reservoir, monotonic: false)
39
- end
40
34
  end
41
35
  end
42
36
  end
@@ -67,7 +67,8 @@ module OpenTelemetry
67
67
  # Iterates a snapshot so a concurrent registration cannot mutate the hash mid-iteration.
68
68
  def add_metric_reader(metric_reader)
69
69
  @instrument_descriptors.values.flatten.each do |descriptor|
70
- descriptor.instrument.register_with_new_metric_store(metric_reader.metric_store)
70
+ descriptor.instrument.register_with_new_metric_store(metric_reader.metric_store,
71
+ default_aggregation: MeterProvider.reader_config(metric_reader))
71
72
  end
72
73
  end
73
74
 
@@ -144,11 +144,19 @@ module OpenTelemetry
144
144
  end
145
145
  private :register_metric_reader
146
146
 
147
+ # @api private
148
+ #
149
+ # Returns the reader's preferred aggregation classes, or nil for a reader that
150
+ # does not provide any. Readers are duck typed, so the method may be absent.
151
+ def self.reader_config(metric_reader)
152
+ metric_reader.default_aggregation if metric_reader.respond_to?(:default_aggregation)
153
+ end
154
+
147
155
  # @api private
148
156
  def register_synchronous_instrument(instrument)
149
157
  @mutex.synchronize do
150
158
  @metric_readers.each do |mr|
151
- instrument.register_with_new_metric_store(mr.metric_store)
159
+ instrument.register_with_new_metric_store(mr.metric_store, default_aggregation: MeterProvider.reader_config(mr))
152
160
  end
153
161
  end
154
162
  end
@@ -27,10 +27,12 @@ module OpenTelemetry
27
27
  timeout,
28
28
  attributes,
29
29
  exemplar_filter,
30
- exemplar_reservoir
30
+ exemplar_reservoir,
31
+ default_aggregation: nil
31
32
  )
32
33
  # Call parent constructor with common parameters
33
- super(name, description, unit, instrument_kind, meter_provider, instrumentation_scope, aggregation, exemplar_filter, exemplar_reservoir)
34
+ super(name, description, unit, instrument_kind, meter_provider, instrumentation_scope, aggregation, exemplar_filter, exemplar_reservoir,
35
+ default_aggregation: default_aggregation)
34
36
 
35
37
  # Initialize asynchronous-specific attributes
36
38
  @callback = callback
@@ -29,7 +29,8 @@ module OpenTelemetry
29
29
  instrumentation_scope,
30
30
  aggregation,
31
31
  exemplar_filter,
32
- exemplar_reservoir
32
+ exemplar_reservoir,
33
+ default_aggregation: nil
33
34
  )
34
35
  @name = name
35
36
  @description = description
@@ -37,7 +38,7 @@ module OpenTelemetry
37
38
  @instrument_kind = instrument_kind
38
39
  @meter_provider = meter_provider
39
40
  @instrumentation_scope = instrumentation_scope
40
- @default_aggregation = aggregation
41
+ @default_aggregation = aggregation || build_aggregation(default_aggregation, exemplar_reservoir)
41
42
  @data_points = {}
42
43
  @registered_views = {}
43
44
  @exemplar_filter = exemplar_filter
@@ -47,6 +48,31 @@ module OpenTelemetry
47
48
  @mutex = Mutex.new
48
49
  end
49
50
 
51
+ # Builds this stream's aggregation from the metric reader's preferred
52
+ # aggregation classes, falling back to the spec defaults.
53
+ #
54
+ # @param [Hash{Symbol => Class}, nil] preferred aggregation classes by instrument kind
55
+ # @param [Object, nil] exemplar_reservoir the instrument's exemplar reservoir
56
+ # @return [Object] a new aggregation, owned by this stream
57
+ def build_aggregation(preferred, exemplar_reservoir)
58
+ defaults = OpenTelemetry::SDK::Metrics::Export::MetricReader::DEFAULT_AGGREGATION
59
+ aggregation_class = (preferred || defaults)[@instrument_kind] || defaults[@instrument_kind]
60
+
61
+ if aggregation_class.nil?
62
+ OpenTelemetry.logger.warn("Unknown instrument kind: #{@instrument_kind}, defaulting to Drop aggregation")
63
+ aggregation_class = OpenTelemetry::SDK::Metrics::Aggregation::Drop
64
+ end
65
+
66
+ kwargs = { exemplar_reservoir: exemplar_reservoir }
67
+ if aggregation_class <= OpenTelemetry::SDK::Metrics::Aggregation::Sum
68
+ kwargs[:monotonic] = %i[counter observable_counter].include?(@instrument_kind)
69
+ kwargs[:instrument_kind] = @instrument_kind
70
+ kwargs[:aggregation_temporality] = :cumulative if %i[up_down_counter observable_up_down_counter].include?(@instrument_kind)
71
+ end
72
+
73
+ aggregation_class.new(**kwargs)
74
+ end
75
+
50
76
  # Returns a snapshot of this stream's aggregated metric data.
51
77
  def collect(start_time, end_time)
52
78
  @mutex.synchronize do
@@ -8,7 +8,7 @@ module OpenTelemetry
8
8
  module SDK
9
9
  module Metrics
10
10
  # Current OpenTelemetry metrics sdk version
11
- VERSION = '0.21.0'
11
+ VERSION = '0.22.0'
12
12
  end
13
13
  end
14
14
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opentelemetry-metrics-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenTelemetry Authors
@@ -122,10 +122,10 @@ homepage: https://github.com/open-telemetry/opentelemetry-ruby
122
122
  licenses:
123
123
  - Apache-2.0
124
124
  metadata:
125
- changelog_uri: https://rubydoc.info/gems/opentelemetry-metrics-sdk/0.21.0/file/CHANGELOG.md
126
- source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/opentelemetry-metrics-sdk/v0.21.0/metrics_sdk
125
+ changelog_uri: https://rubydoc.info/gems/opentelemetry-metrics-sdk/0.22.0/file/CHANGELOG.md
126
+ source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/opentelemetry-metrics-sdk/v0.22.0/metrics_sdk
127
127
  bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby/issues
128
- documentation_uri: https://rubydoc.info/gems/opentelemetry-metrics-sdk/0.21.0
128
+ documentation_uri: https://rubydoc.info/gems/opentelemetry-metrics-sdk/0.22.0
129
129
  rdoc_options: []
130
130
  require_paths:
131
131
  - lib