You've already forked opentelemetry-go
							
							
				mirror of
				https://github.com/open-telemetry/opentelemetry-go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	Remove several metrics test helpers (#2105)
* Remove several metrics test helpers * Lint * Changelog * Lint
This commit is contained in:
		| @@ -23,6 +23,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm | ||||
|  | ||||
| - Removed the deprecated package `go.opentelemetry.io/otel/exporters/trace/jaeger`. (#2020) | ||||
| - Removed the deprecated package `go.opentelemetry.io/otel/exporters/trace/zipkin`. (#2020) | ||||
| - Removed metrics test package `go.opentelemetry.io/otel/sdk/export/metric/metrictest`. (#2105) | ||||
|  | ||||
| ### Fixed | ||||
|  | ||||
|   | ||||
| @@ -22,7 +22,6 @@ import ( | ||||
|  | ||||
| 	"go.opentelemetry.io/otel/exporters/otlp/otlpmetric" | ||||
| 	"go.opentelemetry.io/otel/sdk/export/metric/aggregation" | ||||
| 	"go.opentelemetry.io/otel/sdk/export/metric/metrictest" | ||||
| 	"go.opentelemetry.io/otel/sdk/metric/aggregator/histogram" | ||||
| 	"go.opentelemetry.io/otel/sdk/metric/aggregator/sum" | ||||
|  | ||||
| @@ -764,9 +763,11 @@ func runMetricExportTests(t *testing.T, opts []otlpmetric.Option, rs []record, e | ||||
|  | ||||
| 		var agg, ckpt metricsdk.Aggregator | ||||
| 		if r.iKind.Adding() { | ||||
| 			agg, ckpt = metrictest.Unslice2(sum.New(2)) | ||||
| 			sums := sum.New(2) | ||||
| 			agg, ckpt = &sums[0], &sums[1] | ||||
| 		} else { | ||||
| 			agg, ckpt = metrictest.Unslice2(histogram.New(2, &desc, histogram.WithExplicitBoundaries(testHistogramBoundaries))) | ||||
| 			histos := histogram.New(2, &desc, histogram.WithExplicitBoundaries(testHistogramBoundaries)) | ||||
| 			agg, ckpt = &histos[0], &histos[1] | ||||
| 		} | ||||
|  | ||||
| 		ctx := context.Background() | ||||
|   | ||||
| @@ -29,7 +29,6 @@ import ( | ||||
| 	"go.opentelemetry.io/otel/metric/number" | ||||
| 	export "go.opentelemetry.io/otel/sdk/export/metric" | ||||
| 	"go.opentelemetry.io/otel/sdk/export/metric/aggregation" | ||||
| 	"go.opentelemetry.io/otel/sdk/export/metric/metrictest" | ||||
| 	arrAgg "go.opentelemetry.io/otel/sdk/metric/aggregator/exact" | ||||
| 	"go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue" | ||||
| 	lvAgg "go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue" | ||||
| @@ -101,18 +100,19 @@ func TestStringKeyValues(t *testing.T) { | ||||
| } | ||||
|  | ||||
| func TestMinMaxSumCountValue(t *testing.T) { | ||||
| 	mmsc, ckpt := metrictest.Unslice2(minmaxsumcount.New(2, &metric.Descriptor{})) | ||||
| 	mmscs := minmaxsumcount.New(2, &metric.Descriptor{}) | ||||
| 	mmsc, ckpt := &mmscs[0], &mmscs[1] | ||||
|  | ||||
| 	assert.NoError(t, mmsc.Update(context.Background(), 1, &metric.Descriptor{})) | ||||
| 	assert.NoError(t, mmsc.Update(context.Background(), 10, &metric.Descriptor{})) | ||||
|  | ||||
| 	// Prior to checkpointing ErrNoData should be returned. | ||||
| 	_, _, _, _, err := minMaxSumCountValues(ckpt.(aggregation.MinMaxSumCount)) | ||||
| 	_, _, _, _, err := minMaxSumCountValues(ckpt) | ||||
| 	assert.EqualError(t, err, aggregation.ErrNoData.Error()) | ||||
|  | ||||
| 	// Checkpoint to set non-zero values | ||||
| 	require.NoError(t, mmsc.SynchronizedMove(ckpt, &metric.Descriptor{})) | ||||
| 	min, max, sum, count, err := minMaxSumCountValues(ckpt.(aggregation.MinMaxSumCount)) | ||||
| 	min, max, sum, count, err := minMaxSumCountValues(ckpt) | ||||
| 	if assert.NoError(t, err) { | ||||
| 		assert.Equal(t, min, number.NewInt64Number(1)) | ||||
| 		assert.Equal(t, max, number.NewInt64Number(10)) | ||||
| @@ -124,7 +124,8 @@ func TestMinMaxSumCountValue(t *testing.T) { | ||||
| func TestMinMaxSumCountDatapoints(t *testing.T) { | ||||
| 	desc := metric.NewDescriptor("", metric.ValueRecorderInstrumentKind, number.Int64Kind) | ||||
| 	labels := attribute.NewSet(attribute.String("one", "1")) | ||||
| 	mmsc, ckpt := metrictest.Unslice2(minmaxsumcount.New(2, &desc)) | ||||
| 	mmscs := minmaxsumcount.New(2, &metric.Descriptor{}) | ||||
| 	mmsc, ckpt := &mmscs[0], &mmscs[1] | ||||
|  | ||||
| 	assert.NoError(t, mmsc.Update(context.Background(), 1, &desc)) | ||||
| 	assert.NoError(t, mmsc.Update(context.Background(), 10, &desc)) | ||||
| @@ -154,7 +155,7 @@ func TestMinMaxSumCountDatapoints(t *testing.T) { | ||||
| 		}, | ||||
| 	} | ||||
| 	record := export.NewRecord(&desc, &labels, nil, ckpt.Aggregation(), intervalStart, intervalEnd) | ||||
| 	m, err := minMaxSumCount(record, ckpt.(aggregation.MinMaxSumCount)) | ||||
| 	m, err := minMaxSumCount(record, ckpt) | ||||
| 	if assert.NoError(t, err) { | ||||
| 		assert.Nil(t, m.GetGauge()) | ||||
| 		assert.Nil(t, m.GetSum()) | ||||
| @@ -179,13 +180,14 @@ func TestMinMaxSumCountPropagatesErrors(t *testing.T) { | ||||
| func TestSumIntDataPoints(t *testing.T) { | ||||
| 	desc := metric.NewDescriptor("", metric.ValueRecorderInstrumentKind, number.Int64Kind) | ||||
| 	labels := attribute.NewSet(attribute.String("one", "1")) | ||||
| 	s, ckpt := metrictest.Unslice2(sumAgg.New(2)) | ||||
| 	sums := sumAgg.New(2) | ||||
| 	s, ckpt := &sums[0], &sums[1] | ||||
|  | ||||
| 	assert.NoError(t, s.Update(context.Background(), number.Number(1), &desc)) | ||||
| 	require.NoError(t, s.SynchronizedMove(ckpt, &desc)) | ||||
| 	record := export.NewRecord(&desc, &labels, nil, ckpt.Aggregation(), intervalStart, intervalEnd) | ||||
| 	sum, ok := ckpt.(aggregation.Sum) | ||||
| 	require.True(t, ok, "ckpt is not an aggregation.Sum: %T", ckpt) | ||||
| 	value, err := sum.Sum() | ||||
|  | ||||
| 	value, err := ckpt.Sum() | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| 	if m, err := sumPoint(record, value, record.StartTime(), record.EndTime(), export.CumulativeExportKind, true); assert.NoError(t, err) { | ||||
| @@ -218,13 +220,13 @@ func TestSumIntDataPoints(t *testing.T) { | ||||
| func TestSumFloatDataPoints(t *testing.T) { | ||||
| 	desc := metric.NewDescriptor("", metric.ValueRecorderInstrumentKind, number.Float64Kind) | ||||
| 	labels := attribute.NewSet(attribute.String("one", "1")) | ||||
| 	s, ckpt := metrictest.Unslice2(sumAgg.New(2)) | ||||
| 	sums := sumAgg.New(2) | ||||
| 	s, ckpt := &sums[0], &sums[1] | ||||
|  | ||||
| 	assert.NoError(t, s.Update(context.Background(), number.NewFloat64Number(1), &desc)) | ||||
| 	require.NoError(t, s.SynchronizedMove(ckpt, &desc)) | ||||
| 	record := export.NewRecord(&desc, &labels, nil, ckpt.Aggregation(), intervalStart, intervalEnd) | ||||
| 	sum, ok := ckpt.(aggregation.Sum) | ||||
| 	require.True(t, ok, "ckpt is not an aggregation.Sum: %T", ckpt) | ||||
| 	value, err := sum.Sum() | ||||
| 	value, err := ckpt.Sum() | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| 	if m, err := sumPoint(record, value, record.StartTime(), record.EndTime(), export.DeltaExportKind, false); assert.NoError(t, err) { | ||||
| @@ -256,13 +258,13 @@ func TestSumFloatDataPoints(t *testing.T) { | ||||
| func TestLastValueIntDataPoints(t *testing.T) { | ||||
| 	desc := metric.NewDescriptor("", metric.ValueRecorderInstrumentKind, number.Int64Kind) | ||||
| 	labels := attribute.NewSet(attribute.String("one", "1")) | ||||
| 	s, ckpt := metrictest.Unslice2(lvAgg.New(2)) | ||||
| 	assert.NoError(t, s.Update(context.Background(), number.Number(100), &desc)) | ||||
| 	require.NoError(t, s.SynchronizedMove(ckpt, &desc)) | ||||
| 	lvs := lvAgg.New(2) | ||||
| 	lv, ckpt := &lvs[0], &lvs[1] | ||||
|  | ||||
| 	assert.NoError(t, lv.Update(context.Background(), number.Number(100), &desc)) | ||||
| 	require.NoError(t, lv.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() | ||||
| 	value, timestamp, err := ckpt.LastValue() | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| 	if m, err := gaugePoint(record, value, time.Time{}, timestamp); assert.NoError(t, err) { | ||||
| @@ -291,13 +293,13 @@ func TestLastValueIntDataPoints(t *testing.T) { | ||||
| func TestExactIntDataPoints(t *testing.T) { | ||||
| 	desc := metric.NewDescriptor("", metric.ValueRecorderInstrumentKind, number.Int64Kind) | ||||
| 	labels := attribute.NewSet(attribute.String("one", "1")) | ||||
| 	e, ckpt := metrictest.Unslice2(arrAgg.New(2)) | ||||
| 	arrs := arrAgg.New(2) | ||||
| 	e, ckpt := &arrs[0], &arrs[1] | ||||
|  | ||||
| 	assert.NoError(t, e.Update(context.Background(), number.Number(100), &desc)) | ||||
| 	require.NoError(t, e.SynchronizedMove(ckpt, &desc)) | ||||
| 	record := export.NewRecord(&desc, &labels, nil, ckpt.Aggregation(), intervalStart, intervalEnd) | ||||
| 	p, ok := ckpt.(aggregation.Points) | ||||
| 	require.True(t, ok, "ckpt is not an aggregation.Points: %T", ckpt) | ||||
| 	pts, err := p.Points() | ||||
| 	pts, err := ckpt.Points() | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| 	if m, err := gaugeArray(record, pts); assert.NoError(t, err) { | ||||
| @@ -326,13 +328,12 @@ func TestExactIntDataPoints(t *testing.T) { | ||||
| func TestExactFloatDataPoints(t *testing.T) { | ||||
| 	desc := metric.NewDescriptor("", metric.ValueRecorderInstrumentKind, number.Float64Kind) | ||||
| 	labels := attribute.NewSet(attribute.String("one", "1")) | ||||
| 	e, ckpt := metrictest.Unslice2(arrAgg.New(2)) | ||||
| 	arrs := arrAgg.New(2) | ||||
| 	e, ckpt := &arrs[0], &arrs[1] | ||||
| 	assert.NoError(t, e.Update(context.Background(), number.NewFloat64Number(100), &desc)) | ||||
| 	require.NoError(t, e.SynchronizedMove(ckpt, &desc)) | ||||
| 	record := export.NewRecord(&desc, &labels, nil, ckpt.Aggregation(), intervalStart, intervalEnd) | ||||
| 	p, ok := ckpt.(aggregation.Points) | ||||
| 	require.True(t, ok, "ckpt is not an aggregation.Points: %T", ckpt) | ||||
| 	pts, err := p.Points() | ||||
| 	pts, err := ckpt.Points() | ||||
| 	require.NoError(t, err) | ||||
|  | ||||
| 	if m, err := gaugeArray(record, pts); assert.NoError(t, err) { | ||||
|   | ||||
| @@ -30,19 +30,18 @@ import ( | ||||
|  | ||||
| 	"go.opentelemetry.io/otel/attribute" | ||||
| 	"go.opentelemetry.io/otel/metric" | ||||
| 	"go.opentelemetry.io/otel/metric/number" | ||||
| 	export "go.opentelemetry.io/otel/sdk/export/metric" | ||||
| 	"go.opentelemetry.io/otel/sdk/export/metric/metrictest" | ||||
| 	"go.opentelemetry.io/otel/sdk/metric/aggregator/aggregatortest" | ||||
| 	"go.opentelemetry.io/otel/sdk/metric/aggregator/lastvalue" | ||||
| 	"go.opentelemetry.io/otel/sdk/metric/aggregator/minmaxsumcount" | ||||
| 	"go.opentelemetry.io/otel/sdk/metric/aggregator/sum" | ||||
| 	controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" | ||||
| 	processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" | ||||
| 	"go.opentelemetry.io/otel/sdk/metric/processor/processortest" | ||||
| 	"go.opentelemetry.io/otel/sdk/resource" | ||||
| ) | ||||
|  | ||||
| type testFixture struct { | ||||
| 	t        *testing.T | ||||
| 	ctx      context.Context | ||||
| 	cont     *controller.Controller | ||||
| 	meter    metric.Meter | ||||
| 	exporter *stdoutmetric.Exporter | ||||
| 	output   *bytes.Buffer | ||||
| } | ||||
| @@ -50,6 +49,10 @@ type testFixture struct { | ||||
| var testResource = resource.NewSchemaless(attribute.String("R", "V")) | ||||
|  | ||||
| func newFixture(t *testing.T, opts ...stdoutmetric.Option) testFixture { | ||||
| 	return newFixtureWithResource(t, testResource, opts...) | ||||
| } | ||||
|  | ||||
| func newFixtureWithResource(t *testing.T, res *resource.Resource, opts ...stdoutmetric.Option) testFixture { | ||||
| 	buf := &bytes.Buffer{} | ||||
| 	opts = append(opts, stdoutmetric.WithWriter(buf)) | ||||
| 	opts = append(opts, stdoutmetric.WithoutTimestamps()) | ||||
| @@ -57,10 +60,22 @@ func newFixture(t *testing.T, opts ...stdoutmetric.Option) testFixture { | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Error building fixture: ", err) | ||||
| 	} | ||||
| 	aggSel := processortest.AggregatorSelector() | ||||
| 	proc := processor.New(aggSel, export.StatelessExportKindSelector()) | ||||
| 	cont := controller.New(proc, | ||||
| 		controller.WithExporter(exp), | ||||
| 		controller.WithResource(res), | ||||
| 	) | ||||
| 	ctx := context.Background() | ||||
| 	require.NoError(t, cont.Start(ctx)) | ||||
| 	meter := cont.MeterProvider().Meter("test") | ||||
|  | ||||
| 	return testFixture{ | ||||
| 		t:        t, | ||||
| 		ctx:      context.Background(), | ||||
| 		ctx:      ctx, | ||||
| 		exporter: exp, | ||||
| 		cont:     cont, | ||||
| 		meter:    meter, | ||||
| 		output:   buf, | ||||
| 	} | ||||
| } | ||||
| @@ -69,41 +84,33 @@ func (fix testFixture) Output() string { | ||||
| 	return strings.TrimSpace(fix.output.String()) | ||||
| } | ||||
|  | ||||
| func (fix testFixture) Export(checkpointSet export.CheckpointSet) { | ||||
| 	err := fix.exporter.Export(fix.ctx, checkpointSet) | ||||
| 	if err != nil { | ||||
| 		fix.t.Error("export failed: ", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestStdoutTimestamp(t *testing.T) { | ||||
| 	var buf bytes.Buffer | ||||
| 	aggSel := processortest.AggregatorSelector() | ||||
| 	proc := processor.New(aggSel, export.CumulativeExportKindSelector()) | ||||
| 	exporter, err := stdoutmetric.New( | ||||
| 		stdoutmetric.WithWriter(&buf), | ||||
| 	) | ||||
| 	if err != nil { | ||||
| 		t.Fatal("Invalid config: ", err) | ||||
| 	} | ||||
| 	cont := controller.New(proc, | ||||
| 		controller.WithExporter(exporter), | ||||
| 		controller.WithResource(testResource), | ||||
| 	) | ||||
| 	ctx := context.Background() | ||||
|  | ||||
| 	require.NoError(t, cont.Start(ctx)) | ||||
| 	meter := cont.MeterProvider().Meter("test") | ||||
| 	counter := metric.Must(meter).NewInt64Counter("name.lastvalue") | ||||
|  | ||||
| 	before := time.Now() | ||||
| 	// Ensure the timestamp is after before. | ||||
| 	time.Sleep(time.Nanosecond) | ||||
|  | ||||
| 	checkpointSet := metrictest.NewCheckpointSet(testResource) | ||||
| 	counter.Add(ctx, 1) | ||||
|  | ||||
| 	ctx := context.Background() | ||||
| 	desc := metric.NewDescriptor("test.name", metric.ValueObserverInstrumentKind, number.Int64Kind) | ||||
|  | ||||
| 	lvagg, ckpt := metrictest.Unslice2(lastvalue.New(2)) | ||||
|  | ||||
| 	aggregatortest.CheckedUpdate(t, lvagg, number.NewInt64Number(321), &desc) | ||||
| 	require.NoError(t, lvagg.SynchronizedMove(ckpt, &desc)) | ||||
|  | ||||
| 	checkpointSet.Add(&desc, ckpt) | ||||
|  | ||||
| 	if err := exporter.Export(ctx, checkpointSet); err != nil { | ||||
| 		t.Fatal("Unexpected export error: ", err) | ||||
| 	} | ||||
| 	require.NoError(t, cont.Stop(ctx)) | ||||
|  | ||||
| 	// Ensure the timestamp is before after. | ||||
| 	time.Sleep(time.Nanosecond) | ||||
| @@ -131,129 +138,71 @@ func TestStdoutTimestamp(t *testing.T) { | ||||
| func TestStdoutCounterFormat(t *testing.T) { | ||||
| 	fix := newFixture(t) | ||||
|  | ||||
| 	checkpointSet := metrictest.NewCheckpointSet(testResource) | ||||
| 	counter := metric.Must(fix.meter).NewInt64Counter("name.sum") | ||||
| 	counter.Add(fix.ctx, 123, attribute.String("A", "B"), attribute.String("C", "D")) | ||||
|  | ||||
| 	desc := metric.NewDescriptor("test.name", metric.CounterInstrumentKind, number.Int64Kind) | ||||
| 	require.NoError(t, fix.cont.Stop(fix.ctx)) | ||||
|  | ||||
| 	cagg, ckpt := metrictest.Unslice2(sum.New(2)) | ||||
|  | ||||
| 	aggregatortest.CheckedUpdate(fix.t, cagg, number.NewInt64Number(123), &desc) | ||||
| 	require.NoError(t, cagg.SynchronizedMove(ckpt, &desc)) | ||||
|  | ||||
| 	checkpointSet.Add(&desc, ckpt, attribute.String("A", "B"), attribute.String("C", "D")) | ||||
|  | ||||
| 	fix.Export(checkpointSet) | ||||
|  | ||||
| 	require.Equal(t, `[{"Name":"test.name{R=V,A=B,C=D}","Sum":123}]`, fix.Output()) | ||||
| 	require.Equal(t, `[{"Name":"name.sum{R=V,instrumentation.name=test,A=B,C=D}","Sum":123}]`, fix.Output()) | ||||
| } | ||||
|  | ||||
| func TestStdoutLastValueFormat(t *testing.T) { | ||||
| 	fix := newFixture(t) | ||||
|  | ||||
| 	checkpointSet := metrictest.NewCheckpointSet(testResource) | ||||
| 	counter := metric.Must(fix.meter).NewFloat64Counter("name.lastvalue") | ||||
| 	counter.Add(fix.ctx, 123.456, attribute.String("A", "B"), attribute.String("C", "D")) | ||||
|  | ||||
| 	desc := metric.NewDescriptor("test.name", metric.ValueObserverInstrumentKind, number.Float64Kind) | ||||
| 	lvagg, ckpt := metrictest.Unslice2(lastvalue.New(2)) | ||||
| 	require.NoError(t, fix.cont.Stop(fix.ctx)) | ||||
|  | ||||
| 	aggregatortest.CheckedUpdate(fix.t, lvagg, number.NewFloat64Number(123.456), &desc) | ||||
| 	require.NoError(t, lvagg.SynchronizedMove(ckpt, &desc)) | ||||
|  | ||||
| 	checkpointSet.Add(&desc, ckpt, attribute.String("A", "B"), attribute.String("C", "D")) | ||||
|  | ||||
| 	fix.Export(checkpointSet) | ||||
|  | ||||
| 	require.Equal(t, `[{"Name":"test.name{R=V,A=B,C=D}","Last":123.456}]`, fix.Output()) | ||||
| 	require.Equal(t, `[{"Name":"name.lastvalue{R=V,instrumentation.name=test,A=B,C=D}","Last":123.456}]`, fix.Output()) | ||||
| } | ||||
|  | ||||
| func TestStdoutMinMaxSumCount(t *testing.T) { | ||||
| 	fix := newFixture(t) | ||||
|  | ||||
| 	checkpointSet := metrictest.NewCheckpointSet(testResource) | ||||
| 	counter := metric.Must(fix.meter).NewFloat64Counter("name.minmaxsumcount") | ||||
| 	counter.Add(fix.ctx, 123.456, attribute.String("A", "B"), attribute.String("C", "D")) | ||||
| 	counter.Add(fix.ctx, 876.543, attribute.String("A", "B"), attribute.String("C", "D")) | ||||
|  | ||||
| 	desc := metric.NewDescriptor("test.name", metric.ValueRecorderInstrumentKind, number.Float64Kind) | ||||
| 	require.NoError(t, fix.cont.Stop(fix.ctx)) | ||||
|  | ||||
| 	magg, ckpt := metrictest.Unslice2(minmaxsumcount.New(2, &desc)) | ||||
|  | ||||
| 	aggregatortest.CheckedUpdate(fix.t, magg, number.NewFloat64Number(123.456), &desc) | ||||
| 	aggregatortest.CheckedUpdate(fix.t, magg, number.NewFloat64Number(876.543), &desc) | ||||
| 	require.NoError(t, magg.SynchronizedMove(ckpt, &desc)) | ||||
|  | ||||
| 	checkpointSet.Add(&desc, ckpt, attribute.String("A", "B"), attribute.String("C", "D")) | ||||
|  | ||||
| 	fix.Export(checkpointSet) | ||||
|  | ||||
| 	require.Equal(t, `[{"Name":"test.name{R=V,A=B,C=D}","Min":123.456,"Max":876.543,"Sum":999.999,"Count":2}]`, fix.Output()) | ||||
| 	require.Equal(t, `[{"Name":"name.minmaxsumcount{R=V,instrumentation.name=test,A=B,C=D}","Min":123.456,"Max":876.543,"Sum":999.999,"Count":2}]`, fix.Output()) | ||||
| } | ||||
|  | ||||
| func TestStdoutValueRecorderFormat(t *testing.T) { | ||||
| 	fix := newFixture(t, stdoutmetric.WithPrettyPrint()) | ||||
|  | ||||
| 	checkpointSet := metrictest.NewCheckpointSet(testResource) | ||||
|  | ||||
| 	desc := metric.NewDescriptor("test.name", metric.ValueRecorderInstrumentKind, number.Float64Kind) | ||||
| 	aagg, ckpt := metrictest.Unslice2(minmaxsumcount.New(2, &desc)) | ||||
| 	inst := metric.Must(fix.meter).NewFloat64ValueRecorder("name.histogram") | ||||
|  | ||||
| 	for i := 0; i < 1000; i++ { | ||||
| 		aggregatortest.CheckedUpdate(fix.t, aagg, number.NewFloat64Number(float64(i)+0.5), &desc) | ||||
| 		inst.Record(fix.ctx, float64(i)+0.5, attribute.String("A", "B"), attribute.String("C", "D")) | ||||
| 	} | ||||
| 	require.NoError(t, fix.cont.Stop(fix.ctx)) | ||||
|  | ||||
| 	require.NoError(t, aagg.SynchronizedMove(ckpt, &desc)) | ||||
|  | ||||
| 	checkpointSet.Add(&desc, ckpt, attribute.String("A", "B"), attribute.String("C", "D")) | ||||
|  | ||||
| 	fix.Export(checkpointSet) | ||||
|  | ||||
| 	// TODO: Stdout does not export `Count` for histogram, nor the buckets. | ||||
| 	require.Equal(t, `[ | ||||
| 	{ | ||||
| 		"Name": "test.name{R=V,A=B,C=D}", | ||||
| 		"Min": 0.5, | ||||
| 		"Max": 999.5, | ||||
| 		"Sum": 500000, | ||||
| 		"Count": 1000 | ||||
| 		"Name": "name.histogram{R=V,instrumentation.name=test,A=B,C=D}", | ||||
| 		"Sum": 500000 | ||||
| 	} | ||||
| ]`, fix.Output()) | ||||
| } | ||||
|  | ||||
| func TestStdoutNoData(t *testing.T) { | ||||
| 	desc := metric.NewDescriptor("test.name", metric.ValueRecorderInstrumentKind, number.Float64Kind) | ||||
|  | ||||
| 	runTwoAggs := func(agg, ckpt export.Aggregator) { | ||||
| 		t.Run(fmt.Sprintf("%T", agg), func(t *testing.T) { | ||||
| 	runTwoAggs := func(aggName string) { | ||||
| 		t.Run(aggName, func(t *testing.T) { | ||||
| 			t.Parallel() | ||||
|  | ||||
| 			fix := newFixture(t) | ||||
|  | ||||
| 			checkpointSet := metrictest.NewCheckpointSet(testResource) | ||||
|  | ||||
| 			require.NoError(t, agg.SynchronizedMove(ckpt, &desc)) | ||||
|  | ||||
| 			checkpointSet.Add(&desc, ckpt) | ||||
|  | ||||
| 			fix.Export(checkpointSet) | ||||
| 			_ = metric.Must(fix.meter).NewFloat64Counter(fmt.Sprint("name.", aggName)) | ||||
| 			require.NoError(t, fix.cont.Stop(fix.ctx)) | ||||
|  | ||||
| 			require.Equal(t, "", fix.Output()) | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	runTwoAggs(metrictest.Unslice2(lastvalue.New(2))) | ||||
| 	runTwoAggs(metrictest.Unslice2(minmaxsumcount.New(2, &desc))) | ||||
| } | ||||
|  | ||||
| func TestStdoutLastValueNotSet(t *testing.T) { | ||||
| 	fix := newFixture(t) | ||||
|  | ||||
| 	checkpointSet := metrictest.NewCheckpointSet(testResource) | ||||
|  | ||||
| 	desc := metric.NewDescriptor("test.name", metric.ValueObserverInstrumentKind, number.Float64Kind) | ||||
|  | ||||
| 	lvagg, ckpt := metrictest.Unslice2(lastvalue.New(2)) | ||||
| 	require.NoError(t, lvagg.SynchronizedMove(ckpt, &desc)) | ||||
|  | ||||
| 	checkpointSet.Add(&desc, lvagg, attribute.String("A", "B"), attribute.String("C", "D")) | ||||
|  | ||||
| 	fix.Export(checkpointSet) | ||||
|  | ||||
| 	require.Equal(t, "", fix.Output()) | ||||
| 	runTwoAggs("lastvalue") | ||||
| 	runTwoAggs("minmaxsumcount") | ||||
| } | ||||
|  | ||||
| func TestStdoutResource(t *testing.T) { | ||||
| @@ -270,41 +219,35 @@ func TestStdoutResource(t *testing.T) { | ||||
| 		} | ||||
| 	} | ||||
| 	testCases := []testCase{ | ||||
| 		newCase("R1=V1,R2=V2,A=B,C=D", | ||||
| 		newCase("R1=V1,R2=V2,instrumentation.name=test,A=B,C=D", | ||||
| 			resource.NewSchemaless(attribute.String("R1", "V1"), attribute.String("R2", "V2")), | ||||
| 			attribute.String("A", "B"), | ||||
| 			attribute.String("C", "D")), | ||||
| 		newCase("R1=V1,R2=V2", | ||||
| 		newCase("R1=V1,R2=V2,instrumentation.name=test", | ||||
| 			resource.NewSchemaless(attribute.String("R1", "V1"), attribute.String("R2", "V2")), | ||||
| 		), | ||||
| 		newCase("A=B,C=D", | ||||
| 		newCase("instrumentation.name=test,A=B,C=D", | ||||
| 			nil, | ||||
| 			attribute.String("A", "B"), | ||||
| 			attribute.String("C", "D"), | ||||
| 		), | ||||
| 		// We explicitly do not de-duplicate between resources | ||||
| 		// and metric labels in this exporter. | ||||
| 		newCase("R1=V1,R2=V2,R1=V3,R2=V4", | ||||
| 		newCase("R1=V1,R2=V2,instrumentation.name=test,R1=V3,R2=V4", | ||||
| 			resource.NewSchemaless(attribute.String("R1", "V1"), attribute.String("R2", "V2")), | ||||
| 			attribute.String("R1", "V3"), | ||||
| 			attribute.String("R2", "V4")), | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range testCases { | ||||
| 		fix := newFixture(t) | ||||
| 		ctx := context.Background() | ||||
| 		fix := newFixtureWithResource(t, tc.res) | ||||
|  | ||||
| 		checkpointSet := metrictest.NewCheckpointSet(tc.res) | ||||
| 		counter := metric.Must(fix.meter).NewFloat64Counter("name.lastvalue") | ||||
| 		counter.Add(ctx, 123.456, tc.attrs...) | ||||
|  | ||||
| 		desc := metric.NewDescriptor("test.name", metric.ValueObserverInstrumentKind, number.Float64Kind) | ||||
| 		lvagg, ckpt := metrictest.Unslice2(lastvalue.New(2)) | ||||
| 		require.NoError(t, fix.cont.Stop(fix.ctx)) | ||||
|  | ||||
| 		aggregatortest.CheckedUpdate(fix.t, lvagg, number.NewFloat64Number(123.456), &desc) | ||||
| 		require.NoError(t, lvagg.SynchronizedMove(ckpt, &desc)) | ||||
|  | ||||
| 		checkpointSet.Add(&desc, ckpt, tc.attrs...) | ||||
|  | ||||
| 		fix.Export(checkpointSet) | ||||
|  | ||||
| 		require.Equal(t, `[{"Name":"test.name{`+tc.expect+`}","Last":123.456}]`, fix.Output()) | ||||
| 		require.Equal(t, `[{"Name":"name.lastvalue{`+tc.expect+`}","Last":123.456}]`, fix.Output()) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,135 +0,0 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| package metrictest // import "go.opentelemetry.io/otel/sdk/export/metric/metrictest" | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"reflect" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"go.opentelemetry.io/otel/attribute" | ||||
| 	"go.opentelemetry.io/otel/metric" | ||||
| 	"go.opentelemetry.io/otel/metric/number" | ||||
| 	export "go.opentelemetry.io/otel/sdk/export/metric" | ||||
| 	"go.opentelemetry.io/otel/sdk/export/metric/aggregation" | ||||
| 	"go.opentelemetry.io/otel/sdk/resource" | ||||
| ) | ||||
|  | ||||
| type mapkey struct { | ||||
| 	desc     *metric.Descriptor | ||||
| 	distinct attribute.Distinct | ||||
| } | ||||
|  | ||||
| // CheckpointSet is useful for testing Exporters. | ||||
| // TODO(#872): Uses of this can be replaced by processortest.Output. | ||||
| type CheckpointSet struct { | ||||
| 	sync.RWMutex | ||||
| 	records  map[mapkey]export.Record | ||||
| 	updates  []export.Record | ||||
| 	resource *resource.Resource | ||||
| } | ||||
|  | ||||
| // NoopAggregator is useful for testing Exporters. | ||||
| type NoopAggregator struct{} | ||||
|  | ||||
| var _ export.Aggregator = (*NoopAggregator)(nil) | ||||
|  | ||||
| // Update implements export.Aggregator. | ||||
| func (NoopAggregator) Update(context.Context, number.Number, *metric.Descriptor) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // SynchronizedMove implements export.Aggregator. | ||||
| func (NoopAggregator) SynchronizedMove(export.Aggregator, *metric.Descriptor) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Merge implements export.Aggregator. | ||||
| func (NoopAggregator) Merge(export.Aggregator, *metric.Descriptor) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Aggregation returns an interface for reading the state of this aggregator. | ||||
| func (NoopAggregator) Aggregation() aggregation.Aggregation { | ||||
| 	return NoopAggregator{} | ||||
| } | ||||
|  | ||||
| // Kind implements aggregation.Aggregation. | ||||
| func (NoopAggregator) Kind() aggregation.Kind { | ||||
| 	return aggregation.Kind("Noop") | ||||
| } | ||||
|  | ||||
| // NewCheckpointSet returns a test CheckpointSet that new records could be added. | ||||
| // Records are grouped by their encoded labels. | ||||
| func NewCheckpointSet(resource *resource.Resource) *CheckpointSet { | ||||
| 	return &CheckpointSet{ | ||||
| 		records:  make(map[mapkey]export.Record), | ||||
| 		resource: resource, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Reset clears the Aggregator state. | ||||
| func (p *CheckpointSet) Reset() { | ||||
| 	p.records = make(map[mapkey]export.Record) | ||||
| 	p.updates = nil | ||||
| } | ||||
|  | ||||
| // Add a new record to a CheckpointSet. | ||||
| // | ||||
| // If there is an existing record with the same descriptor and labels, | ||||
| // the stored aggregator will be returned and should be merged. | ||||
| func (p *CheckpointSet) Add(desc *metric.Descriptor, newAgg export.Aggregator, labels ...attribute.KeyValue) (agg export.Aggregator, added bool) { | ||||
| 	elabels := attribute.NewSet(labels...) | ||||
|  | ||||
| 	key := mapkey{ | ||||
| 		desc:     desc, | ||||
| 		distinct: elabels.Equivalent(), | ||||
| 	} | ||||
| 	if record, ok := p.records[key]; ok { | ||||
| 		return record.Aggregation().(export.Aggregator), false | ||||
| 	} | ||||
|  | ||||
| 	rec := export.NewRecord(desc, &elabels, p.resource, newAgg.Aggregation(), time.Time{}, time.Time{}) | ||||
| 	p.updates = append(p.updates, rec) | ||||
| 	p.records[key] = rec | ||||
| 	return newAgg, true | ||||
| } | ||||
|  | ||||
| // ForEach does not use ExportKindSelected: use a real Processor to | ||||
| // test ExportKind functionality. | ||||
| func (p *CheckpointSet) ForEach(_ export.ExportKindSelector, f func(export.Record) error) error { | ||||
| 	for _, r := range p.updates { | ||||
| 		if err := f(r); err != nil && !errors.Is(err, aggregation.ErrNoData) { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Unslice2 takes a slice of []some.Aggregator and returns a slice of []export.Aggregator | ||||
| func Unslice2(sl interface{}) (one, two export.Aggregator) { | ||||
| 	slv := reflect.ValueOf(sl) | ||||
| 	if slv.Type().Kind() != reflect.Slice { | ||||
| 		panic("Invalid Unslice2") | ||||
| 	} | ||||
| 	if slv.Len() != 2 { | ||||
| 		panic("Invalid Unslice2: length > 2") | ||||
| 	} | ||||
| 	one = slv.Index(0).Addr().Interface().(export.Aggregator) | ||||
| 	two = slv.Index(1).Addr().Interface().(export.Aggregator) | ||||
| 	return | ||||
| } | ||||
| @@ -1,30 +0,0 @@ | ||||
| // Copyright The OpenTelemetry Authors | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| package metrictest | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/require" | ||||
| ) | ||||
|  | ||||
| func TestUnslice(t *testing.T) { | ||||
| 	in := make([]NoopAggregator, 2) | ||||
|  | ||||
| 	a, b := Unslice2(in) | ||||
|  | ||||
| 	require.Equal(t, a.(*NoopAggregator), &in[0]) | ||||
| 	require.Equal(t, b.(*NoopAggregator), &in[1]) | ||||
| } | ||||
| @@ -26,7 +26,6 @@ import ( | ||||
| 	"go.opentelemetry.io/otel" | ||||
| 	"go.opentelemetry.io/otel/attribute" | ||||
| 	"go.opentelemetry.io/otel/metric" | ||||
| 	"go.opentelemetry.io/otel/metric/number" | ||||
| 	export "go.opentelemetry.io/otel/sdk/export/metric" | ||||
| 	"go.opentelemetry.io/otel/sdk/export/metric/aggregation" | ||||
| 	metricsdk "go.opentelemetry.io/otel/sdk/metric" | ||||
| @@ -69,16 +68,6 @@ func init() { | ||||
| 	otel.SetErrorHandler(testHandler) | ||||
| } | ||||
|  | ||||
| // correctnessProcessor could be replaced with processortest.Processor | ||||
| // with a non-default aggregator selector.  TODO(#872) use the | ||||
| // processortest code here. | ||||
| type correctnessProcessor struct { | ||||
| 	t *testing.T | ||||
| 	*testSelector | ||||
|  | ||||
| 	accumulations []export.Accumulation | ||||
| } | ||||
|  | ||||
| type testSelector struct { | ||||
| 	selector    export.AggregatorSelector | ||||
| 	newAggCount int | ||||
| @@ -89,28 +78,24 @@ func (ts *testSelector) AggregatorFor(desc *metric.Descriptor, aggPtrs ...*expor | ||||
| 	processortest.AggregatorSelector().AggregatorFor(desc, aggPtrs...) | ||||
| } | ||||
|  | ||||
| func newSDK(t *testing.T) (metric.Meter, *metricsdk.Accumulator, *correctnessProcessor) { | ||||
| func newSDK(t *testing.T) (metric.Meter, *metricsdk.Accumulator, *testSelector, *processortest.Processor) { | ||||
| 	testHandler.Reset() | ||||
| 	processor := &correctnessProcessor{ | ||||
| 		t:            t, | ||||
| 		testSelector: &testSelector{selector: processortest.AggregatorSelector()}, | ||||
| 	} | ||||
| 	testSelector := &testSelector{selector: processortest.AggregatorSelector()} | ||||
| 	processor := processortest.NewProcessor( | ||||
| 		testSelector, | ||||
| 		attribute.DefaultEncoder(), | ||||
| 	) | ||||
| 	accum := metricsdk.NewAccumulator( | ||||
| 		processor, | ||||
| 		testResource, | ||||
| 	) | ||||
| 	meter := metric.WrapMeterImpl(accum, "test") | ||||
| 	return meter, accum, processor | ||||
| } | ||||
|  | ||||
| func (ci *correctnessProcessor) Process(accumulation export.Accumulation) error { | ||||
| 	ci.accumulations = append(ci.accumulations, accumulation) | ||||
| 	return nil | ||||
| 	return meter, accum, testSelector, processor | ||||
| } | ||||
|  | ||||
| func TestInputRangeCounter(t *testing.T) { | ||||
| 	ctx := context.Background() | ||||
| 	meter, sdk, processor := newSDK(t) | ||||
| 	meter, sdk, _, processor := newSDK(t) | ||||
|  | ||||
| 	counter := Must(meter).NewInt64Counter("name.sum") | ||||
|  | ||||
| @@ -120,19 +105,19 @@ func TestInputRangeCounter(t *testing.T) { | ||||
| 	checkpointed := sdk.Collect(ctx) | ||||
| 	require.Equal(t, 0, checkpointed) | ||||
|  | ||||
| 	processor.accumulations = nil | ||||
| 	processor.Reset() | ||||
| 	counter.Add(ctx, 1) | ||||
| 	checkpointed = sdk.Collect(ctx) | ||||
| 	sum, err := processor.accumulations[0].Aggregator().(aggregation.Sum).Sum() | ||||
| 	require.Equal(t, int64(1), sum.AsInt64()) | ||||
| 	require.Equal(t, map[string]float64{ | ||||
| 		"name.sum//R=V": 1, | ||||
| 	}, processor.Values()) | ||||
| 	require.Equal(t, 1, checkpointed) | ||||
| 	require.Nil(t, err) | ||||
| 	require.Nil(t, testHandler.Flush()) | ||||
| } | ||||
|  | ||||
| func TestInputRangeUpDownCounter(t *testing.T) { | ||||
| 	ctx := context.Background() | ||||
| 	meter, sdk, processor := newSDK(t) | ||||
| 	meter, sdk, _, processor := newSDK(t) | ||||
|  | ||||
| 	counter := Must(meter).NewInt64UpDownCounter("name.sum") | ||||
|  | ||||
| @@ -142,16 +127,16 @@ func TestInputRangeUpDownCounter(t *testing.T) { | ||||
| 	counter.Add(ctx, 1) | ||||
|  | ||||
| 	checkpointed := sdk.Collect(ctx) | ||||
| 	sum, err := processor.accumulations[0].Aggregator().(aggregation.Sum).Sum() | ||||
| 	require.Equal(t, int64(1), sum.AsInt64()) | ||||
| 	require.Equal(t, map[string]float64{ | ||||
| 		"name.sum//R=V": 1, | ||||
| 	}, processor.Values()) | ||||
| 	require.Equal(t, 1, checkpointed) | ||||
| 	require.Nil(t, err) | ||||
| 	require.Nil(t, testHandler.Flush()) | ||||
| } | ||||
|  | ||||
| func TestInputRangeValueRecorder(t *testing.T) { | ||||
| 	ctx := context.Background() | ||||
| 	meter, sdk, processor := newSDK(t) | ||||
| 	meter, sdk, _, processor := newSDK(t) | ||||
|  | ||||
| 	valuerecorder := Must(meter).NewFloat64ValueRecorder("name.exact") | ||||
|  | ||||
| @@ -164,19 +149,19 @@ func TestInputRangeValueRecorder(t *testing.T) { | ||||
| 	valuerecorder.Record(ctx, 1) | ||||
| 	valuerecorder.Record(ctx, 2) | ||||
|  | ||||
| 	processor.accumulations = nil | ||||
| 	processor.Reset() | ||||
| 	checkpointed = sdk.Collect(ctx) | ||||
|  | ||||
| 	count, err := processor.accumulations[0].Aggregator().(aggregation.Count).Count() | ||||
| 	require.Equal(t, uint64(2), count) | ||||
| 	require.Equal(t, map[string]float64{ | ||||
| 		"name.exact//R=V": 3, | ||||
| 	}, processor.Values()) | ||||
| 	require.Equal(t, 1, checkpointed) | ||||
| 	require.Nil(t, testHandler.Flush()) | ||||
| 	require.Nil(t, err) | ||||
| } | ||||
|  | ||||
| func TestDisabledInstrument(t *testing.T) { | ||||
| 	ctx := context.Background() | ||||
| 	meter, sdk, processor := newSDK(t) | ||||
| 	meter, sdk, _, processor := newSDK(t) | ||||
|  | ||||
| 	valuerecorder := Must(meter).NewFloat64ValueRecorder("name.disabled") | ||||
|  | ||||
| @@ -184,12 +169,12 @@ func TestDisabledInstrument(t *testing.T) { | ||||
| 	checkpointed := sdk.Collect(ctx) | ||||
|  | ||||
| 	require.Equal(t, 0, checkpointed) | ||||
| 	require.Equal(t, 0, len(processor.accumulations)) | ||||
| 	require.Equal(t, map[string]float64{}, processor.Values()) | ||||
| } | ||||
|  | ||||
| func TestRecordNaN(t *testing.T) { | ||||
| 	ctx := context.Background() | ||||
| 	meter, _, _ := newSDK(t) | ||||
| 	meter, _, _, _ := newSDK(t) | ||||
|  | ||||
| 	c := Must(meter).NewFloat64Counter("name.sum") | ||||
|  | ||||
| @@ -200,7 +185,7 @@ func TestRecordNaN(t *testing.T) { | ||||
|  | ||||
| func TestSDKLabelsDeduplication(t *testing.T) { | ||||
| 	ctx := context.Background() | ||||
| 	meter, sdk, processor := newSDK(t) | ||||
| 	meter, sdk, _, processor := newSDK(t) | ||||
|  | ||||
| 	counter := Must(meter).NewInt64Counter("name.sum") | ||||
|  | ||||
| @@ -217,7 +202,7 @@ func TestSDKLabelsDeduplication(t *testing.T) { | ||||
| 		keysB = append(keysB, attribute.Key(fmt.Sprintf("B%03d", i))) | ||||
| 	} | ||||
|  | ||||
| 	var allExpect [][]attribute.KeyValue | ||||
| 	allExpect := map[string]float64{} | ||||
| 	for numKeys := 0; numKeys < maxKeys; numKeys++ { | ||||
|  | ||||
| 		var kvsA []attribute.KeyValue | ||||
| @@ -238,29 +223,24 @@ func TestSDKLabelsDeduplication(t *testing.T) { | ||||
|  | ||||
| 		counter.Add(ctx, 1, kvsA...) | ||||
| 		counter.Add(ctx, 1, kvsA...) | ||||
| 		allExpect = append(allExpect, expectA) | ||||
| 		format := func(attrs []attribute.KeyValue) string { | ||||
| 			str := attribute.DefaultEncoder().Encode(newSetIter(attrs...)) | ||||
| 			return fmt.Sprint("name.sum/", str, "/R=V") | ||||
| 		} | ||||
| 		allExpect[format(expectA)] += 2 | ||||
|  | ||||
| 		if numKeys != 0 { | ||||
| 			// In this case A and B sets are the same. | ||||
| 			counter.Add(ctx, 1, kvsB...) | ||||
| 			counter.Add(ctx, 1, kvsB...) | ||||
| 			allExpect = append(allExpect, expectB) | ||||
| 			allExpect[format(expectB)] += 2 | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	sdk.Collect(ctx) | ||||
|  | ||||
| 	var actual [][]attribute.KeyValue | ||||
| 	for _, rec := range processor.accumulations { | ||||
| 		sum, _ := rec.Aggregator().(aggregation.Sum).Sum() | ||||
| 		require.Equal(t, sum, number.NewInt64Number(2)) | ||||
|  | ||||
| 		kvs := rec.Labels().ToSlice() | ||||
| 		actual = append(actual, kvs) | ||||
| 	} | ||||
|  | ||||
| 	require.ElementsMatch(t, allExpect, actual) | ||||
| 	require.EqualValues(t, allExpect, processor.Values()) | ||||
| } | ||||
|  | ||||
| func newSetIter(kvs ...attribute.KeyValue) attribute.Iterator { | ||||
| @@ -295,7 +275,7 @@ func TestDefaultLabelEncoder(t *testing.T) { | ||||
|  | ||||
| func TestObserverCollection(t *testing.T) { | ||||
| 	ctx := context.Background() | ||||
| 	meter, sdk, processor := newSDK(t) | ||||
| 	meter, sdk, _, processor := newSDK(t) | ||||
| 	mult := 1 | ||||
|  | ||||
| 	_ = Must(meter).NewFloat64ValueObserver("float.valueobserver.lastvalue", func(_ context.Context, result metric.Float64ObserverResult) { | ||||
| @@ -342,15 +322,11 @@ func TestObserverCollection(t *testing.T) { | ||||
| 	}) | ||||
|  | ||||
| 	for mult = 0; mult < 3; mult++ { | ||||
| 		processor.accumulations = nil | ||||
| 		processor.Reset() | ||||
|  | ||||
| 		collected := sdk.Collect(ctx) | ||||
| 		require.Equal(t, collected, len(processor.accumulations)) | ||||
| 		require.Equal(t, collected, len(processor.Values())) | ||||
|  | ||||
| 		out := processortest.NewOutput(attribute.DefaultEncoder()) | ||||
| 		for _, rec := range processor.accumulations { | ||||
| 			require.NoError(t, out.AddAccumulation(rec)) | ||||
| 		} | ||||
| 		mult := float64(mult) | ||||
| 		require.EqualValues(t, map[string]float64{ | ||||
| 			"float.valueobserver.lastvalue/A=B/R=V": -mult, | ||||
| @@ -367,13 +343,13 @@ func TestObserverCollection(t *testing.T) { | ||||
| 			"float.updownsumobserver.sum/C=D/R=V": mult, | ||||
| 			"int.updownsumobserver.sum//R=V":      -mult, | ||||
| 			"int.updownsumobserver.sum/A=B/R=V":   mult, | ||||
| 		}, out.Map()) | ||||
| 		}, processor.Values()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestSumObserverInputRange(t *testing.T) { | ||||
| 	ctx := context.Background() | ||||
| 	meter, sdk, processor := newSDK(t) | ||||
| 	meter, sdk, _, processor := newSDK(t) | ||||
|  | ||||
| 	// TODO: these tests are testing for negative values, not for _descending values_. Fix. | ||||
| 	_ = Must(meter).NewFloat64SumObserver("float.sumobserver.sum", func(_ context.Context, result metric.Float64ObserverResult) { | ||||
| @@ -392,7 +368,7 @@ func TestSumObserverInputRange(t *testing.T) { | ||||
| 	collected := sdk.Collect(ctx) | ||||
|  | ||||
| 	require.Equal(t, 0, collected) | ||||
| 	require.Equal(t, 0, len(processor.accumulations)) | ||||
| 	require.EqualValues(t, map[string]float64{}, processor.Values()) | ||||
|  | ||||
| 	// check that the error condition was reset | ||||
| 	require.NoError(t, testHandler.Flush()) | ||||
| @@ -400,7 +376,7 @@ func TestSumObserverInputRange(t *testing.T) { | ||||
|  | ||||
| func TestObserverBatch(t *testing.T) { | ||||
| 	ctx := context.Background() | ||||
| 	meter, sdk, processor := newSDK(t) | ||||
| 	meter, sdk, _, processor := newSDK(t) | ||||
|  | ||||
| 	var floatValueObs metric.Float64ValueObserver | ||||
| 	var intValueObs metric.Int64ValueObserver | ||||
| @@ -450,12 +426,8 @@ func TestObserverBatch(t *testing.T) { | ||||
|  | ||||
| 	collected := sdk.Collect(ctx) | ||||
|  | ||||
| 	require.Equal(t, collected, len(processor.accumulations)) | ||||
| 	require.Equal(t, collected, len(processor.Values())) | ||||
|  | ||||
| 	out := processortest.NewOutput(attribute.DefaultEncoder()) | ||||
| 	for _, rec := range processor.accumulations { | ||||
| 		require.NoError(t, out.AddAccumulation(rec)) | ||||
| 	} | ||||
| 	require.EqualValues(t, map[string]float64{ | ||||
| 		"float.sumobserver.sum//R=V":    1.1, | ||||
| 		"float.sumobserver.sum/A=B/R=V": 1000, | ||||
| @@ -471,12 +443,12 @@ func TestObserverBatch(t *testing.T) { | ||||
| 		"float.valueobserver.lastvalue/C=D/R=V": -1, | ||||
| 		"int.valueobserver.lastvalue//R=V":      1, | ||||
| 		"int.valueobserver.lastvalue/A=B/R=V":   1, | ||||
| 	}, out.Map()) | ||||
| 	}, processor.Values()) | ||||
| } | ||||
|  | ||||
| func TestRecordBatch(t *testing.T) { | ||||
| 	ctx := context.Background() | ||||
| 	meter, sdk, processor := newSDK(t) | ||||
| 	meter, sdk, _, processor := newSDK(t) | ||||
|  | ||||
| 	counter1 := Must(meter).NewInt64Counter("int64.sum") | ||||
| 	counter2 := Must(meter).NewFloat64Counter("float64.sum") | ||||
| @@ -497,16 +469,12 @@ func TestRecordBatch(t *testing.T) { | ||||
|  | ||||
| 	sdk.Collect(ctx) | ||||
|  | ||||
| 	out := processortest.NewOutput(attribute.DefaultEncoder()) | ||||
| 	for _, rec := range processor.accumulations { | ||||
| 		require.NoError(t, out.AddAccumulation(rec)) | ||||
| 	} | ||||
| 	require.EqualValues(t, map[string]float64{ | ||||
| 		"int64.sum/A=B,C=D/R=V":     1, | ||||
| 		"float64.sum/A=B,C=D/R=V":   2, | ||||
| 		"int64.exact/A=B,C=D/R=V":   3, | ||||
| 		"float64.exact/A=B,C=D/R=V": 4, | ||||
| 	}, out.Map()) | ||||
| 	}, processor.Values()) | ||||
| } | ||||
|  | ||||
| // TestRecordPersistence ensures that a direct-called instrument that | ||||
| @@ -514,7 +482,7 @@ func TestRecordBatch(t *testing.T) { | ||||
| // that its encoded labels will be cached across collection intervals. | ||||
| func TestRecordPersistence(t *testing.T) { | ||||
| 	ctx := context.Background() | ||||
| 	meter, sdk, processor := newSDK(t) | ||||
| 	meter, sdk, selector, _ := newSDK(t) | ||||
|  | ||||
| 	c := Must(meter).NewFloat64Counter("name.sum") | ||||
| 	b := c.Bind(attribute.String("bound", "true")) | ||||
| @@ -526,7 +494,7 @@ func TestRecordPersistence(t *testing.T) { | ||||
| 		sdk.Collect(ctx) | ||||
| 	} | ||||
|  | ||||
| 	require.Equal(t, 4, processor.newAggCount) | ||||
| 	require.Equal(t, 4, selector.newAggCount) | ||||
| } | ||||
|  | ||||
| func TestIncorrectInstruments(t *testing.T) { | ||||
| @@ -536,7 +504,7 @@ func TestIncorrectInstruments(t *testing.T) { | ||||
| 	var observer metric.Int64ValueObserver | ||||
|  | ||||
| 	ctx := context.Background() | ||||
| 	meter, sdk, _ := newSDK(t) | ||||
| 	meter, sdk, _, processor := newSDK(t) | ||||
|  | ||||
| 	// Now try with uninitialized instruments. | ||||
| 	meter.RecordBatch(ctx, nil, counter.Measurement(1)) | ||||
| @@ -562,12 +530,13 @@ func TestIncorrectInstruments(t *testing.T) { | ||||
|  | ||||
| 	collected = sdk.Collect(ctx) | ||||
| 	require.Equal(t, 0, collected) | ||||
| 	require.EqualValues(t, map[string]float64{}, processor.Values()) | ||||
| 	require.Equal(t, metricsdk.ErrUninitializedInstrument, testHandler.Flush()) | ||||
| } | ||||
|  | ||||
| func TestSyncInAsync(t *testing.T) { | ||||
| 	ctx := context.Background() | ||||
| 	meter, sdk, processor := newSDK(t) | ||||
| 	meter, sdk, _, processor := newSDK(t) | ||||
|  | ||||
| 	counter := Must(meter).NewFloat64Counter("counter.sum") | ||||
| 	_ = Must(meter).NewInt64ValueObserver("observer.lastvalue", | ||||
| @@ -579,12 +548,8 @@ func TestSyncInAsync(t *testing.T) { | ||||
|  | ||||
| 	sdk.Collect(ctx) | ||||
|  | ||||
| 	out := processortest.NewOutput(attribute.DefaultEncoder()) | ||||
| 	for _, rec := range processor.accumulations { | ||||
| 		require.NoError(t, out.AddAccumulation(rec)) | ||||
| 	} | ||||
| 	require.EqualValues(t, map[string]float64{ | ||||
| 		"counter.sum//R=V":        100, | ||||
| 		"observer.lastvalue//R=V": 10, | ||||
| 	}, out.Map()) | ||||
| 	}, processor.Values()) | ||||
| } | ||||
|   | ||||
| @@ -29,8 +29,8 @@ import ( | ||||
| 	"go.opentelemetry.io/otel/metric/number" | ||||
| 	export "go.opentelemetry.io/otel/sdk/export/metric" | ||||
| 	"go.opentelemetry.io/otel/sdk/export/metric/aggregation" | ||||
| 	"go.opentelemetry.io/otel/sdk/export/metric/metrictest" | ||||
| 	sdk "go.opentelemetry.io/otel/sdk/metric" | ||||
| 	"go.opentelemetry.io/otel/sdk/metric/aggregator/aggregatortest" | ||||
| 	"go.opentelemetry.io/otel/sdk/metric/processor/basic" | ||||
| 	"go.opentelemetry.io/otel/sdk/metric/processor/processortest" | ||||
| 	processorTest "go.opentelemetry.io/otel/sdk/metric/processor/processortest" | ||||
| @@ -301,7 +301,7 @@ func TestBasicInconsistent(t *testing.T) { | ||||
| 	b = basic.New(processorTest.AggregatorSelector(), export.StatelessExportKindSelector()) | ||||
|  | ||||
| 	desc := metric.NewDescriptor("inst", metric.CounterInstrumentKind, number.Int64Kind) | ||||
| 	accum := export.NewAccumulation(&desc, attribute.EmptySet(), resource.Empty(), metrictest.NoopAggregator{}) | ||||
| 	accum := export.NewAccumulation(&desc, attribute.EmptySet(), resource.Empty(), aggregatortest.NoopAggregator{}) | ||||
| 	require.Equal(t, basic.ErrInconsistentState, b.Process(accum)) | ||||
|  | ||||
| 	// Test invalid kind: | ||||
| @@ -326,7 +326,7 @@ func TestBasicTimestamps(t *testing.T) { | ||||
| 	afterNew := time.Now() | ||||
|  | ||||
| 	desc := metric.NewDescriptor("inst", metric.CounterInstrumentKind, number.Int64Kind) | ||||
| 	accum := export.NewAccumulation(&desc, attribute.EmptySet(), resource.Empty(), metrictest.NoopAggregator{}) | ||||
| 	accum := export.NewAccumulation(&desc, attribute.EmptySet(), resource.Empty(), aggregatortest.NoopAggregator{}) | ||||
|  | ||||
| 	b.StartCollection() | ||||
| 	_ = b.Process(accum) | ||||
|   | ||||
| @@ -121,6 +121,11 @@ func (p *Processor) Values() map[string]float64 { | ||||
| 	return p.output.Map() | ||||
| } | ||||
|  | ||||
| // Reset clears the state of this test processor. | ||||
| func (p *Processor) Reset() { | ||||
| 	p.output.Reset() | ||||
| } | ||||
|  | ||||
| // Checkpointer returns a checkpointer that computes a single | ||||
| // interval. | ||||
| func Checkpointer(p *Processor) export.Checkpointer { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user