1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-02-05 13:15:41 +02:00

Use LastValue by default for ValueObserver instruments (#1165)

* Use LastValue by default for ValueObserver instruments

* Update test

* Update test with feedback

* Update fix

* Update changelog

* sum->scalar

* Tests pass

* Add a test

* Undo incorrect proto adds

* Restore origin protos

* Restore

* Upstream

* Add more tests

* Precommit

* Typo

* ore test feedback
This commit is contained in:
Joshua MacDonald 2020-09-24 15:30:55 -07:00 committed by GitHub
parent 304d4cdffc
commit 8c3cc43992
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 298 additions and 55 deletions

View File

@ -45,6 +45,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Don't consider unset environment variable for resource detection to be an error. (#1170)
- Rename `go.opentelemetry.io/otel/api/metric.ConfigureInstrument` to `NewInstrumentConfig` and
`go.opentelemetry.io/otel/api/metric.ConfigureMeter` to `NewMeterConfig`.
- ValueObserver instruments use LastValue aggregator by default. (#1165)
- OTLP Metric exporter supports LastValue aggregation. (#1165)
- Move the `go.opentelemetry.io/otel/api/unit` package to `go.opentelemetry.io/otel/unit`. (#1185)
- Rename `Provider` to `MeterProvider` in the `go.opentelemetry.io/otel/api/metric` package. (#1190)
- Rename `NoopProvider` to `NoopMeterProvider` in the `go.opentelemetry.io/otel/api/metric` package. (#1190)

View File

@ -48,7 +48,7 @@ func main() {
// ),
// )
tracerProvider := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter))
pusher := push.New(simple.NewWithExactDistribution(), exporter)
pusher := push.New(simple.NewWithInexpensiveDistribution(), exporter)
pusher.Start()
metricProvider := pusher.MeterProvider()

View File

@ -22,6 +22,7 @@ import (
"fmt"
"strings"
"sync"
"time"
commonpb "go.opentelemetry.io/otel/exporters/otlp/internal/opentelemetry-proto-gen/common/v1"
metricpb "go.opentelemetry.io/otel/exporters/otlp/internal/opentelemetry-proto-gen/metrics/v1"
@ -40,6 +41,11 @@ var (
// aggregator is attempted.
ErrUnimplementedAgg = errors.New("unimplemented aggregator")
// ErrIncompatibleAgg is returned when
// aggregation.Kind implies an interface conversion that has
// failed
ErrIncompatibleAgg = errors.New("incompatible aggregation type")
// ErrUnknownValueType is returned when a transformation of an unknown value
// is attempted.
ErrUnknownValueType = errors.New("invalid value type")
@ -60,6 +66,14 @@ type result struct {
Err error
}
// toNanos returns the number of nanoseconds since the UNIX epoch.
func toNanos(t time.Time) uint64 {
if t.IsZero() {
return 0
}
return uint64(t.UnixNano())
}
// CheckpointSet transforms all records contained in a checkpoint into
// batched OTLP ResourceMetrics.
func CheckpointSet(ctx context.Context, exportSelector export.ExportKindSelector, cps export.CheckpointSet, numWorkers uint) ([]*metricpb.ResourceMetrics, error) {
@ -231,27 +245,50 @@ func sink(ctx context.Context, in <-chan result) ([]*metricpb.ResourceMetrics, e
return rms, nil
}
// Record transforms a Record into an OTLP Metric. An ErrUnimplementedAgg
// Record transforms a Record into an OTLP Metric. An ErrIncompatibleAgg
// error is returned if the Record Aggregator is not supported.
func Record(r export.Record) (*metricpb.Metric, error) {
switch a := r.Aggregation().(type) {
case aggregation.MinMaxSumCount:
return minMaxSumCount(r, a)
case aggregation.Sum:
return sum(r, a)
agg := r.Aggregation()
switch agg.Kind() {
case aggregation.MinMaxSumCountKind:
mmsc, ok := agg.(aggregation.MinMaxSumCount)
if !ok {
return nil, fmt.Errorf("%w: %T", ErrIncompatibleAgg, agg)
}
return minMaxSumCount(r, mmsc)
case aggregation.SumKind:
s, ok := agg.(aggregation.Sum)
if !ok {
return nil, fmt.Errorf("%w: %T", ErrIncompatibleAgg, agg)
}
sum, err := s.Sum()
if err != nil {
return nil, err
}
return scalar(r, sum, r.StartTime(), r.EndTime())
case aggregation.LastValueKind:
lv, ok := agg.(aggregation.LastValue)
if !ok {
return nil, fmt.Errorf("%w: %T", ErrIncompatibleAgg, agg)
}
value, tm, err := lv.LastValue()
if err != nil {
return nil, err
}
return scalar(r, value, time.Time{}, tm)
default:
return nil, fmt.Errorf("%w: %v", ErrUnimplementedAgg, a)
return nil, fmt.Errorf("%w: %T", ErrUnimplementedAgg, agg)
}
}
// sum transforms a Sum Aggregator into an OTLP Metric.
func sum(record export.Record, a aggregation.Sum) (*metricpb.Metric, error) {
// scalar transforms a Sum or LastValue Aggregator into an OTLP Metric.
// For LastValue (Gauge), use start==time.Time{}.
func scalar(record export.Record, num metric.Number, start, end time.Time) (*metricpb.Metric, error) {
desc := record.Descriptor()
labels := record.Labels()
sum, err := a.Sum()
if err != nil {
return nil, err
}
m := &metricpb.Metric{
MetricDescriptor: &metricpb.MetricDescriptor{
@ -266,20 +303,20 @@ func sum(record export.Record, a aggregation.Sum) (*metricpb.Metric, error) {
m.MetricDescriptor.Type = metricpb.MetricDescriptor_INT64
m.Int64DataPoints = []*metricpb.Int64DataPoint{
{
Value: sum.CoerceToInt64(n),
Value: num.CoerceToInt64(n),
Labels: stringKeyValues(labels.Iter()),
StartTimeUnixNano: uint64(record.StartTime().UnixNano()),
TimeUnixNano: uint64(record.EndTime().UnixNano()),
StartTimeUnixNano: toNanos(start),
TimeUnixNano: toNanos(end),
},
}
case metric.Float64NumberKind:
m.MetricDescriptor.Type = metricpb.MetricDescriptor_DOUBLE
m.DoubleDataPoints = []*metricpb.DoubleDataPoint{
{
Value: sum.CoerceToFloat64(n),
Value: num.CoerceToFloat64(n),
Labels: stringKeyValues(labels.Iter()),
StartTimeUnixNano: uint64(record.StartTime().UnixNano()),
TimeUnixNano: uint64(record.EndTime().UnixNano()),
StartTimeUnixNano: toNanos(start),
TimeUnixNano: toNanos(end),
},
}
default:
@ -339,8 +376,8 @@ func minMaxSumCount(record export.Record, a aggregation.MinMaxSumCount) (*metric
Value: max.CoerceToFloat64(numKind),
},
},
StartTimeUnixNano: uint64(record.StartTime().UnixNano()),
TimeUnixNano: uint64(record.EndTime().UnixNano()),
StartTimeUnixNano: toNanos(record.StartTime()),
TimeUnixNano: toNanos(record.EndTime()),
},
},
}, nil

View File

@ -17,6 +17,7 @@ package transform
import (
"context"
"errors"
"fmt"
"testing"
"time"
@ -31,8 +32,13 @@ import (
export "go.opentelemetry.io/otel/sdk/export/metric"
"go.opentelemetry.io/otel/sdk/export/metric/aggregation"
"go.opentelemetry.io/otel/sdk/export/metric/metrictest"
"go.opentelemetry.io/otel/sdk/metric/aggregator/array"
"go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue"
lvAgg "go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue"
"go.opentelemetry.io/otel/sdk/metric/aggregator/minmaxsumcount"
"go.opentelemetry.io/otel/sdk/metric/aggregator/sum"
sumAgg "go.opentelemetry.io/otel/sdk/metric/aggregator/sum"
"go.opentelemetry.io/otel/sdk/resource"
"go.opentelemetry.io/otel/unit"
)
@ -242,7 +248,7 @@ func TestSumMetricDescriptor(t *testing.T) {
},
{
"sum-test-b",
metric.ValueRecorderKind, // This shouldn't change anything.
metric.ValueObserverKind, // This shouldn't change anything.
"test-b-description",
unit.Milliseconds,
metric.Float64NumberKind,
@ -264,7 +270,7 @@ func TestSumMetricDescriptor(t *testing.T) {
labels := label.NewSet(test.labels...)
emptyAgg := &sumAgg.New(1)[0]
record := export.NewRecord(&desc, &labels, nil, emptyAgg, intervalStart, intervalEnd)
got, err := sum(record, emptyAgg)
got, err := scalar(record, 0, time.Time{}, time.Time{})
if assert.NoError(t, err) {
assert.Equal(t, test.expected, got.MetricDescriptor)
}
@ -278,7 +284,12 @@ func TestSumInt64DataPoints(t *testing.T) {
assert.NoError(t, s.Update(context.Background(), metric.Number(1), &desc))
require.NoError(t, s.SynchronizedMove(ckpt, &desc))
record := export.NewRecord(&desc, &labels, nil, ckpt.Aggregation(), intervalStart, intervalEnd)
if m, err := sum(record, ckpt.(aggregation.Sum)); assert.NoError(t, err) {
sum, ok := ckpt.(aggregation.Sum)
require.True(t, ok, "ckpt is not an aggregation.Sum: %T", ckpt)
value, err := sum.Sum()
require.NoError(t, err)
if m, err := scalar(record, value, record.StartTime(), record.EndTime()); assert.NoError(t, err) {
assert.Equal(t, []*metricpb.Int64DataPoint{{
Value: 1,
StartTimeUnixNano: uint64(intervalStart.UnixNano()),
@ -297,7 +308,12 @@ func TestSumFloat64DataPoints(t *testing.T) {
assert.NoError(t, s.Update(context.Background(), metric.NewFloat64Number(1), &desc))
require.NoError(t, s.SynchronizedMove(ckpt, &desc))
record := export.NewRecord(&desc, &labels, nil, ckpt.Aggregation(), intervalStart, intervalEnd)
if m, err := sum(record, ckpt.(aggregation.Sum)); assert.NoError(t, err) {
sum, ok := ckpt.(aggregation.Sum)
require.True(t, ok, "ckpt is not an aggregation.Sum: %T", ckpt)
value, err := sum.Sum()
require.NoError(t, err)
if m, err := scalar(record, value, record.StartTime(), record.EndTime()); assert.NoError(t, err) {
assert.Equal(t, []*metricpb.Int64DataPoint(nil), m.Int64DataPoints)
assert.Equal(t, []*metricpb.DoubleDataPoint{{
Value: 1,
@ -309,14 +325,176 @@ func TestSumFloat64DataPoints(t *testing.T) {
}
}
func TestLastValueInt64DataPoints(t *testing.T) {
desc := metric.NewDescriptor("", metric.ValueRecorderKind, metric.Int64NumberKind)
labels := label.NewSet()
s, ckpt := metrictest.Unslice2(lvAgg.New(2))
assert.NoError(t, s.Update(context.Background(), metric.Number(100), &desc))
require.NoError(t, s.SynchronizedMove(ckpt, &desc))
record := export.NewRecord(&desc, &labels, nil, ckpt.Aggregation(), intervalStart, intervalEnd)
sum, ok := ckpt.(aggregation.LastValue)
require.True(t, ok, "ckpt is not an aggregation.LastValue: %T", ckpt)
value, timestamp, err := sum.LastValue()
require.NoError(t, err)
if m, err := scalar(record, value, time.Time{}, timestamp); assert.NoError(t, err) {
assert.Equal(t, []*metricpb.Int64DataPoint{{
Value: 100,
StartTimeUnixNano: 0,
TimeUnixNano: uint64(timestamp.UnixNano()),
}}, m.Int64DataPoints)
assert.Equal(t, []*metricpb.DoubleDataPoint(nil), m.DoubleDataPoints)
assert.Equal(t, []*metricpb.HistogramDataPoint(nil), m.HistogramDataPoints)
assert.Equal(t, []*metricpb.SummaryDataPoint(nil), m.SummaryDataPoints)
}
}
func TestSumErrUnknownValueType(t *testing.T) {
desc := metric.NewDescriptor("", metric.ValueRecorderKind, metric.NumberKind(-1))
labels := label.NewSet()
s := &sumAgg.New(1)[0]
record := export.NewRecord(&desc, &labels, nil, s, intervalStart, intervalEnd)
_, err := sum(record, s)
value, err := s.Sum()
require.NoError(t, err)
_, err = scalar(record, value, record.StartTime(), record.EndTime())
assert.Error(t, err)
if !errors.Is(err, ErrUnknownValueType) {
t.Errorf("expected ErrUnknownValueType, got %v", err)
}
}
type testAgg struct {
kind aggregation.Kind
agg aggregation.Aggregation
}
func (t *testAgg) Kind() aggregation.Kind {
return t.kind
}
func (t *testAgg) Aggregation() aggregation.Aggregation {
return t.agg
}
// None of these three are used:
func (t *testAgg) Update(ctx context.Context, number metric.Number, descriptor *metric.Descriptor) error {
return nil
}
func (t *testAgg) SynchronizedMove(destination export.Aggregator, descriptor *metric.Descriptor) error {
return nil
}
func (t *testAgg) Merge(aggregator export.Aggregator, descriptor *metric.Descriptor) error {
return nil
}
type testErrSum struct {
err error
}
type testErrLastValue struct {
err error
}
type testErrMinMaxSumCount struct {
testErrSum
}
func (te *testErrLastValue) LastValue() (metric.Number, time.Time, error) {
return 0, time.Time{}, te.err
}
func (te *testErrLastValue) Kind() aggregation.Kind {
return aggregation.LastValueKind
}
func (te *testErrSum) Sum() (metric.Number, error) {
return 0, te.err
}
func (te *testErrSum) Kind() aggregation.Kind {
return aggregation.SumKind
}
func (te *testErrMinMaxSumCount) Min() (metric.Number, error) {
return 0, te.err
}
func (te *testErrMinMaxSumCount) Max() (metric.Number, error) {
return 0, te.err
}
func (te *testErrMinMaxSumCount) Count() (int64, error) {
return 0, te.err
}
var _ export.Aggregator = &testAgg{}
var _ aggregation.Aggregation = &testAgg{}
var _ aggregation.Sum = &testErrSum{}
var _ aggregation.LastValue = &testErrLastValue{}
var _ aggregation.MinMaxSumCount = &testErrMinMaxSumCount{}
func TestRecordAggregatorIncompatibleErrors(t *testing.T) {
makeMpb := func(kind aggregation.Kind, agg aggregation.Aggregation) (*metricpb.Metric, error) {
desc := metric.NewDescriptor("things", metric.CounterKind, metric.Int64NumberKind)
labels := label.NewSet()
res := resource.New()
test := &testAgg{
kind: kind,
agg: agg,
}
return Record(export.NewRecord(&desc, &labels, res, test, intervalStart, intervalEnd))
}
mpb, err := makeMpb(aggregation.SumKind, &lastvalue.New(1)[0])
require.Error(t, err)
require.Nil(t, mpb)
require.True(t, errors.Is(err, ErrIncompatibleAgg))
mpb, err = makeMpb(aggregation.LastValueKind, &sum.New(1)[0])
require.Error(t, err)
require.Nil(t, mpb)
require.True(t, errors.Is(err, ErrIncompatibleAgg))
mpb, err = makeMpb(aggregation.MinMaxSumCountKind, &lastvalue.New(1)[0])
require.Error(t, err)
require.Nil(t, mpb)
require.True(t, errors.Is(err, ErrIncompatibleAgg))
mpb, err = makeMpb(aggregation.ExactKind, &array.New(1)[0])
require.Error(t, err)
require.Nil(t, mpb)
require.True(t, errors.Is(err, ErrUnimplementedAgg))
}
func TestRecordAggregatorUnexpectedErrors(t *testing.T) {
makeMpb := func(kind aggregation.Kind, agg aggregation.Aggregation) (*metricpb.Metric, error) {
desc := metric.NewDescriptor("things", metric.CounterKind, metric.Int64NumberKind)
labels := label.NewSet()
res := resource.New()
return Record(export.NewRecord(&desc, &labels, res, agg, intervalStart, intervalEnd))
}
errEx := fmt.Errorf("timeout")
mpb, err := makeMpb(aggregation.SumKind, &testErrSum{errEx})
require.Error(t, err)
require.Nil(t, mpb)
require.True(t, errors.Is(err, errEx))
mpb, err = makeMpb(aggregation.LastValueKind, &testErrLastValue{errEx})
require.Error(t, err)
require.Nil(t, mpb)
require.True(t, errors.Is(err, errEx))
mpb, err = makeMpb(aggregation.MinMaxSumCountKind, &testErrMinMaxSumCount{testErrSum{errEx}})
require.Error(t, err)
require.Nil(t, mpb)
require.True(t, errors.Is(err, errEx))
}

View File

@ -121,7 +121,7 @@ func newExporterEndToEndTest(t *testing.T, additionalOpts []otlp.ExporterOption)
span.End()
}
selector := simple.NewWithExactDistribution()
selector := simple.NewWithInexpensiveDistribution()
processor := processor.New(selector, metricsdk.PassThroughExporter)
pusher := push.New(processor, exp)
pusher.Start()
@ -144,6 +144,7 @@ func newExporterEndToEndTest(t *testing.T, additionalOpts []otlp.ExporterOption)
"test-float64-valueobserver": {metric.ValueObserverKind, metricapi.Float64NumberKind, 3},
}
for name, data := range instruments {
data := data
switch data.iKind {
case metric.CounterKind:
switch data.nKind {
@ -166,10 +167,11 @@ func newExporterEndToEndTest(t *testing.T, additionalOpts []otlp.ExporterOption)
case metric.ValueObserverKind:
switch data.nKind {
case metricapi.Int64NumberKind:
callback := func(v int64) metricapi.Int64ObserverFunc {
return metricapi.Int64ObserverFunc(func(_ context.Context, result metricapi.Int64ObserverResult) { result.Observe(v, labels...) })
}(data.val)
metricapi.Must(meter).NewInt64ValueObserver(name, callback)
metricapi.Must(meter).NewInt64ValueObserver(name,
func(_ context.Context, result metricapi.Int64ObserverResult) {
result.Observe(data.val, labels...)
},
)
case metricapi.Float64NumberKind:
callback := func(v float64) metricapi.Float64ObserverFunc {
return metricapi.Float64ObserverFunc(func(_ context.Context, result metricapi.Float64ObserverResult) { result.Observe(v, labels...) })
@ -245,7 +247,7 @@ func newExporterEndToEndTest(t *testing.T, additionalOpts []otlp.ExporterOption)
seen[desc.Name] = struct{}{}
switch data.iKind {
case metric.CounterKind:
case metric.CounterKind, metric.ValueObserverKind:
switch data.nKind {
case metricapi.Int64NumberKind:
assert.Equal(t, metricpb.MetricDescriptor_INT64.String(), desc.GetType().String())
@ -260,7 +262,7 @@ func newExporterEndToEndTest(t *testing.T, additionalOpts []otlp.ExporterOption)
default:
assert.Failf(t, "invalid number kind", data.nKind.String())
}
case metric.ValueRecorderKind, metric.ValueObserverKind:
case metric.ValueRecorderKind:
assert.Equal(t, metricpb.MetricDescriptor_SUMMARY.String(), desc.GetType().String())
m.GetSummaryDataPoints()
if dp := m.GetSummaryDataPoints(); assert.Len(t, dp, 1) {
@ -486,7 +488,7 @@ func TestNewExporter_withMultipleAttributeTypes(t *testing.T) {
span.SetAttributes(testKvs...)
span.End()
selector := simple.NewWithExactDistribution()
selector := simple.NewWithInexpensiveDistribution()
processor := processor.New(selector, metricsdk.PassThroughExporter)
pusher := push.New(processor, exp)
pusher.Start()

View File

@ -20,6 +20,7 @@ import (
"go.opentelemetry.io/otel/sdk/metric/aggregator/array"
"go.opentelemetry.io/otel/sdk/metric/aggregator/ddsketch"
"go.opentelemetry.io/otel/sdk/metric/aggregator/histogram"
"go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue"
"go.opentelemetry.io/otel/sdk/metric/aggregator/minmaxsumcount"
"go.opentelemetry.io/otel/sdk/metric/aggregator/sum"
)
@ -86,9 +87,18 @@ func sumAggs(aggPtrs []*export.Aggregator) {
}
}
func lastValueAggs(aggPtrs []*export.Aggregator) {
aggs := lastvalue.New(len(aggPtrs))
for i := range aggPtrs {
*aggPtrs[i] = &aggs[i]
}
}
func (selectorInexpensive) AggregatorFor(descriptor *metric.Descriptor, aggPtrs ...*export.Aggregator) {
switch descriptor.MetricKind() {
case metric.ValueObserverKind, metric.ValueRecorderKind:
case metric.ValueObserverKind:
lastValueAggs(aggPtrs)
case metric.ValueRecorderKind:
aggs := minmaxsumcount.New(len(aggPtrs), descriptor)
for i := range aggPtrs {
*aggPtrs[i] = &aggs[i]
@ -100,7 +110,9 @@ func (selectorInexpensive) AggregatorFor(descriptor *metric.Descriptor, aggPtrs
func (s selectorSketch) AggregatorFor(descriptor *metric.Descriptor, aggPtrs ...*export.Aggregator) {
switch descriptor.MetricKind() {
case metric.ValueObserverKind, metric.ValueRecorderKind:
case metric.ValueObserverKind:
lastValueAggs(aggPtrs)
case metric.ValueRecorderKind:
aggs := ddsketch.New(len(aggPtrs), descriptor, s.config)
for i := range aggPtrs {
*aggPtrs[i] = &aggs[i]
@ -112,7 +124,9 @@ func (s selectorSketch) AggregatorFor(descriptor *metric.Descriptor, aggPtrs ...
func (selectorExact) AggregatorFor(descriptor *metric.Descriptor, aggPtrs ...*export.Aggregator) {
switch descriptor.MetricKind() {
case metric.ValueObserverKind, metric.ValueRecorderKind:
case metric.ValueObserverKind:
lastValueAggs(aggPtrs)
case metric.ValueRecorderKind:
aggs := array.New(len(aggPtrs))
for i := range aggPtrs {
*aggPtrs[i] = &aggs[i]
@ -124,7 +138,9 @@ func (selectorExact) AggregatorFor(descriptor *metric.Descriptor, aggPtrs ...*ex
func (s selectorHistogram) AggregatorFor(descriptor *metric.Descriptor, aggPtrs ...*export.Aggregator) {
switch descriptor.MetricKind() {
case metric.ValueObserverKind, metric.ValueRecorderKind:
case metric.ValueObserverKind:
lastValueAggs(aggPtrs)
case metric.ValueRecorderKind:
aggs := histogram.New(len(aggPtrs), descriptor, s.boundaries)
for i := range aggPtrs {
*aggPtrs[i] = &aggs[i]

View File

@ -24,15 +24,19 @@ import (
"go.opentelemetry.io/otel/sdk/metric/aggregator/array"
"go.opentelemetry.io/otel/sdk/metric/aggregator/ddsketch"
"go.opentelemetry.io/otel/sdk/metric/aggregator/histogram"
"go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue"
"go.opentelemetry.io/otel/sdk/metric/aggregator/minmaxsumcount"
"go.opentelemetry.io/otel/sdk/metric/aggregator/sum"
"go.opentelemetry.io/otel/sdk/metric/selector/simple"
)
var (
testCounterDesc = metric.NewDescriptor("counter", metric.CounterKind, metric.Int64NumberKind)
testValueRecorderDesc = metric.NewDescriptor("valuerecorder", metric.ValueRecorderKind, metric.Int64NumberKind)
testValueObserverDesc = metric.NewDescriptor("valueobserver", metric.ValueObserverKind, metric.Int64NumberKind)
testCounterDesc = metric.NewDescriptor("counter", metric.CounterKind, metric.Int64NumberKind)
testUpDownCounterDesc = metric.NewDescriptor("updowncounter", metric.UpDownCounterKind, metric.Int64NumberKind)
testSumObserverDesc = metric.NewDescriptor("sumobserver", metric.SumObserverKind, metric.Int64NumberKind)
testUpDownSumObserverDesc = metric.NewDescriptor("updownsumobserver", metric.UpDownSumObserverKind, metric.Int64NumberKind)
testValueRecorderDesc = metric.NewDescriptor("valuerecorder", metric.ValueRecorderKind, metric.Int64NumberKind)
testValueObserverDesc = metric.NewDescriptor("valueobserver", metric.ValueObserverKind, metric.Int64NumberKind)
)
func oneAgg(sel export.AggregatorSelector, desc *metric.Descriptor) export.Aggregator {
@ -41,30 +45,34 @@ func oneAgg(sel export.AggregatorSelector, desc *metric.Descriptor) export.Aggre
return agg
}
func testFixedSelectors(t *testing.T, sel export.AggregatorSelector) {
require.IsType(t, (*lastvalue.Aggregator)(nil), oneAgg(sel, &testValueObserverDesc))
require.IsType(t, (*sum.Aggregator)(nil), oneAgg(sel, &testCounterDesc))
require.IsType(t, (*sum.Aggregator)(nil), oneAgg(sel, &testUpDownCounterDesc))
require.IsType(t, (*sum.Aggregator)(nil), oneAgg(sel, &testSumObserverDesc))
require.IsType(t, (*sum.Aggregator)(nil), oneAgg(sel, &testUpDownSumObserverDesc))
}
func TestInexpensiveDistribution(t *testing.T) {
inex := simple.NewWithInexpensiveDistribution()
require.NotPanics(t, func() { _ = oneAgg(inex, &testCounterDesc).(*sum.Aggregator) })
require.NotPanics(t, func() { _ = oneAgg(inex, &testValueRecorderDesc).(*minmaxsumcount.Aggregator) })
require.NotPanics(t, func() { _ = oneAgg(inex, &testValueObserverDesc).(*minmaxsumcount.Aggregator) })
require.IsType(t, (*minmaxsumcount.Aggregator)(nil), oneAgg(inex, &testValueRecorderDesc))
testFixedSelectors(t, inex)
}
func TestSketchDistribution(t *testing.T) {
sk := simple.NewWithSketchDistribution(ddsketch.NewDefaultConfig())
require.NotPanics(t, func() { _ = oneAgg(sk, &testCounterDesc).(*sum.Aggregator) })
require.NotPanics(t, func() { _ = oneAgg(sk, &testValueRecorderDesc).(*ddsketch.Aggregator) })
require.NotPanics(t, func() { _ = oneAgg(sk, &testValueObserverDesc).(*ddsketch.Aggregator) })
require.IsType(t, (*ddsketch.Aggregator)(nil), oneAgg(sk, &testValueRecorderDesc))
testFixedSelectors(t, sk)
}
func TestExactDistribution(t *testing.T) {
ex := simple.NewWithExactDistribution()
require.NotPanics(t, func() { _ = oneAgg(ex, &testCounterDesc).(*sum.Aggregator) })
require.NotPanics(t, func() { _ = oneAgg(ex, &testValueRecorderDesc).(*array.Aggregator) })
require.NotPanics(t, func() { _ = oneAgg(ex, &testValueObserverDesc).(*array.Aggregator) })
require.IsType(t, (*array.Aggregator)(nil), oneAgg(ex, &testValueRecorderDesc))
testFixedSelectors(t, ex)
}
func TestHistogramDistribution(t *testing.T) {
ex := simple.NewWithHistogramDistribution(nil)
require.NotPanics(t, func() { _ = oneAgg(ex, &testCounterDesc).(*sum.Aggregator) })
require.NotPanics(t, func() { _ = oneAgg(ex, &testValueRecorderDesc).(*histogram.Aggregator) })
require.NotPanics(t, func() { _ = oneAgg(ex, &testValueObserverDesc).(*histogram.Aggregator) })
hist := simple.NewWithHistogramDistribution(nil)
require.IsType(t, (*histogram.Aggregator)(nil), oneAgg(hist, &testValueRecorderDesc))
testFixedSelectors(t, hist)
}