opentelemetry-metrics-sdk 0.1.0 → 0.3.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: 68999276f28a3e390725b6aebabc70a8846818e93fa9d6520f09c7992376bbbf
4
- data.tar.gz: 923878943342c36c768458f3f46fa34275faaf739a5257ca2d61a0bb46eccf5e
3
+ metadata.gz: b0394fb7c1a15117d165ce69b4419700868f9a9a2b662c9f1a5c933f71dc1a25
4
+ data.tar.gz: 58b977f251b7eea72c6935058073cd46aa0803c21e10686571cd9ffa0e23792f
5
5
  SHA512:
6
- metadata.gz: 4f8a1bf6946c7a1bc27955369fa540dfb1ca481b393a5e1bfd4eb9c1957b0ed404fa6c9007dbc4af0314bcbcf8eb2dfdb5ef76d838d24a87ef635016c78238ea
7
- data.tar.gz: e487825f271ba21fe3f491cbd497635d22cd224c3ba370b6de93b22367deb2bce11867db0d60a7860152a3cf255152c922ba6c452c5f8c9a01d5563ee8733025
6
+ metadata.gz: 969ec426ccc294ba7fff17b3edc5c0536d885e4c410f2a91c49b36afbd6ad2595a8073332c86e3109ba50d7ac51d119f30a3c9f24a3074576b79279f46ec7b34
7
+ data.tar.gz: ea08bec0926c227147edaa1dc66d9da4a4f0b714a9d01fb7e2db4edca81e152cfdae9338ac1e900bb29a1a24e2dab6df8c9653a5539fbce02a248ab4eeca3650
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Release History: opentelemetry-metrics-sdk
2
2
 
3
+ ### v0.3.0 / 2024-10-22
4
+
5
+ * ADDED: Add basic metrics view
6
+ * FIXED: Coerce aggregation_temporality to symbol
7
+ * FIXED: Add warning if invalid meter name given
8
+
9
+ ### v0.2.0 / 2024-08-27
10
+
11
+ * ADDED: Add basic periodic exporting metric_reader
12
+
3
13
  ### v0.1.0 / 2024-07-31
4
14
 
5
15
  Initial release.
data/README.md CHANGED
@@ -15,6 +15,7 @@ Metrics is one of the core signals in OpenTelemetry. This package allows you to
15
15
  This gem does not have a full implementation of the Metrics SDK specification. The work is in progress.
16
16
 
17
17
  At this time, you should be able to:
18
+
18
19
  * Create synchronous:
19
20
  * counters
20
21
  * up down counters
@@ -26,6 +27,7 @@ At this time, you should be able to:
26
27
  * Use delta aggregation temporality
27
28
 
28
29
  We do not yet have support for:
30
+
29
31
  * Asynchronous instruments
30
32
  * Cumulative aggregation temporality
31
33
  * Metrics Views
@@ -41,7 +43,7 @@ Until the Ruby implementation of OpenTelemetry Metrics becomes stable, the funct
41
43
 
42
44
  Install the gems using:
43
45
 
44
- ```
46
+ ```sh
45
47
  gem install opentelemetry-metrics-sdk
46
48
  gem install opentelemetry-sdk
