1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-11-06 09:09:44 +02:00
Files
opentelemetry-go/sdk/metric/exemplar/reservoir_test.go
David Ashpole 481f4983f7 Move exemplar types to non-internal package (#5747)
Part of https://github.com/open-telemetry/opentelemetry-go/issues/5249

This makes all existing types designed to implement the public Exemplar
API public by moving most of `internal/exemplar` to `exemplar`. The only
types that are not being made public are `exemplar.Drop`, and
`exemplar.FilteredReservoir`. Those types are moved to
`internal/aggregate`, and are renamed to `DropReservoir` and
`FilteredExemplarReservoir`.

The following types are made public:

* `exemplar.Exemplar`
* `exemplar.Filter`
* `exemplar.SampledFilter`
* `exemplar.AlwaysOnFilter`
* `exemplar.HistogramReservoir`
* `exemplar.FixedSizeReservoir`
* `exemplar.Reservoir`
* `exemplar.Value`
* `exemplar.ValueType`
2024-09-26 13:25:05 -07:00

143 lines
3.2 KiB
Go

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
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)
type factory func(requestedCap int) (r Reservoir, actualCap int)
func ReservoirTest[N int64 | float64](f factory) func(*testing.T) {
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)
r.Offer(ctx, staticTime, NewValue(N(10)), nil)
var dest []Exemplar
r.Collect(&dest)
want := Exemplar{
Time: staticTime,
Value: NewValue(N(10)),
SpanID: sID[:],
TraceID: tID[:],
}
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)
r.Offer(ctx, staticTime, NewValue(N(10)), []attribute.KeyValue{adminTrue})
var dest []Exemplar
r.Collect(&dest)
want := Exemplar{
FilteredAttributes: []attribute.KeyValue{adminTrue},
Time: staticTime,
Value: NewValue(N(10)),
}
require.Len(t, dest, 1, "number of collected exemplars")
assert.Equal(t, want, dest[0])
})
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)
}
r.Offer(ctx, staticTime, NewValue(N(10)), nil)
var dest []Exemplar
r.Collect(&dest)
// No empty exemplars are exported.
require.Len(t, dest, 1, "number of collected exemplars")
})
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++ {
v := NewValue(N(i))
r.Offer(ctx, staticTime, v, nil)
}
var dest []Exemplar
r.Collect(&dest)
assert.Len(t, dest, n, "multiple offers did not fill reservoir")
// Ensure the collect reset also resets any counting state.
for i := 0; i < n+1; i++ {
v := NewValue(N(i))
r.Offer(ctx, staticTime, v, nil)
}
dest = dest[:0]
r.Collect(&dest)
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)
}
r.Offer(context.Background(), staticTime, NewValue(N(10)), nil)
dest := []Exemplar{{}} // Should be reset to empty.
r.Collect(&dest)
assert.Empty(t, dest, "no exemplars should be collected")
})
}
}