You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2026-06-19 21:45:50 +02:00
fix: handle FixedSizeReservoir size=0 without panic (#8295)
Fixes #8232 - Added guard for size=0 in FixedSizeReservoir - Prevents panic during Offer/update - Added test to ensure no panic occurs --------- Co-authored-by: David Ashpole <dashpole@google.com>
This commit is contained in:
@@ -64,6 +64,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix `FixedSizeReservoir` in `go.opentelemetry.io/otel/sdk/metric/exemplar` to safely handle zero size.
|
||||
A capacity check in the constructor initializes the reservoir safely and skips initialization for zero-cap; early returns in `Offer()` and `Collect()` ensure no-op behavior. (#8295)
|
||||
- Limit OTLP request size to 32 MiB by default in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`.
|
||||
The limit applies before compression, oversized requests are treated as non-retryable errors, and the limit can be configured with the new `WithMaxRequestSize` option. (#8157)
|
||||
- Limit OTLP request size to 32 MiB by default in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`.
|
||||
|
||||
@@ -54,7 +54,9 @@ func newFixedSizeReservoir(s *storage) *FixedSizeReservoir {
|
||||
r := &FixedSizeReservoir{
|
||||
storage: s,
|
||||
}
|
||||
r.reset()
|
||||
if cap(r.measurements) > 0 {
|
||||
r.reset()
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -86,6 +88,10 @@ func (*FixedSizeReservoir) randomFloat64() float64 {
|
||||
// parameters are the value and dropped (filtered) attributes of the
|
||||
// measurement respectively.
|
||||
func (r *FixedSizeReservoir) Offer(ctx context.Context, t time.Time, n Value, a []attribute.KeyValue) {
|
||||
if cap(r.measurements) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// 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):
|
||||
@@ -194,6 +200,10 @@ func (r *FixedSizeReservoir) advance() {
|
||||
//
|
||||
// The Reservoir state is preserved after this call.
|
||||
func (r *FixedSizeReservoir) Collect(dest *[]Exemplar) {
|
||||
if cap(r.measurements) == 0 {
|
||||
*dest = (*dest)[:0]
|
||||
return
|
||||
}
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
r.storage.Collect(dest)
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNewFixedSizeReservoir(t *testing.T) {
|
||||
@@ -22,6 +23,19 @@ func TestNewFixedSizeReservoir(t *testing.T) {
|
||||
}))
|
||||
}
|
||||
|
||||
func TestNewFixedSizeReservoirZeroSize(t *testing.T) {
|
||||
r := NewFixedSizeReservoir(0)
|
||||
require.NotNil(t, r)
|
||||
|
||||
// Offer should be a no-op and not panic.
|
||||
r.Offer(t.Context(), staticTime, NewValue(float64(10)), nil)
|
||||
|
||||
// Collect should leave dest empty.
|
||||
dest := []Exemplar{{}} // pre-filled sentinel
|
||||
r.Collect(&dest)
|
||||
assert.Empty(t, dest)
|
||||
}
|
||||
|
||||
func TestNewFixedSizeReservoirSamplingCorrectness(t *testing.T) {
|
||||
intensity := 0.1
|
||||
sampleSize := 1000
|
||||
|
||||
Reference in New Issue
Block a user