opentelemetry-metrics-sdk 0.6.1 → 0.7.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 +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/opentelemetry/sdk/metrics/aggregation/exponential_bucket_histogram.rb +222 -0
- data/lib/opentelemetry/sdk/metrics/aggregation/exponential_histogram/buckets.rb +113 -0
- data/lib/opentelemetry/sdk/metrics/aggregation/exponential_histogram/exponent_mapping.rb +47 -0
- data/lib/opentelemetry/sdk/metrics/aggregation/exponential_histogram/ieee_754.rb +42 -0
- data/lib/opentelemetry/sdk/metrics/aggregation/exponential_histogram/log2e_scale_factor.rb +30 -0
- data/lib/opentelemetry/sdk/metrics/aggregation/exponential_histogram/logarithm_mapping.rb +56 -0
- data/lib/opentelemetry/sdk/metrics/aggregation/exponential_histogram_data_point.rb +31 -0
- data/lib/opentelemetry/sdk/metrics/aggregation.rb +2 -0
- data/lib/opentelemetry/sdk/metrics/state/metric_stream.rb +2 -2
- data/lib/opentelemetry/sdk/metrics/version.rb +1 -1
- metadata +11 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ad774f1262340ffa611f512b97fa605e92857ce72262bcdf7c60edc96a4d61e
|
4
|
+
data.tar.gz: 5be962ef2df37a6202e3fc99d5efca5846572824568cca61f33beb121daabb7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09a50b41250b9cbbc69a1d64a19652d9b4bac203f5111b0c9a794d4a15aac0327a67ac846a65cc083ae908dde4c3766d6cb65838b8d1af81b0d33bfac9e41ec4'
|
7
|
+
data.tar.gz: dc20ca5183f8423e32dcfb2b7dc810212f19ae2ac59a2026015983381662b388673540df3427a479a81c83756330aac4ce27e95161a50f239d8470fb6c6a4aea
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,222 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright The OpenTelemetry Authors
|
4
|
+
#
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
|
7
|
+
require_relative 'exponential_histogram/buckets'
|
8
|
+
require_relative 'exponential_histogram/log2e_scale_factor'
|
9
|
+
require_relative 'exponential_histogram/ieee_754'
|
10
|
+
require_relative 'exponential_histogram/logarithm_mapping'
|
11
|
+
require_relative 'exponential_histogram/exponent_mapping'
|
12
|
+
|
13
|
+
module OpenTelemetry
|
14
|
+
module SDK
|
15
|
+
module Metrics
|
16
|
+
module Aggregation
|
17
|
+
# Contains the implementation of the {https://opentelemetry.io/docs/specs/otel/metrics/data-model/#exponentialhistogram ExponentialBucketHistogram} aggregation
|
18
|
+
class ExponentialBucketHistogram # rubocop:disable Metrics/ClassLength
|
19
|
+
attr_reader :aggregation_temporality
|
20
|
+
|
21
|
+
# relate to min max scale: https://opentelemetry.io/docs/specs/otel/metrics/sdk/#support-a-minimum-and-maximum-scale
|
22
|
+
MAX_SCALE = 20
|
23
|
+
MIN_SCALE = -10
|
24
|
+
MAX_SIZE = 160
|
25
|
+
|
26
|
+
# The default boundaries are calculated based on default max_size and max_scale values
|
27
|
+
def initialize(
|
28
|
+
aggregation_temporality: ENV.fetch('OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE', :delta),
|
29
|
+
max_size: MAX_SIZE,
|
30
|
+
max_scale: MAX_SCALE,
|
31
|
+
record_min_max: true,
|
32
|
+
zero_threshold: 0
|
33
|
+
)
|
34
|
+
@aggregation_temporality = aggregation_temporality
|
35
|
+
@record_min_max = record_min_max
|
36
|
+
@min = Float::INFINITY
|
37
|
+
@max = -Float::INFINITY
|
38
|
+
@sum = 0
|
39
|
+
@count = 0
|
40
|
+
@zero_threshold = zero_threshold
|
41
|
+
@zero_count = 0
|
42
|
+
@size = validate_size(max_size)
|
43
|
+
@scale = validate_scale(max_scale)
|
44
|
+
|
45
|
+
@mapping = new_mapping(@scale)
|
46
|
+
end
|
47
|
+
|
48
|
+
def collect(start_time, end_time, data_points)
|
49
|
+
if @aggregation_temporality == :delta
|
50
|
+
# Set timestamps and 'move' data point values to result.
|
51
|
+
hdps = data_points.values.map! do |hdp|
|
52
|
+
hdp.start_time_unix_nano = start_time
|
53
|
+
hdp.time_unix_nano = end_time
|
54
|
+
hdp
|
55
|
+
end
|
56
|
+
data_points.clear
|
57
|
+
hdps
|
58
|
+
else
|
59
|
+
# Update timestamps and take a snapshot.
|
60
|
+
data_points.values.map! do |hdp|
|
61
|
+
hdp.start_time_unix_nano ||= start_time # Start time of a data point is from the first observation.
|
62
|
+
hdp.time_unix_nano = end_time
|
63
|
+
hdp = hdp.dup
|
64
|
+
hdp.positive = hdp.positive.dup
|
65
|
+
hdp.negative = hdp.negative.dup
|
66
|
+
hdp
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# rubocop:disable Metrics/MethodLength
|
72
|
+
def update(amount, attributes, data_points)
|
73
|
+
# fetch or initialize the ExponentialHistogramDataPoint
|
74
|
+
hdp = data_points.fetch(attributes) do
|
75
|
+
if @record_min_max
|
76
|
+
min = Float::INFINITY
|
77
|
+
max = -Float::INFINITY
|
78
|
+
end
|
79
|
+
|
80
|
+
data_points[attributes] = ExponentialHistogramDataPoint.new(
|
81
|
+
attributes,
|
82
|
+
nil, # :start_time_unix_nano
|
83
|
+
0, # :time_unix_nano
|
84
|
+
0, # :count
|
85
|
+
0, # :sum
|
86
|
+
@scale, # :scale
|
87
|
+
@zero_count, # :zero_count
|
88
|
+
ExponentialHistogram::Buckets.new, # :positive
|
89
|
+
ExponentialHistogram::Buckets.new, # :negative
|
90
|
+
0, # :flags
|
91
|
+
nil, # :exemplars
|
92
|
+
min, # :min
|
93
|
+
max, # :max
|
94
|
+
@zero_threshold # :zero_threshold)
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Start to populate the data point (esp. the buckets)
|
99
|
+
if @record_min_max
|
100
|
+
hdp.max = amount if amount > hdp.max
|
101
|
+
hdp.min = amount if amount < hdp.min
|
102
|
+
end
|
103
|
+
|
104
|
+
hdp.sum += amount
|
105
|
+
hdp.count += 1
|
106
|
+
|
107
|
+
if amount.abs <= @zero_threshold
|
108
|
+
hdp.zero_count += 1
|
109
|
+
hdp.scale = 0 if hdp.count == hdp.zero_count # if always getting zero, then there is no point to keep doing the update
|
110
|
+
return
|
111
|
+
end
|
112
|
+
|
113
|
+
# rescale, map to index, update the buckets here
|
114
|
+
buckets = amount.positive? ? hdp.positive : hdp.negative
|
115
|
+
amount = -amount if amount.negative?
|
116
|
+
|
117
|
+
bucket_index = @mapping.map_to_index(amount)
|
118
|
+
|
119
|
+
rescaling_needed = false
|
120
|
+
low = high = 0
|
121
|
+
|
122
|
+
if buckets.counts == [0] # special case of empty
|
123
|
+
buckets.index_start = bucket_index
|
124
|
+
buckets.index_end = bucket_index
|
125
|
+
buckets.index_base = bucket_index
|
126
|
+
|
127
|
+
elsif bucket_index < buckets.index_start && (buckets.index_end - bucket_index) >= @size
|
128
|
+
rescaling_needed = true
|
129
|
+
low = bucket_index
|
130
|
+
high = buckets.index_end
|
131
|
+
|
132
|
+
elsif bucket_index > buckets.index_end && (bucket_index - buckets.index_start) >= @size
|
133
|
+
rescaling_needed = true
|
134
|
+
low = buckets.index_start
|
135
|
+
high = bucket_index
|
136
|
+
end
|
137
|
+
|
138
|
+
if rescaling_needed
|
139
|
+
scale_change = get_scale_change(low, high)
|
140
|
+
downscale(scale_change, hdp.positive, hdp.negative)
|
141
|
+
new_scale = @mapping.scale - scale_change
|
142
|
+
hdp.scale = new_scale
|
143
|
+
@mapping = new_mapping(new_scale)
|
144
|
+
bucket_index = @mapping.map_to_index(amount)
|
145
|
+
|
146
|
+
OpenTelemetry.logger.debug "Rescaled with new scale #{new_scale} from #{low} and #{high}; bucket_index is updated to #{bucket_index}"
|
147
|
+
end
|
148
|
+
|
149
|
+
# adjust buckets based on the bucket_index
|
150
|
+
if bucket_index < buckets.index_start
|
151
|
+
span = buckets.index_end - bucket_index
|
152
|
+
grow_buckets(span, buckets)
|
153
|
+
buckets.index_start = bucket_index
|
154
|
+
elsif bucket_index > buckets.index_end
|
155
|
+
span = bucket_index - buckets.index_start
|
156
|
+
grow_buckets(span, buckets)
|
157
|
+
buckets.index_end = bucket_index
|
158
|
+
end
|
159
|
+
|
160
|
+
bucket_index -= buckets.index_base
|
161
|
+
bucket_index += buckets.counts.size if bucket_index.negative?
|
162
|
+
|
163
|
+
buckets.increment_bucket(bucket_index)
|
164
|
+
nil
|
165
|
+
end
|
166
|
+
# rubocop:enable Metrics/MethodLength
|
167
|
+
|
168
|
+
private
|
169
|
+
|
170
|
+
def grow_buckets(span, buckets)
|
171
|
+
return if span < buckets.counts.size
|
172
|
+
|
173
|
+
OpenTelemetry.logger.debug "buckets need to grow to #{span + 1} from #{buckets.counts.size} (max bucket size #{@size})"
|
174
|
+
buckets.grow(span + 1, @size)
|
175
|
+
end
|
176
|
+
|
177
|
+
def new_mapping(scale)
|
178
|
+
scale <= 0 ? ExponentialHistogram::ExponentMapping.new(scale) : ExponentialHistogram::LogarithmMapping.new(scale)
|
179
|
+
end
|
180
|
+
|
181
|
+
def empty_counts
|
182
|
+
@boundaries ? Array.new(@boundaries.size + 1, 0) : nil
|
183
|
+
end
|
184
|
+
|
185
|
+
def get_scale_change(low, high)
|
186
|
+
# puts "get_scale_change: low: #{low}, high: #{high}, @size: #{@size}"
|
187
|
+
# python code also produce 18 with 0,1048575, the high is little bit off
|
188
|
+
# just checked, the mapping is also ok, produce the 1048575
|
189
|
+
change = 0
|
190
|
+
while high - low >= @size
|
191
|
+
high >>= 1
|
192
|
+
low >>= 1
|
193
|
+
change += 1
|
194
|
+
end
|
195
|
+
change
|
196
|
+
end
|
197
|
+
|
198
|
+
def downscale(change, positive, negative)
|
199
|
+
return if change <= 0
|
200
|
+
|
201
|
+
positive.downscale(change)
|
202
|
+
negative.downscale(change)
|
203
|
+
end
|
204
|
+
|
205
|
+
def validate_scale(scale)
|
206
|
+
return scale unless scale > MAX_SCALE || scale < MIN_SCALE
|
207
|
+
|
208
|
+
OpenTelemetry.logger.warn "Scale #{scale} is invalid, using default max scale #{MAX_SCALE}"
|
209
|
+
MAX_SCALE
|
210
|
+
end
|
211
|
+
|
212
|
+
def validate_size(size)
|
213
|
+
return size unless size > MAX_SIZE || size < 0
|
214
|
+
|
215
|
+
OpenTelemetry.logger.warn "Size #{size} is invalid, using default max size #{MAX_SIZE}"
|
216
|
+
MAX_SIZE
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
@@ -0,0 +1,113 @@
|
|
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
|
+
module ExponentialHistogram
|
12
|
+
# Buckets is the fundamental building block of exponential histogram that store bucket/boundary value
|
13
|
+
class Buckets
|
14
|
+
attr_accessor :index_start, :index_end, :index_base
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@counts = [0]
|
18
|
+
@index_base = 0
|
19
|
+
@index_start = 0
|
20
|
+
@index_end = 0
|
21
|
+
end
|
22
|
+
|
23
|
+
# grow simply expand the @counts size
|
24
|
+
def grow(needed, max_size)
|
25
|
+
size = @counts.size
|
26
|
+
bias = @index_base - @index_start
|
27
|
+
old_positive_limit = size - bias
|
28
|
+
|
29
|
+
new_size = [2**Math.log2(needed).ceil, max_size].min
|
30
|
+
|
31
|
+
new_positive_limit = new_size - bias
|
32
|
+
|
33
|
+
tmp = Array.new(new_size, 0)
|
34
|
+
tmp[new_positive_limit..-1] = @counts[old_positive_limit..]
|
35
|
+
tmp[0...old_positive_limit] = @counts[0...old_positive_limit]
|
36
|
+
@counts = tmp
|
37
|
+
end
|
38
|
+
|
39
|
+
def offset
|
40
|
+
@index_start
|
41
|
+
end
|
42
|
+
|
43
|
+
def offset_counts
|
44
|
+
bias = @index_base - @index_start
|
45
|
+
@counts[-bias..] + @counts[0...-bias]
|
46
|
+
end
|
47
|
+
alias counts offset_counts
|
48
|
+
|
49
|
+
def length
|
50
|
+
return 0 if @counts.empty?
|
51
|
+
return 0 if @index_end == @index_start && counts[0] == 0
|
52
|
+
|
53
|
+
@index_end - @index_start + 1
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_bucket(key)
|
57
|
+
bias = @index_base - @index_start
|
58
|
+
|
59
|
+
key += @counts.size if key < bias
|
60
|
+
key -= bias
|
61
|
+
|
62
|
+
@counts[key]
|
63
|
+
end
|
64
|
+
|
65
|
+
def downscale(amount)
|
66
|
+
bias = @index_base - @index_start
|
67
|
+
|
68
|
+
if bias != 0
|
69
|
+
@index_base = @index_start
|
70
|
+
@counts.reverse!
|
71
|
+
@counts = @counts[0...bias].reverse + @counts[bias..].reverse
|
72
|
+
end
|
73
|
+
|
74
|
+
size = 1 + @index_end - @index_start
|
75
|
+
each = 1 << amount
|
76
|
+
inpos = 0
|
77
|
+
outpos = 0
|
78
|
+
pos = @index_start
|
79
|
+
|
80
|
+
while pos <= @index_end
|
81
|
+
mod = pos % each
|
82
|
+
mod += each if mod < 0
|
83
|
+
|
84
|
+
inds = mod
|
85
|
+
|
86
|
+
while inds < each && inpos < size
|
87
|
+
if outpos != inpos
|
88
|
+
@counts[outpos] += @counts[inpos]
|
89
|
+
@counts[inpos] = 0
|
90
|
+
end
|
91
|
+
|
92
|
+
inpos += 1
|
93
|
+
pos += 1
|
94
|
+
inds += 1
|
95
|
+
end
|
96
|
+
|
97
|
+
outpos += 1
|
98
|
+
end
|
99
|
+
|
100
|
+
@index_start >>= amount
|
101
|
+
@index_end >>= amount
|
102
|
+
@index_base = @index_start
|
103
|
+
end
|
104
|
+
|
105
|
+
def increment_bucket(bucket_index, increment = 1)
|
106
|
+
@counts[bucket_index] += increment
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,47 @@
|
|
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
|
+
module ExponentialHistogram
|
12
|
+
# LogarithmMapping for mapping when scale < 0
|
13
|
+
class ExponentMapping
|
14
|
+
attr_reader :scale
|
15
|
+
|
16
|
+
def initialize(scale)
|
17
|
+
@scale = scale
|
18
|
+
@min_normal_lower_boundary_index = calculate_min_normal_lower_boundary_index(scale)
|
19
|
+
@max_normal_lower_boundary_index = IEEE754::MAX_NORMAL_EXPONENT >> -@scale
|
20
|
+
end
|
21
|
+
|
22
|
+
def map_to_index(value)
|
23
|
+
return @min_normal_lower_boundary_index if value < IEEE754::MIN_NORMAL_VALUE
|
24
|
+
|
25
|
+
exponent = IEEE754.get_ieee_754_exponent(value)
|
26
|
+
correction = (IEEE754.get_ieee_754_mantissa(value) - 1) >> IEEE754::MANTISSA_WIDTH
|
27
|
+
(exponent + correction) >> -@scale
|
28
|
+
end
|
29
|
+
|
30
|
+
def calculate_min_normal_lower_boundary_index(scale)
|
31
|
+
inds = IEEE754::MIN_NORMAL_EXPONENT >> -scale
|
32
|
+
inds -= 1 if -scale < 2
|
33
|
+
inds
|
34
|
+
end
|
35
|
+
|
36
|
+
# for testing
|
37
|
+
def get_lower_boundary(inds)
|
38
|
+
raise StandardError, 'mapping underflow' if inds < @min_normal_lower_boundary_index || inds > @max_normal_lower_boundary_index
|
39
|
+
|
40
|
+
Math.ldexp(1, inds << -@scale)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,42 @@
|
|
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
|
+
module ExponentialHistogram
|
12
|
+
# IEEE754 standard for floating-point calculation
|
13
|
+
module IEEE754
|
14
|
+
MANTISSA_WIDTH = 52
|
15
|
+
EXPONENT_WIDTH = 11
|
16
|
+
|
17
|
+
MANTISSA_MASK = (1 << MANTISSA_WIDTH) - 1
|
18
|
+
EXPONENT_BIAS = (2**(EXPONENT_WIDTH - 1)) - 1
|
19
|
+
EXPONENT_MASK = ((1 << EXPONENT_WIDTH) - 1) << MANTISSA_WIDTH
|
20
|
+
SIGN_MASK = 1 << (EXPONENT_WIDTH + MANTISSA_WIDTH)
|
21
|
+
|
22
|
+
MIN_NORMAL_EXPONENT = -EXPONENT_BIAS + 1
|
23
|
+
MAX_NORMAL_EXPONENT = EXPONENT_BIAS
|
24
|
+
|
25
|
+
MIN_NORMAL_VALUE = Float::MIN
|
26
|
+
MAX_NORMAL_VALUE = Float::MAX
|
27
|
+
|
28
|
+
def self.get_ieee_754_exponent(value)
|
29
|
+
bits = [value].pack('d').unpack1('Q')
|
30
|
+
((bits & EXPONENT_MASK) >> MANTISSA_WIDTH) - EXPONENT_BIAS
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.get_ieee_754_mantissa(value)
|
34
|
+
bits = [value].pack('d').unpack1('Q')
|
35
|
+
bits & MANTISSA_MASK
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
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
|
+
module OpenTelemetry
|
8
|
+
module SDK
|
9
|
+
module Metrics
|
10
|
+
module Aggregation
|
11
|
+
module ExponentialHistogram
|
12
|
+
# Log2eScaleFactor is precomputed scale factor value
|
13
|
+
class Log2eScaleFactor
|
14
|
+
MAX_SCALE = 20
|
15
|
+
|
16
|
+
LOG2E_SCALE_BUCKETS = (0..MAX_SCALE).map do |scale|
|
17
|
+
log2e = 1 / Math.log(2)
|
18
|
+
Math.ldexp(log2e, scale)
|
19
|
+
end
|
20
|
+
|
21
|
+
# for testing
|
22
|
+
def self.log2e_scale_buckets
|
23
|
+
LOG2E_SCALE_BUCKETS
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
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
|
+
module OpenTelemetry
|
8
|
+
module SDK
|
9
|
+
module Metrics
|
10
|
+
module Aggregation
|
11
|
+
module ExponentialHistogram
|
12
|
+
# LogarithmMapping for mapping when scale > 0
|
13
|
+
class LogarithmMapping
|
14
|
+
attr_reader :scale
|
15
|
+
|
16
|
+
def initialize(scale)
|
17
|
+
@scale = scale
|
18
|
+
@scale_factor = Log2eScaleFactor::LOG2E_SCALE_BUCKETS[scale] # scale_factor is used for mapping the index
|
19
|
+
@min_normal_lower_boundary_index = IEEE754::MIN_NORMAL_EXPONENT << @scale
|
20
|
+
@max_normal_lower_boundary_index = ((IEEE754::MAX_NORMAL_EXPONENT + 1) << @scale) - 1
|
21
|
+
end
|
22
|
+
|
23
|
+
def map_to_index(value)
|
24
|
+
return @min_normal_lower_boundary_index - 1 if value <= IEEE754::MIN_NORMAL_VALUE
|
25
|
+
|
26
|
+
if IEEE754.get_ieee_754_mantissa(value) == 0
|
27
|
+
exponent = IEEE754.get_ieee_754_exponent(value)
|
28
|
+
return (exponent << @scale) - 1
|
29
|
+
end
|
30
|
+
|
31
|
+
[(Math.log(value) * @scale_factor).floor, @max_normal_lower_boundary_index].min
|
32
|
+
end
|
33
|
+
|
34
|
+
# for testing
|
35
|
+
def get_lower_boundary(inds)
|
36
|
+
if inds >= @max_normal_lower_boundary_index
|
37
|
+
return 2 * Math.exp((inds - (1 << @scale)) / @scale_factor) if inds == @max_normal_lower_boundary_index
|
38
|
+
|
39
|
+
raise StandardError, 'mapping overflow'
|
40
|
+
end
|
41
|
+
|
42
|
+
if inds <= @min_normal_lower_boundary_index
|
43
|
+
return IEEE754::MIN_NORMAL_VALUE if inds == @min_normal_lower_boundary_index
|
44
|
+
return Math.exp((inds + (1 << @scale)) / @scale_factor) / 2 if inds == @min_normal_lower_boundary_index - 1
|
45
|
+
|
46
|
+
raise StandardError, 'mapping underflow'
|
47
|
+
end
|
48
|
+
|
49
|
+
Math.exp(inds / @scale_factor)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,31 @@
|
|
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
|
+
# rubocop:disable Lint/StructNewOverride
|
12
|
+
|
13
|
+
ExponentialHistogramDataPoint = Struct.new(:attributes, # optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}
|
14
|
+
:start_time_unix_nano, # Integer nanoseconds since Epoch
|
15
|
+
:time_unix_nano, # Integer nanoseconds since Epoch
|
16
|
+
:count, # Integer count is the number of values in the population. Must be non-negative
|
17
|
+
:sum, # Integer sum of the values in the population. If count is zero then this field then this field must be zero
|
18
|
+
:scale, # Integer scale factor
|
19
|
+
:zero_count, # Integer special bucket that count of observations that fall into the zero bucket
|
20
|
+
:positive, # Buckets representing the positive range of the histogram.
|
21
|
+
:negative, # Buckets representing the negative range of the histogram.
|
22
|
+
:flags, # Integer flags associated with the data point.
|
23
|
+
:exemplars, # optional List of exemplars collected from measurements that were used to form the data point
|
24
|
+
:min, # optional Float min is the minimum value over (start_time, end_time].
|
25
|
+
:max, # optional Float max is the maximum value over (start_time, end_time].
|
26
|
+
:zero_threshold) # optional Float the threshold for the zero bucket
|
27
|
+
# rubocop:enable Lint/StructNewOverride
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -21,3 +21,5 @@ require 'opentelemetry/sdk/metrics/aggregation/explicit_bucket_histogram'
|
|
21
21
|
require 'opentelemetry/sdk/metrics/aggregation/sum'
|
22
22
|
require 'opentelemetry/sdk/metrics/aggregation/last_value'
|
23
23
|
require 'opentelemetry/sdk/metrics/aggregation/drop'
|
24
|
+
require 'opentelemetry/sdk/metrics/aggregation/exponential_histogram_data_point'
|
25
|
+
require 'opentelemetry/sdk/metrics/aggregation/exponential_bucket_histogram'
|
@@ -91,12 +91,12 @@ module OpenTelemetry
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def to_s
|
94
|
-
instrument_info =
|
94
|
+
instrument_info = +''
|
95
95
|
instrument_info << "name=#{@name}"
|
96
96
|
instrument_info << " description=#{@description}" if @description
|
97
97
|
instrument_info << " unit=#{@unit}" if @unit
|
98
98
|
@data_points.map do |attributes, value|
|
99
|
-
metric_stream_string =
|
99
|
+
metric_stream_string = +''
|
100
100
|
metric_stream_string << instrument_info
|
101
101
|
metric_stream_string << " attributes=#{attributes}" if attributes
|
102
102
|
metric_stream_string << " #{value}"
|
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.
|
4
|
+
version: 0.7.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: 2025-
|
11
|
+
date: 2025-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opentelemetry-api
|
@@ -208,6 +208,13 @@ files:
|
|
208
208
|
- lib/opentelemetry/sdk/metrics/aggregation.rb
|
209
209
|
- lib/opentelemetry/sdk/metrics/aggregation/drop.rb
|
210
210
|
- lib/opentelemetry/sdk/metrics/aggregation/explicit_bucket_histogram.rb
|
211
|
+
- lib/opentelemetry/sdk/metrics/aggregation/exponential_bucket_histogram.rb
|
212
|
+
- lib/opentelemetry/sdk/metrics/aggregation/exponential_histogram/buckets.rb
|
213
|
+
- lib/opentelemetry/sdk/metrics/aggregation/exponential_histogram/exponent_mapping.rb
|
214
|
+
- lib/opentelemetry/sdk/metrics/aggregation/exponential_histogram/ieee_754.rb
|
215
|
+
- lib/opentelemetry/sdk/metrics/aggregation/exponential_histogram/log2e_scale_factor.rb
|
216
|
+
- lib/opentelemetry/sdk/metrics/aggregation/exponential_histogram/logarithm_mapping.rb
|
217
|
+
- lib/opentelemetry/sdk/metrics/aggregation/exponential_histogram_data_point.rb
|
211
218
|
- lib/opentelemetry/sdk/metrics/aggregation/histogram_data_point.rb
|
212
219
|
- lib/opentelemetry/sdk/metrics/aggregation/last_value.rb
|
213
220
|
- lib/opentelemetry/sdk/metrics/aggregation/number_data_point.rb
|
@@ -240,10 +247,10 @@ homepage: https://github.com/open-telemetry/opentelemetry-ruby
|
|
240
247
|
licenses:
|
241
248
|
- Apache-2.0
|
242
249
|
metadata:
|
243
|
-
changelog_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-metrics-sdk/v0.
|
250
|
+
changelog_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-metrics-sdk/v0.7.0/file.CHANGELOG.html
|
244
251
|
source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby/tree/main/metrics_sdk
|
245
252
|
bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby/issues
|
246
|
-
documentation_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-metrics-sdk/v0.
|
253
|
+
documentation_uri: https://open-telemetry.github.io/opentelemetry-ruby/opentelemetry-metrics-sdk/v0.7.0
|
247
254
|
post_install_message:
|
248
255
|
rdoc_options: []
|
249
256
|
require_paths:
|