summaryrefslogtreecommitdiff
path: root/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go')
-rw-r--r--vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go165
1 files changed, 79 insertions, 86 deletions
diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go
index 4139a6d15..707342408 100644
--- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go
+++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go
@@ -1,16 +1,5 @@
// Copyright The OpenTelemetry Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+// SPDX-License-Identifier: Apache-2.0
package aggregate // import "go.opentelemetry.io/otel/sdk/metric/internal/aggregate"
@@ -41,7 +30,8 @@ const (
// expoHistogramDataPoint is a single data point in an exponential histogram.
type expoHistogramDataPoint[N int64 | float64] struct {
- res exemplar.Reservoir[N]
+ attrs attribute.Set
+ res exemplar.FilteredReservoir[N]
count uint64
min N
@@ -52,14 +42,14 @@ type expoHistogramDataPoint[N int64 | float64] struct {
noMinMax bool
noSum bool
- scale int
+ scale int32
posBuckets expoBuckets
negBuckets expoBuckets
zeroCount uint64
}
-func newExpoHistogramDataPoint[N int64 | float64](maxSize, maxScale int, noMinMax, noSum bool) *expoHistogramDataPoint[N] {
+func newExpoHistogramDataPoint[N int64 | float64](attrs attribute.Set, maxSize int, maxScale int32, noMinMax, noSum bool) *expoHistogramDataPoint[N] {
f := math.MaxFloat64
max := N(f) // if N is int64, max will overflow to -9223372036854775808
min := N(-f)
@@ -68,6 +58,7 @@ func newExpoHistogramDataPoint[N int64 | float64](maxSize, maxScale int, noMinMa
min = N(minInt64)
}
return &expoHistogramDataPoint[N]{
+ attrs: attrs,
min: max,
max: min,
maxSize: maxSize,
@@ -128,11 +119,13 @@ func (p *expoHistogramDataPoint[N]) record(v N) {
}
// getBin returns the bin v should be recorded into.
-func (p *expoHistogramDataPoint[N]) getBin(v float64) int {
- frac, exp := math.Frexp(v)
+func (p *expoHistogramDataPoint[N]) getBin(v float64) int32 {
+ frac, expInt := math.Frexp(v)
+ // 11-bit exponential.
+ exp := int32(expInt) // nolint: gosec
if p.scale <= 0 {
// Because of the choice of fraction is always 1 power of two higher than we want.
- correction := 1
+ var correction int32 = 1
if frac == .5 {
// If v is an exact power of two the frac will be .5 and the exp
// will be one higher than we want.
@@ -140,7 +133,7 @@ func (p *expoHistogramDataPoint[N]) getBin(v float64) int {
}
return (exp - correction) >> (-p.scale)
}
- return exp<<p.scale + int(math.Log(frac)*scaleFactors[p.scale]) - 1
+ return exp<<p.scale + int32(math.Log(frac)*scaleFactors[p.scale]) - 1
}
// scaleFactors are constants used in calculating the logarithm index. They are
@@ -171,20 +164,20 @@ var scaleFactors = [21]float64{
// scaleChange returns the magnitude of the scale change needed to fit bin in
// the bucket. If no scale change is needed 0 is returned.
-func (p *expoHistogramDataPoint[N]) scaleChange(bin, startBin, length int) int {
+func (p *expoHistogramDataPoint[N]) scaleChange(bin, startBin int32, length int) int32 {
if length == 0 {
// No need to rescale if there are no buckets.
return 0
}
- low := startBin
- high := bin
+ low := int(startBin)
+ high := int(bin)
if startBin >= bin {
- low = bin
- high = startBin + length - 1
+ low = int(bin)
+ high = int(startBin) + length - 1
}
- count := 0
+ var count int32
for high-low >= p.maxSize {
low = low >> 1
high = high >> 1
@@ -198,39 +191,39 @@ func (p *expoHistogramDataPoint[N]) scaleChange(bin, startBin, length int) int {
// expoBuckets is a set of buckets in an exponential histogram.
type expoBuckets struct {
- startBin int
+ startBin int32
counts []uint64
}
// record increments the count for the given bin, and expands the buckets if needed.
// Size changes must be done before calling this function.
-func (b *expoBuckets) record(bin int) {
+func (b *expoBuckets) record(bin int32) {
if len(b.counts) == 0 {
b.counts = []uint64{1}
b.startBin = bin
return
}
- endBin := b.startBin + len(b.counts) - 1
+ endBin := int(b.startBin) + len(b.counts) - 1
// if the new bin is inside the current range
- if bin >= b.startBin && bin <= endBin {
+ if bin >= b.startBin && int(bin) <= endBin {
b.counts[bin-b.startBin]++
return
}
// if the new bin is before the current start add spaces to the counts
if bin < b.startBin {
origLen := len(b.counts)
- newLength := endBin - bin + 1
+ newLength := endBin - int(bin) + 1
shift := b.startBin - bin
if newLength > cap(b.counts) {
b.counts = append(b.counts, make([]uint64, newLength-len(b.counts))...)
}
- copy(b.counts[shift:origLen+shift], b.counts[:])
+ copy(b.counts[shift:origLen+int(shift)], b.counts[:])
b.counts = b.counts[:newLength]
- for i := 1; i < shift; i++ {
+ for i := 1; i < int(shift); i++ {
b.counts[i] = 0
}
b.startBin = bin
@@ -238,17 +231,17 @@ func (b *expoBuckets) record(bin int) {
return
}
// if the new is after the end add spaces to the end
- if bin > endBin {
- if bin-b.startBin < cap(b.counts) {
+ if int(bin) > endBin {
+ if int(bin-b.startBin) < cap(b.counts) {
b.counts = b.counts[:bin-b.startBin+1]
- for i := endBin + 1 - b.startBin; i < len(b.counts); i++ {
+ for i := endBin + 1 - int(b.startBin); i < len(b.counts); i++ {
b.counts[i] = 0
}
b.counts[bin-b.startBin] = 1
return
}
- end := make([]uint64, bin-b.startBin-len(b.counts)+1)
+ end := make([]uint64, int(bin-b.startBin)-len(b.counts)+1)
b.counts = append(b.counts, end...)
b.counts[bin-b.startBin] = 1
}
@@ -256,7 +249,7 @@ func (b *expoBuckets) record(bin int) {
// downscale shrinks a bucket by a factor of 2*s. It will sum counts into the
// correct lower resolution bucket.
-func (b *expoBuckets) downscale(delta int) {
+func (b *expoBuckets) downscale(delta int32) {
// Example
// delta = 2
// Original offset: -6
@@ -271,19 +264,19 @@ func (b *expoBuckets) downscale(delta int) {
return
}
- steps := 1 << delta
+ steps := int32(1) << delta
offset := b.startBin % steps
offset = (offset + steps) % steps // to make offset positive
for i := 1; i < len(b.counts); i++ {
- idx := i + offset
- if idx%steps == 0 {
- b.counts[idx/steps] = b.counts[i]
+ idx := i + int(offset)
+ if idx%int(steps) == 0 {
+ b.counts[idx/int(steps)] = b.counts[i]
continue
}
- b.counts[idx/steps] += b.counts[i]
+ b.counts[idx/int(steps)] += b.counts[i]
}
- lastIdx := (len(b.counts) - 1 + offset) / steps
+ lastIdx := (len(b.counts) - 1 + int(offset)) / int(steps)
b.counts = b.counts[:lastIdx+1]
b.startBin = b.startBin >> delta
}
@@ -291,16 +284,16 @@ func (b *expoBuckets) downscale(delta int) {
// newExponentialHistogram returns an Aggregator that summarizes a set of
// measurements as an exponential histogram. Each histogram is scoped by attributes
// and the aggregation cycle the measurements were made in.
-func newExponentialHistogram[N int64 | float64](maxSize, maxScale int32, noMinMax, noSum bool, limit int, r func() exemplar.Reservoir[N]) *expoHistogram[N] {
+func newExponentialHistogram[N int64 | float64](maxSize, maxScale int32, noMinMax, noSum bool, limit int, r func() exemplar.FilteredReservoir[N]) *expoHistogram[N] {
return &expoHistogram[N]{
noSum: noSum,
noMinMax: noMinMax,
maxSize: int(maxSize),
- maxScale: int(maxScale),
+ maxScale: maxScale,
newRes: r,
limit: newLimiter[*expoHistogramDataPoint[N]](limit),
- values: make(map[attribute.Set]*expoHistogramDataPoint[N]),
+ values: make(map[attribute.Distinct]*expoHistogramDataPoint[N]),
start: now(),
}
@@ -312,11 +305,11 @@ type expoHistogram[N int64 | float64] struct {
noSum bool
noMinMax bool
maxSize int
- maxScale int
+ maxScale int32
- newRes func() exemplar.Reservoir[N]
+ newRes func() exemplar.FilteredReservoir[N]
limit limiter[*expoHistogramDataPoint[N]]
- values map[attribute.Set]*expoHistogramDataPoint[N]
+ values map[attribute.Distinct]*expoHistogramDataPoint[N]
valuesMu sync.Mutex
start time.Time
@@ -328,21 +321,19 @@ func (e *expoHistogram[N]) measure(ctx context.Context, value N, fltrAttr attrib
return
}
- t := now()
-
e.valuesMu.Lock()
defer e.valuesMu.Unlock()
attr := e.limit.Attributes(fltrAttr, e.values)
- v, ok := e.values[attr]
+ v, ok := e.values[attr.Equivalent()]
if !ok {
- v = newExpoHistogramDataPoint[N](e.maxSize, e.maxScale, e.noMinMax, e.noSum)
+ v = newExpoHistogramDataPoint[N](attr, e.maxSize, e.maxScale, e.noMinMax, e.noSum)
v.res = e.newRes()
- e.values[attr] = v
+ e.values[attr.Equivalent()] = v
}
v.record(value)
- v.res.Offer(ctx, t, value, droppedAttr)
+ v.res.Offer(ctx, value, droppedAttr)
}
func (e *expoHistogram[N]) delta(dest *metricdata.Aggregation) int {
@@ -360,36 +351,38 @@ func (e *expoHistogram[N]) delta(dest *metricdata.Aggregation) int {
hDPts := reset(h.DataPoints, n, n)
var i int
- for a, b := range e.values {
- hDPts[i].Attributes = a
+ for _, val := range e.values {
+ hDPts[i].Attributes = val.attrs
hDPts[i].StartTime = e.start
hDPts[i].Time = t
- hDPts[i].Count = b.count
- hDPts[i].Scale = int32(b.scale)
- hDPts[i].ZeroCount = b.zeroCount
+ hDPts[i].Count = val.count
+ hDPts[i].Scale = val.scale
+ hDPts[i].ZeroCount = val.zeroCount
hDPts[i].ZeroThreshold = 0.0
- hDPts[i].PositiveBucket.Offset = int32(b.posBuckets.startBin)
- hDPts[i].PositiveBucket.Counts = reset(hDPts[i].PositiveBucket.Counts, len(b.posBuckets.counts), len(b.posBuckets.counts))
- copy(hDPts[i].PositiveBucket.Counts, b.posBuckets.counts)
+ hDPts[i].PositiveBucket.Offset = val.posBuckets.startBin
+ hDPts[i].PositiveBucket.Counts = reset(hDPts[i].PositiveBucket.Counts, len(val.posBuckets.counts), len(val.posBuckets.counts))
+ copy(hDPts[i].PositiveBucket.Counts, val.posBuckets.counts)
- hDPts[i].NegativeBucket.Offset = int32(b.negBuckets.startBin)
- hDPts[i].NegativeBucket.Counts = reset(hDPts[i].NegativeBucket.Counts, len(b.negBuckets.counts), len(b.negBuckets.counts))
- copy(hDPts[i].NegativeBucket.Counts, b.negBuckets.counts)
+ hDPts[i].NegativeBucket.Offset = val.negBuckets.startBin
+ hDPts[i].NegativeBucket.Counts = reset(hDPts[i].NegativeBucket.Counts, len(val.negBuckets.counts), len(val.negBuckets.counts))
+ copy(hDPts[i].NegativeBucket.Counts, val.negBuckets.counts)
if !e.noSum {
- hDPts[i].Sum = b.sum
+ hDPts[i].Sum = val.sum
}
if !e.noMinMax {
- hDPts[i].Min = metricdata.NewExtrema(b.min)
- hDPts[i].Max = metricdata.NewExtrema(b.max)
+ hDPts[i].Min = metricdata.NewExtrema(val.min)
+ hDPts[i].Max = metricdata.NewExtrema(val.max)
}
- b.res.Collect(&hDPts[i].Exemplars)
+ collectExemplars(&hDPts[i].Exemplars, val.res.Collect)
- delete(e.values, a)
i++
}
+ // Unused attribute sets do not report.
+ clear(e.values)
+
e.start = t
h.DataPoints = hDPts
*dest = h
@@ -411,32 +404,32 @@ func (e *expoHistogram[N]) cumulative(dest *metricdata.Aggregation) int {
hDPts := reset(h.DataPoints, n, n)
var i int
- for a, b := range e.values {
- hDPts[i].Attributes = a
+ for _, val := range e.values {
+ hDPts[i].Attributes = val.attrs
hDPts[i].StartTime = e.start
hDPts[i].Time = t
- hDPts[i].Count = b.count
- hDPts[i].Scale = int32(b.scale)
- hDPts[i].ZeroCount = b.zeroCount
+ hDPts[i].Count = val.count
+ hDPts[i].Scale = val.scale
+ hDPts[i].ZeroCount = val.zeroCount
hDPts[i].ZeroThreshold = 0.0
- hDPts[i].PositiveBucket.Offset = int32(b.posBuckets.startBin)
- hDPts[i].PositiveBucket.Counts = reset(hDPts[i].PositiveBucket.Counts, len(b.posBuckets.counts), len(b.posBuckets.counts))
- copy(hDPts[i].PositiveBucket.Counts, b.posBuckets.counts)
+ hDPts[i].PositiveBucket.Offset = val.posBuckets.startBin
+ hDPts[i].PositiveBucket.Counts = reset(hDPts[i].PositiveBucket.Counts, len(val.posBuckets.counts), len(val.posBuckets.counts))
+ copy(hDPts[i].PositiveBucket.Counts, val.posBuckets.counts)
- hDPts[i].NegativeBucket.Offset = int32(b.negBuckets.startBin)
- hDPts[i].NegativeBucket.Counts = reset(hDPts[i].NegativeBucket.Counts, len(b.negBuckets.counts), len(b.negBuckets.counts))
- copy(hDPts[i].NegativeBucket.Counts, b.negBuckets.counts)
+ hDPts[i].NegativeBucket.Offset = val.negBuckets.startBin
+ hDPts[i].NegativeBucket.Counts = reset(hDPts[i].NegativeBucket.Counts, len(val.negBuckets.counts), len(val.negBuckets.counts))
+ copy(hDPts[i].NegativeBucket.Counts, val.negBuckets.counts)
if !e.noSum {
- hDPts[i].Sum = b.sum
+ hDPts[i].Sum = val.sum
}
if !e.noMinMax {
- hDPts[i].Min = metricdata.NewExtrema(b.min)
- hDPts[i].Max = metricdata.NewExtrema(b.max)
+ hDPts[i].Min = metricdata.NewExtrema(val.min)
+ hDPts[i].Max = metricdata.NewExtrema(val.max)
}
- b.res.Collect(&hDPts[i].Exemplars)
+ collectExemplars(&hDPts[i].Exemplars, val.res.Collect)
i++
// TODO (#3006): This will use an unbounded amount of memory if there