diff --git a/CHANGELOG.md b/CHANGELOG.md index 59a34649849..73ba8d532ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - AWS SDK add `rpc.system` attribute in `go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws`. (#3582, #3617) - Add the new `go.opentelemetry.io/contrib/instrgen` package to provide auto-generated source code instrumentation. (#3068, #3108) +### Fixed + +- Prevent taking from reservoir in AWS XRay Remote Sampler when there is zero capacity in `go.opentelemetry.io/contrib/samplers/aws/xray`. (#3684) + ## [1.16.0-rc.2/0.41.0-rc.2/0.10.0-rc.2] - 2023-03-23 ### Added diff --git a/samplers/aws/xray/internal/reservoir.go b/samplers/aws/xray/internal/reservoir.go index 40d32f3402e..957b1f976c2 100644 --- a/samplers/aws/xray/internal/reservoir.go +++ b/samplers/aws/xray/internal/reservoir.go @@ -59,6 +59,10 @@ func (r *reservoir) take(now time.Time, borrowed bool, itemCost float64) bool { r.mu.Lock() defer r.mu.Unlock() + if r.capacity == 0 { + return false + } + if r.lastTick.IsZero() { r.lastTick = now diff --git a/samplers/aws/xray/internal/reservoir_test.go b/samplers/aws/xray/internal/reservoir_test.go index 72e0f7cd24c..a022d650c77 100644 --- a/samplers/aws/xray/internal/reservoir_test.go +++ b/samplers/aws/xray/internal/reservoir_test.go @@ -161,6 +161,30 @@ func TestConsumeFromReservoir(t *testing.T) { assert.Equal(t, r.quotaBalance, 7.0) } +func TestZeroCapacityFailBorrow(t *testing.T) { + clock := &mockClock{ + nowTime: 1500000000, + } + + r := &reservoir{ + quota: 0, + capacity: 0, + } + + // start with no quota balance + assert.Equal(t, r.quotaBalance, 0.0) + // attempt to borrow from reservoir, and should fail since there is no capacity + assert.False(t, r.take(clock.now(), true, 1.0)) + + // increase the clock by 5 + clock.nowTime = 1500000005 + + // validate there is still no quota balance + assert.Equal(t, r.quotaBalance, 0.0) + // again, attempt to borrow from reservoir, and should fail since there is no capacity + assert.False(t, r.take(clock.now(), true, 1.0)) +} + func TestResetQuotaUsageRotation(t *testing.T) { clock := &mockClock{ nowTime: 1500000000, diff --git a/samplers/aws/xray/internal/rule_test.go b/samplers/aws/xray/internal/rule_test.go index 6bdc726f90b..ad99cc9a166 100644 --- a/samplers/aws/xray/internal/rule_test.go +++ b/samplers/aws/xray/internal/rule_test.go @@ -162,6 +162,7 @@ func TestConsumeFromReservoirSample(t *testing.T) { RuleName: "r1", }, reservoir: &reservoir{ + capacity: 10, quota: 10, expiresAt: time.Unix(1500000060, 0), },