47
49
  ```
@@ -97,7 +99,6 @@ During this experimental stage, we're looking for lots of community feedback abo
97
99
 
98
100
  The `opentelemetry-metrics-sdk` gem is distributed under the Apache 2.0 license. See [LICENSE][license-github] for more information.
99
101
 
100
-
101
102
  [metrics-sdk]: https://opentelemetry.io/docs/specs/otel/metrics/sdk/
102
103
  [opentelemetry-home]: https://opentelemetry.io
103
104
  [bundler-home]: https://bundler.io
@@ -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
+ module SDK
9
+ module Metrics
10
+ module Aggregation
11
+ # Contains the implementation of the Drop aggregation
12
+ class Drop
13
+ attr_reader :aggregation_temporality
14
+
15
+ def initialize(aggregation_temporality: :delta)
16
+ @aggregation_temporality = aggregation_temporality
17
+ end
18
+
19
+ def collect(start_time, end_time, data_points)
20
+ data_points.values.map!(&:dup)
21
+ end
22
+
23
+ def update(increment, attributes, data_points)
24
+ data_points[attributes] = NumberDataPoint.new(
25
+ {},
26
+ 0,
27
+ 0,
28
+ 0,
29
+ 0
30
+ )
31
+ nil
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -25,25 +25,25 @@ module OpenTelemetry
25
25
  boundaries: DEFAULT_BOUNDARIES,
26
26
  record_min_max: true
27
27
  )
28
- @data_points = {}
29
- @aggregation_temporality = aggregation_temporality
28
+
29
+ @aggregation_temporality = aggregation_temporality.to_sym
30
30
  @boundaries = boundaries && !boundaries.empty? ? boundaries.sort : nil
31
31
  @record_min_max = record_min_max
32
32
  end
33
33
 
34
- def collect(start_time, end_time)
34
+ def collect(start_time, end_time, data_points)
35
35
  if @aggregation_temporality == :delta
36
36
  # Set timestamps and 'move' data point values to result.
37
- hdps = @data_points.values.map! do |hdp|
37
+ hdps = data_points.values.map! do |hdp|
38
38
  hdp.start_time_unix_nano = start_time
39
39
  hdp.time_unix_nano = end_time
40
40
  hdp
41
41
  end
42
- @data_points.clear
42
+ data_points.clear
43
43
  hdps
44
44
  else
45
45
  # Update timestamps and take a snapshot.
46
- @data_points.values.map! do |hdp|
46
+ data_points.values.map! do |hdp|
47
47
  hdp.start_time_unix_nano ||= start_time # Start time of a data point is from the first observation.
48
48
  hdp.time_unix_nano = end_time
49
49
  hdp = hdp.dup
@@ -53,14 +53,14 @@ module OpenTelemetry
53
53
  end
54
54
  end
55
55
 
56
- def update(amount, attributes)
57
- hdp = @data_points.fetch(attributes) do
56
+ def update(amount, attributes, data_points)
57
+ hdp = data_points.fetch(attributes) do
58
58
  if @record_min_max
59
59
  min = Float::INFINITY
60
60
  max = -Float::INFINITY
61
61
  end
62
62
 
63
- @data_points[attributes] = HistogramDataPoint.new(
63
+ data_points[attributes] = HistogramDataPoint.new(
64
64
  attributes,
65
65
  nil, # :start_time_unix_nano
66
66
  nil, # :time_unix_nano
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright The OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ module SDK
9
+ module Metrics
10
+ module Aggregation
11
+ # Contains the implementation of the LastValue aggregation
12
+ class LastValue
13
+ attr_reader :aggregation_temporality
14
+
15
+ def initialize(aggregation_temporality: :delta)
16
+ @aggregation_temporality = aggregation_temporality
17
+ end
18
+
19
+ def collect(start_time, end_time, data_points)
20
+ if @aggregation_temporality == :delta
21
+ # Set timestamps and 'move' data point values to result.
22
+ ndps = data_points.values.map! do |ndp|
23
+ ndp.start_time_unix_nano = start_time
24
+ ndp.time_unix_nano = end_time
25
+ ndp
26
+ end
27
+ data_points.clear
28
+ ndps
29
+ else
30
+ # Update timestamps and take a snapshot.
31
+ data_points.values.map! do |ndp|
32
+ ndp.start_time_unix_nano ||= start_time # Start time of a data point is from the first observation.
33
+ ndp.time_unix_nano = end_time
34
+ ndp.dup
35
+ end
36
+ end
37
+ end
38
+
39
+ def update(increment, attributes, data_points)
40
+ data_points[attributes] = NumberDataPoint.new(
41
+ attributes,
42
+ nil,
43
+ nil,
44
+ increment,
45
+ nil
46
+ )
47
+ nil
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -15,23 +15,22 @@ module OpenTelemetry
15
15
 
16
16
  def initialize(aggregation_temporality: ENV.fetch('OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE', :delta))
17
17
  # TODO: the default should be :cumulative, see issue #1555
18
- @aggregation_temporality = aggregation_temporality
19
- @data_points = {}
18
+ @aggregation_temporality = aggregation_temporality.to_sym
20
19
  end
21
20
 
22
- def collect(start_time, end_time)
21
+ def collect(start_time, end_time, data_points)
23
22
  if @aggregation_temporality == :delta
24
23
  # Set timestamps and 'move' data point values to result.
25
- ndps = @data_points.values.map! do |ndp|
24
+ ndps = data_points.values.map! do |ndp|
26
25
  ndp.start_time_unix_nano = start_time
27
26
  ndp.time_unix_nano = end_time
28
27
  ndp
29
28
  end
30
- @data_points.clear
29
+ data_points.clear
31
30
  ndps
32
31
  else
33
32
  # Update timestamps and take a snapshot.
34
- @data_points.values.map! do |ndp|
33
+ data_points.values.map! do |ndp|
35
34
  ndp.start_time_unix_nano ||= start_time # Start time of a data point is from the first observation.
36
35
  ndp.time_unix_nano = end_time
37
36
  ndp.dup
@@ -39,8 +38,8 @@ module OpenTelemetry
39
38
  end
40
39
  end
41
40
 
42
- def update(increment, attributes)
43
- ndp = @data_points[attributes] || @data_points[attributes] = NumberDataPoint.new(
41
+ def update(increment, attributes, data_points)
42
+ ndp = data_points[attributes] || data_points[attributes] = NumberDataPoint.new(
44
43
  attributes,
45
44
  nil,
46
45
  nil,
@@ -19,3 +19,5 @@ require 'opentelemetry/sdk/metrics/aggregation/number_data_point'
19
19
  require 'opentelemetry/sdk/metrics/aggregation/histogram_data_point'
20
20
  require 'opentelemetry/sdk/metrics/aggregation/explicit_bucket_histogram'
21
21
  require 'opentelemetry/sdk/metrics/aggregation/sum'
22
+ require 'opentelemetry/sdk/metrics/aggregation/last_value'
23
+ require 'opentelemetry/sdk/metrics/aggregation/drop'
@@ -23,9 +23,9 @@ module OpenTelemetry
23
23
  export(collect)
24
24
  end
25
25
 
26
- def export(metrics)
26
+ def export(metrics, timeout: nil)
27
27
  @mutex.synchronize do
28
- @metric_snapshots << metrics
28
+ @metric_snapshots.concat(Array(metrics))
29
29
  end
30
30
  SUCCESS
31
31
  end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright The OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ module SDK
9
+ module Metrics
10
+ module Export
11
+ # PeriodicMetricReader provides a minimal example implementation.
12
+ class PeriodicMetricReader < MetricReader
13
+ # Returns a new instance of the {PeriodicMetricReader}.
14
+ #
15
+ # @param [Integer] export_interval_millis the maximum interval time.
16
+ # Defaults to the value of the OTEL_METRIC_EXPORT_INTERVAL environment
17
+ # variable, if set, or 60_000.
18
+ # @param [Integer] export_timeout_millis the maximum export timeout.
19
+ # Defaults to the value of the OTEL_METRIC_EXPORT_TIMEOUT environment
20
+ # variable, if set, or 30_000.
21
+ # @param [MetricReader] exporter the (duck type) MetricReader to where the
22
+ # recorded metrics are pushed after certain interval.
23
+ #
24
+ # @return a new instance of the {PeriodicMetricReader}.
25
+ def initialize(export_interval_millis: Float(ENV.fetch('OTEL_METRIC_EXPORT_INTERVAL', 60_000)),
26
+ export_timeout_millis: Float(ENV.fetch('OTEL_METRIC_EXPORT_TIMEOUT', 30_000)),
27
+ exporter: nil)
28
+ super()
29
+
30
+ @export_interval = export_interval_millis / 1000.0
31
+ @export_timeout = export_timeout_millis / 1000.0
32
+ @exporter = exporter
33
+ @thread = nil
34
+ @continue = false
35
+ @mutex = Mutex.new
36
+ @export_mutex = Mutex.new
37
+
38
+ start
39
+ end
40
+
41
+ def shutdown(timeout: nil)
42
+ thread = lock do
43
+ @continue = false # force termination in next iteration
44
+ @thread
45
+ end
46
+ thread&.join(@export_interval)
47
+ @exporter.force_flush if @exporter.respond_to?(:force_flush)
48
+ @exporter.shutdown
49
+ Export::SUCCESS
50
+ rescue StandardError => e
51
+ OpenTelemetry.handle_error(exception: e, message: 'Fail to shutdown PeriodicMetricReader.')
52
+ Export::FAILURE
53
+ end
54
+
55
+ def force_flush(timeout: nil)
56
+ export(timeout: timeout)
57
+ Export::SUCCESS
58
+ rescue StandardError
59
+ Export::FAILURE
60
+ end
61
+
62
+ private
63
+
64
+ def start
65
+ @continue = true
66
+ if @exporter.nil?
67
+ OpenTelemetry.logger.warn 'Missing exporter in PeriodicMetricReader.'
68
+ elsif @thread&.alive?
69
+ OpenTelemetry.logger.warn 'PeriodicMetricReader is still running. Please shutdown it if it needs to restart.'
70
+ else
71
+ @thread = Thread.new do
72
+ while @continue
73
+ sleep(@export_interval)
74
+ begin
75
+ Timeout.timeout(@export_timeout) do
76
+ export(timeout: @export_timeout)
77
+ end
78
+ rescue Timeout::Error => e
79
+ OpenTelemetry.handle_error(exception: e, message: 'PeriodicMetricReader timeout.')
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ def export(timeout: nil)
87
+ @export_mutex.synchronize do
88
+ collected_metrics = collect
89
+ @exporter.export(collected_metrics, timeout: timeout || @export_timeout) unless collected_metrics.empty?
90
+ end
91
+ end
92
+
93
+ def lock(&block)
94
+ @mutex.synchronize(&block)
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -26,3 +26,4 @@ end
26
26
  require 'opentelemetry/sdk/metrics/export/metric_reader'
27
27
  require 'opentelemetry/sdk/metrics/export/in_memory_metric_pull_exporter'
28
28
  require 'opentelemetry/sdk/metrics/export/console_metric_pull_exporter'
29
+ require 'opentelemetry/sdk/metrics/export/periodic_metric_reader'
@@ -24,7 +24,7 @@ module OpenTelemetry
24
24
  # Values must be non-nil and (array of) string, boolean or numeric type.
25
25
  # Array values must not contain nil elements and all elements must be of
26
26
  # the same basic type (string, numeric, boolean).
27
- def record(amount, attributes: nil)
27
+ def record(amount, attributes: {})
28
28
  update(amount, attributes)
29
29
  nil
30
30
  rescue StandardError => e
@@ -24,7 +24,7 @@ module OpenTelemetry
24
24
  # Values must be non-nil and (array of) string, boolean or numeric type.
25
25
  # Array values must not contain nil elements and all elements must be of
26
26
  # the same basic type (string, numeric, boolean).
27
- def add(amount, attributes: nil)
27
+ def add(amount, attributes: {})
28
28
  update(amount, attributes)
29
29
  nil
30
30
  rescue StandardError => e
@@ -11,6 +11,8 @@ module OpenTelemetry
11
11
  module Metrics
12
12
  # {Meter} is the SDK implementation of {OpenTelemetry::Metrics::Meter}.
13
13
  class Meter < OpenTelemetry::Metrics::Meter
14
+ NAME_REGEX = /\A[a-zA-Z][-.\w]{0,62}\z/
15
+
14
16
  # @api private
15
17
  #
16
18
  # Returns a new {Meter} instance.
@@ -28,12 +30,18 @@ module OpenTelemetry
28
30
 
29
31
  # @api private
30
32
  def add_metric_reader(metric_reader)
31
- @instrument_registry.each do |_n, instrument|
33
+ @instrument_registry.each_value do |instrument|
32
34
  instrument.register_with_new_metric_store(metric_reader.metric_store)
33
35
  end
34
36
  end
35
37
 
36
38
  def create_instrument(kind, name, unit, description, callback)
39
+ raise InstrumentNameError if name.nil?
40
+ raise InstrumentNameError if name.empty?
41
+ raise InstrumentNameError unless NAME_REGEX.match?(name)
42
+ raise InstrumentUnitError if unit && (!unit.ascii_only? || unit.size > 63)
43
+ raise InstrumentDescriptionError if description && (description.size > 1023 || !utf8mb3_encoding?(description.dup))
44
+
37
45
  super do
38
46
  case kind
39
47
  when :counter then OpenTelemetry::SDK::Metrics::Instrument::Counter.new(name, unit, description, @instrumentation_scope, @meter_provider)
@@ -45,6 +53,11 @@ module OpenTelemetry
45
53
  end
46
54
  end
47
55
  end
56
+
57
+ def utf8mb3_encoding?(string)
58
+ string.force_encoding('UTF-8').valid_encoding? &&
59
+ string.each_char { |c| return false if c.bytesize >= 4 }
60
+ end
48
61
  end
49
62
  end
50
63
  end
@@ -14,7 +14,7 @@ module OpenTelemetry
14
14
  Key = Struct.new(:name, :version)
15
15
  private_constant(:Key)
16
16
 
17
- attr_reader :resource, :metric_readers
17
+ attr_reader :resource, :metric_readers, :registered_views
18
18
 
19
19
  def initialize(resource: OpenTelemetry::SDK::Resources::Resource.create)
20
20
  @mutex = Mutex.new
@@ -22,6 +22,7 @@ module OpenTelemetry
22
22
  @stopped = false
23
23
  @metric_readers = []
24
24
  @resource = resource
25
+ @registered_views = []
25
26
  end
26
27
 
27
28
  # Returns a {Meter} instance.
@@ -36,6 +37,7 @@ module OpenTelemetry
36
37
  OpenTelemetry.logger.warn 'calling MeterProvider#meter after shutdown, a noop meter will be returned.'
37
38
  OpenTelemetry::Metrics::Meter.new
38
39
  else
40
+ OpenTelemetry.logger.warn "Invalid meter name provided: #{name.nil? ? 'nil' : 'empty'} value" if name.to_s.empty?
39
41
  @mutex.synchronize { @meter_registry[Key.new(name, version)] ||= Meter.new(name, version, self) }
40
42
  end
41
43
  end
@@ -125,13 +127,30 @@ module OpenTelemetry
125
127
  end
126
128
  end
127
129
 
128
- # The type of the Instrument(s) (optional).
129
- # The name of the Instrument(s). OpenTelemetry SDK authors MAY choose to support wildcard characters, with the question mark (?) matching exactly one character and the asterisk character (*) matching zero or more characters.
130
- # The name of the Meter (optional).
131
- # The version of the Meter (optional).
132
- # The schema_url of the Meter (optional).
133
- def add_view
134
- # TODO: For each meter add this view to all applicable instruments
130
+ # A View provides SDK users with the flexibility to customize the metrics that are output by the SDK.
131
+ #
132
+ # Example:
133
+ #
134
+ # OpenTelemetry.meter_provider.add_view('test', :aggregation => Aggregation::Drop.new,
135
+ # :type => :counter, :unit => 'smidgen',
136
+ # :meter_name => 'test', :meter_version => '1.0')
137
+ #
138
+ #
139
+ # @param [String] name Name of the view.
140
+ # @param [optional Hash] options For more precise matching, {View} and {MetricsStream}
141
+ # options may include:
142
+ # aggregation: An instance of an aggregation class, e.g. {ExplicitBucketHistogram}, {Sum}, {LastValue}
143
+ # type: A Symbol representing the instrument kind, e.g. :observable_gauge, :counter
144
+ # unit: A String matching an instrumentation unit, e.g. 'smidgen'
145
+ # meter_name: A String matching a meter name, e.g. meter_provider.meter('sample_meter_name', version: '1.2.0'), would be 'sample_meter_name'
146
+ # meter_version: A String matching a meter version, e.g. meter_provider.meter('sample_meter_name', version: '1.2.0'), would be '1.2.0'
147
+ #
148
+ # @return [nil] returns nil
149
+ #
150
+ def add_view(name, **options)
151
+ # TODO: add schema_url as part of options
152
+ @registered_views << View::RegisteredView.new(name, **options)
153
+ nil
135
154
  end
136
155
  end
137
156
  end
@@ -23,7 +23,8 @@ module OpenTelemetry
23
23
  def collect
24
24
  @mutex.synchronize do
25
25
  @epoch_end_time = now_in_nano
26
- snapshot = @metric_streams.map { |ms| ms.collect(@epoch_start_time, @epoch_end_time) }
26
+ # snapshot = @metric_streams.map { |ms| ms.collect(@epoch_start_time, @epoch_end_time) }
27
+ snapshot = @metric_streams.flat_map { |ms| ms.collect(@epoch_start_time, @epoch_end_time) }
27
28
  @epoch_start_time = @epoch_end_time
28
29
  snapshot
29
30
  end
@@ -30,30 +30,61 @@ module OpenTelemetry
30
30
  @instrument_kind = instrument_kind
31
31
  @meter_provider = meter_provider
32
32
  @instrumentation_scope = instrumentation_scope
33
- @aggregation = aggregation
33
+ @default_aggregation = aggregation
34
+ @data_points = {}
35
+ @registered_views = []
34
36
 
37
+ find_registered_view
35
38
  @mutex = Mutex.new
36
39
  end
37
40
 
38
41
  def collect(start_time, end_time)
39
42
  @mutex.synchronize do
40
- MetricData.new(
41
- @name,
42
- @description,
43
- @unit,
44
- @instrument_kind,
45
- @meter_provider.resource,
46
- @instrumentation_scope,
47
- @aggregation.collect(start_time, end_time),
48
- @aggregation.aggregation_temporality,
49
- start_time,
50
- end_time
51
- )
43
+ metric_data = []
44
+ if @registered_views.empty?
45
+ metric_data << aggregate_metric_data(start_time, end_time)
46
+ else
47
+ @registered_views.each { |view| metric_data << aggregate_metric_data(start_time, end_time, aggregation: view.aggregation) }
48
+ end
49
+
50
+ metric_data
52
51
  end
53
52
  end
54
53
 
55
54
  def update(value, attributes)
56
- @mutex.synchronize { @aggregation.update(value, attributes) }
55
+ if @registered_views.empty?
56
+ @mutex.synchronize { @default_aggregation.update(value, attributes, @data_points) }
57
+ else
58
+ @registered_views.each do |view|
59
+ @mutex.synchronize do
60
+ attributes ||= {}
61
+ attributes.merge!(view.attribute_keys)
62
+ view.aggregation.update(value, attributes, @data_points) if view.valid_aggregation?
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ def aggregate_metric_data(start_time, end_time, aggregation: nil)
69
+ aggregator = aggregation || @default_aggregation
70
+ MetricData.new(
71
+ @name,
72
+ @description,
73
+ @unit,
74
+ @instrument_kind,
75
+ @meter_provider.resource,
76
+ @instrumentation_scope,
77
+ aggregator.collect(start_time, end_time, @data_points),
78
+ aggregator.aggregation_temporality,
79
+ start_time,
80
+ end_time
81
+ )
82
+ end
83
+
84
+ def find_registered_view
85
+ return if @meter_provider.nil?
86
+
87
+ @meter_provider.registered_views.each { |view| @registered_views << view if view.match_instrument?(self) }
57
88
  end
58
89
 
59
90
  def to_s
@@ -8,7 +8,7 @@ module OpenTelemetry
8
8
  module SDK
9
9
  module Metrics
10
10
  # Current OpenTelemetry metrics sdk version
11
- VERSION = '0.1.0'
11
+ VERSION = '0.3.0'
12
12
  end
13
13
  end
14
14
  end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright The OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ module SDK
9
+ module Metrics
10
+ module View
11
+ # RegisteredView is an internal class used to match Views with a given {MetricStream}
12
+ class RegisteredView
13
+ attr_reader :name, :aggregation, :attribute_keys, :regex
14
+
15
+ def initialize(name, **options)
16
+ @name = name
17
+ @options = options
18
+ @aggregation = options[:aggregation]
19
+ @attribute_keys = options[:attribute_keys] || {}
20
+
21
+ generate_regex_pattern(name)
22
+ end
23
+
24
+ def match_instrument?(metric_stream)
25
+ return false if @name && !name_match(metric_stream.name)
26
+ return false if @options[:type] && @options[:type] != metric_stream.instrument_kind
27
+ return false if @options[:unit] && @options[:unit] != metric_stream.unit
28
+ return false if @options[:meter_name] && @options[:meter_name] != metric_stream.instrumentation_scope.name
29
+ return false if @options[:meter_version] && @options[:meter_version] != metric_stream.instrumentation_scope.version
30
+
31
+ true
32
+ end
33
+
34
+ def name_match(stream_name)
35
+ !!@regex&.match(stream_name)
36
+ end
37
+
38
+ def valid_aggregation?
39
+ @aggregation.class.name.rpartition('::')[0] == 'OpenTelemetry::SDK::Metrics::Aggregation'
40
+ end
41
+
42
+ private
43
+
44
+ def generate_regex_pattern(view_name)
45
+ regex_pattern = Regexp.escape(view_name)
46
+
47
+ regex_pattern.gsub!('\*', '.*')
48
+ regex_pattern.gsub!('\?', '.')
49
+
50
+ @regex = Regexp.new("^#{regex_pattern}$")
51
+ rescue StandardError
52
+ @regex = nil
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright The OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ module SDK
9
+ module Metrics
10
+ # A View provides SDK users with the flexibility to customize the metrics that are output by the SDK.
11
+ module View
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ require 'opentelemetry/sdk/metrics/view/registered_view'
@@ -20,3 +20,4 @@ require 'opentelemetry/sdk/metrics/instrument'
20
20
  require 'opentelemetry/sdk/metrics/meter'
21
21
  require 'opentelemetry/sdk/metrics/meter_provider'
22
22
  require 'opentelemetry/sdk/metrics/state'
23
+ require 'opentelemetry/sdk/metrics/view'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opentelemetry-metrics-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenTelemetry Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-31 00:00:00.000000000 Z
11
+ date: 2024-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opentelemetry-api
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: opentelemetry-metrics-api
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: 0.1.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: 0.1.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: opentelemetry-sdk
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 1.51.0
145
+ version: '1.65'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 1.51.0
152
+ version: '1.65'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: simplecov
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -206,8 +206,10 @@ files:
206
206
  - lib/opentelemetry-metrics-sdk.rb
207
207
  - lib/opentelemetry/sdk/metrics.rb
208
208
  - lib/opentelemetry/sdk/metrics/aggregation.rb
209
+ - lib/opentelemetry/sdk/metrics/aggregation/drop.rb
209
210
  - lib/opentelemetry/sdk/metrics/aggregation/explicit_bucket_histogram.rb
210
211
  - lib/opentelemetry/sdk/metrics/aggregation/histogram_data_point.rb
212
+ - lib/opentelemetry/sdk/metrics/aggregation/last_value.rb
211
213
  - lib/opentelemetry/sdk/metrics/aggregation/number_data_point.rb
212
214
  - lib/opentelemetry/sdk/metrics/aggregation/sum.rb
213
215
  - lib/opentelemetry/sdk/metrics/configuration_patch.rb
@@ -215,6 +217,7 @@ files:
215
217
  - lib/opentelemetry/sdk/metrics/export/console_metric_pull_exporter.rb
216
218
  - lib/opentelemetry/sdk/metrics/export/in_memory_metric_pull_exporter.rb
217
219
  - lib/opentelemetry/sdk/metrics/export/metric_reader.rb
220
+ - lib/opentelemetry/sdk/metrics/export/periodic_metric_reader.rb
218
221
  - lib/opentelemetry/sdk/metrics/instrument.rb
219
222
  - lib/opentelemetry/sdk/metrics/instrument/counter.rb
220
223
  - lib/opentelemetry/sdk/metrics/instrument/histogram.rb
@@ -230,14 +233,16 @@ files:
230
233
  - lib/opentelemetry/sdk/metrics/state/metric_store.rb
231
234
  - lib/opentelemetry/sdk/metrics/state/metric_stream.rb
232
235
  - lib/opentelemetry/sdk/metrics/version.rb
236
+ - lib/opentelemetry/sdk/metrics/view.rb
237
+ - lib/opentelemetry/sdk/metrics/view/registered_view.rb
233
238
  homepage: https://github.com/open-telemetry/opentelemetry-ruby
234
239
  licenses:
235
240
  - Apache-2.0
236
241
  metadata:
237
- changelog_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-metrics-sdk/v0.1.0/file.CHANGELOG.html
242
+ changelog_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-metrics-sdk/v0.3.0/file.CHANGELOG.html
238
243
  source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/main/metrics_sdk
239
244
  bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby/issues
240
- documentation_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-metrics-sdk/v0.1.0
245
+ documentation_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-metrics-sdk/v0.3.0
241
246
  post_install_message:
242
247
  rdoc_options: []
243
248
  require_paths: