2024-01-24 08:05:51 -08:00
|
|
|
// Copyright The OpenTelemetry Authors
|
2024-02-29 07:05:28 +01:00
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
2024-01-24 08:05:51 -08:00
|
|
|
|
|
|
|
|
package exemplar
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"testing"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
|
|
|
|
"go.opentelemetry.io/otel/attribute"
|
|
|
|
|
"go.opentelemetry.io/otel/trace"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Sat Jan 01 2000 00:00:00 GMT+0000.
|
|
|
|
|
var staticTime = time.Unix(946684800, 0)
|
|
|
|
|
|
2024-09-09 16:53:15 +10:00
|
|
|
type factory func(requestedCap int) (r Reservoir, actualCap int)
|
2024-01-24 08:05:51 -08:00
|
|
|
|
2024-05-07 08:12:59 -07:00
|
|
|
func ReservoirTest[N int64 | float64](f factory) func(*testing.T) {
|
2024-01-24 08:05:51 -08:00
|
|
|
return func(t *testing.T) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
|
|
t.Run("CaptureSpanContext", func(t *testing.T) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
|
|
r, n := f(1)
|
|
|
|
|
if n < 1 {
|
|
|
|
|
t.Skip("skipping, reservoir capacity less than 1:", n)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tID, sID := trace.TraceID{0x01}, trace.SpanID{0x01}
|
|
|
|
|
sc := trace.NewSpanContext(trace.SpanContextConfig{
|
|
|
|
|
TraceID: tID,
|
|
|
|
|
SpanID: sID,
|
|
|
|
|
TraceFlags: trace.FlagsSampled,
|
|
|
|
|
})
|
|
|
|
|
ctx := trace.ContextWithSpanContext(ctx, sc)
|
|
|
|
|
|
2024-05-07 08:12:59 -07:00
|
|
|
r.Offer(ctx, staticTime, NewValue(N(10)), nil)
|
2024-01-24 08:05:51 -08:00
|
|
|
|
2024-05-07 08:12:59 -07:00
|
|
|
var dest []Exemplar
|
2024-01-24 08:05:51 -08:00
|
|
|
r.Collect(&dest)
|
|
|
|
|
|
2024-05-07 08:12:59 -07:00
|
|
|
want := Exemplar{
|
2024-01-24 08:05:51 -08:00
|
|
|
Time: staticTime,
|
2024-05-07 08:12:59 -07:00
|
|
|
Value: NewValue(N(10)),
|
2024-06-22 00:00:26 +02:00
|
|
|
SpanID: sID[:],
|
|
|
|
|
TraceID: tID[:],
|
2024-01-24 08:05:51 -08:00
|
|
|
}
|
|
|
|
|
require.Len(t, dest, 1, "number of collected exemplars")
|
|
|
|
|
assert.Equal(t, want, dest[0])
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("FilterAttributes", func(t *testing.T) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
|
|
r, n := f(1)
|
|
|
|
|
if n < 1 {
|
|
|
|
|
t.Skip("skipping, reservoir capacity less than 1:", n)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
adminTrue := attribute.Bool("admin", true)
|
2024-05-07 08:12:59 -07:00
|
|
|
r.Offer(ctx, staticTime, NewValue(N(10)), []attribute.KeyValue{adminTrue})
|
2024-01-24 08:05:51 -08:00
|
|
|
|
2024-05-07 08:12:59 -07:00
|
|
|
var dest []Exemplar
|
2024-01-24 08:05:51 -08:00
|
|
|
r.Collect(&dest)
|
|
|
|
|
|
2024-05-07 08:12:59 -07:00
|
|
|
want := Exemplar{
|
2024-01-24 08:05:51 -08:00
|
|
|
FilteredAttributes: []attribute.KeyValue{adminTrue},
|
|
|
|
|
Time: staticTime,
|
2024-05-07 08:12:59 -07:00
|
|
|
Value: NewValue(N(10)),
|
2024-01-24 08:05:51 -08:00
|
|
|
}
|
|
|
|
|
require.Len(t, dest, 1, "number of collected exemplars")
|
|
|
|
|
assert.Equal(t, want, dest[0])
|
|
|
|
|
})
|
|
|
|
|
|
2024-01-29 07:26:30 -08:00
|
|
|
t.Run("CollectLessThanN", func(t *testing.T) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
|
|
r, n := f(2)
|
|
|
|
|
if n < 2 {
|
|
|
|
|
t.Skip("skipping, reservoir capacity less than 2:", n)
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-07 08:12:59 -07:00
|
|
|
r.Offer(ctx, staticTime, NewValue(N(10)), nil)
|
2024-01-29 07:26:30 -08:00
|
|
|
|
2024-05-07 08:12:59 -07:00
|
|
|
var dest []Exemplar
|
2024-01-29 07:26:30 -08:00
|
|
|
r.Collect(&dest)
|
|
|
|
|
// No empty exemplars are exported.
|
|
|
|
|
require.Len(t, dest, 1, "number of collected exemplars")
|
|
|
|
|
})
|
|
|
|
|
|
2024-01-24 08:05:51 -08:00
|
|
|
t.Run("MultipleOffers", func(t *testing.T) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
|
|
r, n := f(3)
|
|
|
|
|
if n < 1 {
|
|
|
|
|
t.Skip("skipping, reservoir capacity less than 1:", n)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for i := 0; i < n+1; i++ {
|
2024-05-07 08:12:59 -07:00
|
|
|
v := NewValue(N(i))
|
2024-01-24 08:05:51 -08:00
|
|
|
r.Offer(ctx, staticTime, v, nil)
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-07 08:12:59 -07:00
|
|
|
var dest []Exemplar
|
2024-01-31 14:07:40 -08:00
|
|
|
r.Collect(&dest)
|
2024-01-24 08:05:51 -08:00
|
|
|
assert.Len(t, dest, n, "multiple offers did not fill reservoir")
|
|
|
|
|
|
2024-02-17 04:36:41 -08:00
|
|
|
// Ensure the collect reset also resets any counting state.
|
2024-01-24 08:05:51 -08:00
|
|
|
for i := 0; i < n+1; i++ {
|
2024-05-07 08:12:59 -07:00
|
|
|
v := NewValue(N(i))
|
2024-01-24 08:05:51 -08:00
|
|
|
r.Offer(ctx, staticTime, v, nil)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dest = dest[:0]
|
2024-01-31 14:07:40 -08:00
|
|
|
r.Collect(&dest)
|
2024-01-24 08:05:51 -08:00
|
|
|
assert.Len(t, dest, n, "internal count state not reset")
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("DropAll", func(t *testing.T) {
|
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
|
|
r, n := f(0)
|
|
|
|
|
if n > 0 {
|
|
|
|
|
t.Skip("skipping, reservoir capacity greater than 0:", n)
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-07 08:12:59 -07:00
|
|
|
r.Offer(context.Background(), staticTime, NewValue(N(10)), nil)
|
2024-01-24 08:05:51 -08:00
|
|
|
|
2024-05-07 08:12:59 -07:00
|
|
|
dest := []Exemplar{{}} // Should be reset to empty.
|
2024-01-24 08:05:51 -08:00
|
|
|
r.Collect(&dest)
|
2024-09-21 17:04:28 +02:00
|
|
|
assert.Empty(t, dest, "no exemplars should be collected")
|
2024-01-24 08:05:51 -08:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|