From 773c26ddd06488376b12ff16f1d940c0ab25d3c5 Mon Sep 17 00:00:00 2001 From: David Ashpole Date: Sat, 21 Sep 2024 17:07:46 +0000 Subject: [PATCH] export exemplar.FixedSizeReservoir --- sdk/metric/exemplar/fixed_size_reservoir.go | 28 ++++++++++--------- .../exemplar/fixed_size_reservoir_test.go | 2 +- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/sdk/metric/exemplar/fixed_size_reservoir.go b/sdk/metric/exemplar/fixed_size_reservoir.go index bc9f5e43ab1..72656928646 100644 --- a/sdk/metric/exemplar/fixed_size_reservoir.go +++ b/sdk/metric/exemplar/fixed_size_reservoir.go @@ -12,15 +12,17 @@ import ( "go.opentelemetry.io/otel/attribute" ) -// NewFixedSizeReservoir returns a [Reservoir] that samples at most k exemplars. If there -// are k or less measurements made, the Reservoir will sample each one. If -// there are more than k, the Reservoir will then randomly sample all -// additional measurement with a decreasing probability. -func NewFixedSizeReservoir(k int) Reservoir { +// NewFixedSizeReservoir returns a [FixedSizeReservoir] that samples at most +// k exemplars. If there are k or less measurements made, the Reservoir will +// sample each one. If there are more than k, the Reservoir will then randomly +// sample all additional measurement with a decreasing probability. +func NewFixedSizeReservoir(k int) *FixedSizeReservoir { return newRandRes(newStorage(k)) } -type randRes struct { +var _ Reservoir = &FixedSizeReservoir{} + +type FixedSizeReservoir struct { *storage // count is the number of measurement seen. @@ -39,8 +41,8 @@ type randRes struct { rng *rand.Rand } -func newRandRes(s *storage) *randRes { - r := &randRes{ +func newRandRes(s *storage) *FixedSizeReservoir { + r := &FixedSizeReservoir{ storage: s, rng: rand.New(rand.NewSource(time.Now().UnixNano())), } @@ -50,7 +52,7 @@ func newRandRes(s *storage) *randRes { // randomFloat64 returns, as a float64, a uniform pseudo-random number in the // open interval (0.0,1.0). -func (r *randRes) randomFloat64() float64 { +func (r *FixedSizeReservoir) randomFloat64() float64 { // TODO: This does not return a uniform number. rng.Float64 returns a // uniformly random int in [0,2^53) that is divided by 2^53. Meaning it // returns multiples of 2^-53, and not all floating point numbers between 0 @@ -75,7 +77,7 @@ func (r *randRes) randomFloat64() float64 { return f } -func (r *randRes) Offer(ctx context.Context, t time.Time, n Value, a []attribute.KeyValue) { +func (r *FixedSizeReservoir) Offer(ctx context.Context, t time.Time, n Value, a []attribute.KeyValue) { // The following algorithm is "Algorithm L" from Li, Kim-Hung (4 December // 1994). "Reservoir-Sampling Algorithms of Time Complexity // O(n(1+log(N/n)))". ACM Transactions on Mathematical Software. 20 (4): @@ -131,7 +133,7 @@ func (r *randRes) Offer(ctx context.Context, t time.Time, n Value, a []attribute } // reset resets r to the initial state. -func (r *randRes) reset() { +func (r *FixedSizeReservoir) reset() { // This resets the number of exemplars known. r.count = 0 // Random index inserts should only happen after the storage is full. @@ -153,7 +155,7 @@ func (r *randRes) reset() { // advance updates the count at which the offered measurement will overwrite an // existing exemplar. -func (r *randRes) advance() { +func (r *FixedSizeReservoir) advance() { // Calculate the next value in the random number series. // // The current value of r.w is based on the max of a distribution of random @@ -180,7 +182,7 @@ func (r *randRes) advance() { r.next += int64(math.Log(r.randomFloat64())/math.Log(1-r.w)) + 1 } -func (r *randRes) Collect(dest *[]Exemplar) { +func (r *FixedSizeReservoir) Collect(dest *[]Exemplar) { r.storage.Collect(dest) // Call reset here even though it will reset r.count and restart the random // number series. This will persist any old exemplars as long as no new diff --git a/sdk/metric/exemplar/fixed_size_reservoir_test.go b/sdk/metric/exemplar/fixed_size_reservoir_test.go index 2d29481774d..1840abbd58d 100644 --- a/sdk/metric/exemplar/fixed_size_reservoir_test.go +++ b/sdk/metric/exemplar/fixed_size_reservoir_test.go @@ -44,7 +44,7 @@ func TestNewFixedSizeReservoirSamplingCorrectness(t *testing.T) { } var sum float64 - for _, m := range r.(*randRes).store { + for _, m := range r.store { sum += m.Value.Float64() } mean := sum / float64(sampleSize)