gotosocial/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go

239 lines
5.9 KiB
Go
Raw Normal View History

// Copyright The OpenTelemetry Authors
2024-08-26 16:05:54 +00:00
// SPDX-License-Identifier: Apache-2.0
package aggregate // import "go.opentelemetry.io/otel/sdk/metric/internal/aggregate"
import (
"context"
"sync"
"time"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/metric/internal/exemplar"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
)
type sumValue[N int64 | float64] struct {
2024-08-26 16:05:54 +00:00
n N
res exemplar.FilteredReservoir[N]
attrs attribute.Set
}
// valueMap is the storage for sums.
type valueMap[N int64 | float64] struct {
sync.Mutex
2024-08-26 16:05:54 +00:00
newRes func() exemplar.FilteredReservoir[N]
limit limiter[sumValue[N]]
2024-08-26 16:05:54 +00:00
values map[attribute.Distinct]sumValue[N]
}
2024-08-26 16:05:54 +00:00
func newValueMap[N int64 | float64](limit int, r func() exemplar.FilteredReservoir[N]) *valueMap[N] {
return &valueMap[N]{
newRes: r,
limit: newLimiter[sumValue[N]](limit),
2024-08-26 16:05:54 +00:00
values: make(map[attribute.Distinct]sumValue[N]),
}
}
func (s *valueMap[N]) measure(ctx context.Context, value N, fltrAttr attribute.Set, droppedAttr []attribute.KeyValue) {
s.Lock()
defer s.Unlock()
attr := s.limit.Attributes(fltrAttr, s.values)
2024-08-26 16:05:54 +00:00
v, ok := s.values[attr.Equivalent()]
if !ok {
v.res = s.newRes()
}
2024-08-26 16:05:54 +00:00
v.attrs = attr
v.n += value
2024-08-26 16:05:54 +00:00
v.res.Offer(ctx, value, droppedAttr)
2024-08-26 16:05:54 +00:00
s.values[attr.Equivalent()] = v
}
// newSum returns an aggregator that summarizes a set of measurements as their
// arithmetic sum. Each sum is scoped by attributes and the aggregation cycle
// the measurements were made in.
2024-08-26 16:05:54 +00:00
func newSum[N int64 | float64](monotonic bool, limit int, r func() exemplar.FilteredReservoir[N]) *sum[N] {
return &sum[N]{
valueMap: newValueMap[N](limit, r),
monotonic: monotonic,
start: now(),
}
}
// sum summarizes a set of measurements made as their arithmetic sum.
type sum[N int64 | float64] struct {
*valueMap[N]
monotonic bool
start time.Time
}
func (s *sum[N]) delta(dest *metricdata.Aggregation) int {
t := now()
// If *dest is not a metricdata.Sum, memory reuse is missed. In that case,
// use the zero-value sData and hope for better alignment next cycle.
sData, _ := (*dest).(metricdata.Sum[N])
sData.Temporality = metricdata.DeltaTemporality
sData.IsMonotonic = s.monotonic
s.Lock()
defer s.Unlock()
n := len(s.values)
dPts := reset(sData.DataPoints, n, n)
var i int
2024-08-26 16:05:54 +00:00
for _, val := range s.values {
dPts[i].Attributes = val.attrs
dPts[i].StartTime = s.start
dPts[i].Time = t
dPts[i].Value = val.n
2024-08-26 16:05:54 +00:00
collectExemplars(&dPts[i].Exemplars, val.res.Collect)
i++
}
2024-08-26 16:05:54 +00:00
// Do not report stale values.
clear(s.values)
// The delta collection cycle resets.
s.start = t
sData.DataPoints = dPts
*dest = sData
return n
}
func (s *sum[N]) cumulative(dest *metricdata.Aggregation) int {
t := now()
// If *dest is not a metricdata.Sum, memory reuse is missed. In that case,
// use the zero-value sData and hope for better alignment next cycle.
sData, _ := (*dest).(metricdata.Sum[N])
sData.Temporality = metricdata.CumulativeTemporality
sData.IsMonotonic = s.monotonic
s.Lock()
defer s.Unlock()
n := len(s.values)
dPts := reset(sData.DataPoints, n, n)
var i int
2024-08-26 16:05:54 +00:00
for _, value := range s.values {
dPts[i].Attributes = value.attrs
dPts[i].StartTime = s.start
dPts[i].Time = t
dPts[i].Value = value.n
2024-08-26 16:05:54 +00:00
collectExemplars(&dPts[i].Exemplars, value.res.Collect)
// TODO (#3006): This will use an unbounded amount of memory if there
// are unbounded number of attribute sets being aggregated. Attribute
// sets that become "stale" need to be forgotten so this will not
// overload the system.
i++
}
sData.DataPoints = dPts
*dest = sData
return n
}
// newPrecomputedSum returns an aggregator that summarizes a set of
// observations as their arithmetic sum. Each sum is scoped by attributes and
// the aggregation cycle the measurements were made in.
2024-08-26 16:05:54 +00:00
func newPrecomputedSum[N int64 | float64](monotonic bool, limit int, r func() exemplar.FilteredReservoir[N]) *precomputedSum[N] {
return &precomputedSum[N]{
valueMap: newValueMap[N](limit, r),
monotonic: monotonic,
start: now(),
}
}
// precomputedSum summarizes a set of observations as their arithmetic sum.
type precomputedSum[N int64 | float64] struct {
*valueMap[N]
monotonic bool
start time.Time
2024-08-26 16:05:54 +00:00
reported map[attribute.Distinct]N
}
func (s *precomputedSum[N]) delta(dest *metricdata.Aggregation) int {
t := now()
2024-08-26 16:05:54 +00:00
newReported := make(map[attribute.Distinct]N)
// If *dest is not a metricdata.Sum, memory reuse is missed. In that case,
// use the zero-value sData and hope for better alignment next cycle.
sData, _ := (*dest).(metricdata.Sum[N])
sData.Temporality = metricdata.DeltaTemporality
sData.IsMonotonic = s.monotonic
s.Lock()
defer s.Unlock()
n := len(s.values)
dPts := reset(sData.DataPoints, n, n)
var i int
2024-08-26 16:05:54 +00:00
for key, value := range s.values {
delta := value.n - s.reported[key]
2024-08-26 16:05:54 +00:00
dPts[i].Attributes = value.attrs
dPts[i].StartTime = s.start
dPts[i].Time = t
dPts[i].Value = delta
2024-08-26 16:05:54 +00:00
collectExemplars(&dPts[i].Exemplars, value.res.Collect)
2024-08-26 16:05:54 +00:00
newReported[key] = value.n
i++
}
2024-08-26 16:05:54 +00:00
// Unused attribute sets do not report.
clear(s.values)
s.reported = newReported
// The delta collection cycle resets.
s.start = t
sData.DataPoints = dPts
*dest = sData
return n
}
func (s *precomputedSum[N]) cumulative(dest *metricdata.Aggregation) int {
t := now()
// If *dest is not a metricdata.Sum, memory reuse is missed. In that case,
// use the zero-value sData and hope for better alignment next cycle.
sData, _ := (*dest).(metricdata.Sum[N])
sData.Temporality = metricdata.CumulativeTemporality
sData.IsMonotonic = s.monotonic
s.Lock()
defer s.Unlock()
n := len(s.values)
dPts := reset(sData.DataPoints, n, n)
var i int
2024-08-26 16:05:54 +00:00
for _, val := range s.values {
dPts[i].Attributes = val.attrs
dPts[i].StartTime = s.start
dPts[i].Time = t
dPts[i].Value = val.n
2024-08-26 16:05:54 +00:00
collectExemplars(&dPts[i].Exemplars, val.res.Collect)
i++
}
2024-08-26 16:05:54 +00:00
// Unused attribute sets do not report.
clear(s.values)
sData.DataPoints = dPts
*dest = sData
return n
}