package metricdatatest
import "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
Package metricdatatest provides testing functionality for use with the metricdata package.
Index ¶
- func AssertAggregationsEqual(t TestingT, expected, actual metricdata.Aggregation, opts ...Option) bool
- func AssertEqual[T Datatypes](t TestingT, expected, actual T, opts ...Option) bool
- func AssertHasAttributes[T Datatypes](t TestingT, actual T, attrs ...attribute.KeyValue) bool
- type Datatypes
- type Option
- type TestingT
Examples ¶
Functions ¶
func AssertAggregationsEqual ¶
func AssertAggregationsEqual(t TestingT, expected, actual metricdata.Aggregation, opts ...Option) bool
AssertAggregationsEqual asserts that two Aggregations are equal.
Code:play
Output:Example¶
package main
import (
"context"
"fmt"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
)
func main() {
ctx := context.Background()
// Create a meterprovider with a reader
reader := sdkmetric.NewManualReader()
mp := sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader))
defer func() {
_ = mp.Shutdown(ctx)
}()
// Create an instrument(eg: counter/histogram/gauge) and simulate an operation
meter := mp.Meter("payment-service")
counter, _ := meter.Int64Counter("payment.count")
counter.Add(ctx, 5)
// Collect the metrics
rm := &metricdata.ResourceMetrics{}
_ = reader.Collect(ctx, rm)
got, _ := getMetrics("payment.count", rm)
want := metricdata.Metrics{
Data: metricdata.Sum[int64]{
DataPoints: []metricdata.DataPoint[int64]{{Value: 5}},
Temporality: metricdata.CumulativeTemporality,
IsMonotonic: true,
},
}
// Verify the expected data with the received one.
t := &mockTestingT{}
// Compare Aggregations
hasEqualAggregations := metricdatatest.AssertAggregationsEqual(
t,
want.Data,
got.Data,
metricdatatest.IgnoreTimestamp(),
)
fmt.Printf("Aggregations are equal: %t\n", hasEqualAggregations)
}
// Helper function to retrieve the metrics.
// nolint:unparam // 'bool' return value currently unused, but retained for completeness
func getMetrics(name string, rm *metricdata.ResourceMetrics) (metricdata.Metrics, bool) {
for _, scopeMetrics := range rm.ScopeMetrics {
for _, m := range scopeMetrics.Metrics {
if m.Name == name {
return m, true
}
}
}
return metricdata.Metrics{}, false
}
// mockTestingT implements the [metricdatatest.TestingT] interface for examples.
// Usually, we use [*testing.T] as a substitute.
type mockTestingT struct{}
func (*mockTestingT) Helper() {}
func (*mockTestingT) Error(...any) {}
Aggregations are equal: true
func AssertEqual ¶
AssertEqual asserts that the two concrete data-types from the metricdata
package are equal.
Code:play
Output:Example¶
package main
import (
"context"
"fmt"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
)
func main() {
ctx := context.Background()
// Create a meterprovider with a reader
reader := sdkmetric.NewManualReader()
mp := sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader))
defer func() {
_ = mp.Shutdown(ctx)
}()
// Create an instrument(eg: counter/histogram/gauge) and simulate an operation
meter := mp.Meter("payment-service")
counter, _ := meter.Int64Counter("payment.requests")
counter.Add(ctx, 5)
// Collect the metrics
rm := &metricdata.ResourceMetrics{}
_ = reader.Collect(ctx, rm)
got, _ := getMetrics("payment.requests", rm)
want := metricdata.Metrics{
Name: "payment.requests",
Data: metricdata.Sum[int64]{
DataPoints: []metricdata.DataPoint[int64]{{Value: 5}},
Temporality: metricdata.CumulativeTemporality,
IsMonotonic: true,
},
}
// Compare expected metrics with the received one
t := &mockTestingT{}
assertEqual := metricdatatest.AssertEqual(
t,
want,
got,
metricdatatest.IgnoreTimestamp(), // ignoring timestamps
)
fmt.Printf("Metrics are equal: %t\n", assertEqual)
}
// Helper function to retrieve the metrics.
// nolint:unparam // 'bool' return value currently unused, but retained for completeness
func getMetrics(name string, rm *metricdata.ResourceMetrics) (metricdata.Metrics, bool) {
for _, scopeMetrics := range rm.ScopeMetrics {
for _, m := range scopeMetrics.Metrics {
if m.Name == name {
return m, true
}
}
}
return metricdata.Metrics{}, false
}
// mockTestingT implements the [metricdatatest.TestingT] interface for examples.
// Usually, we use [*testing.T] as a substitute.
type mockTestingT struct{}
func (*mockTestingT) Helper() {}
func (*mockTestingT) Error(...any) {}
Metrics are equal: true
func AssertHasAttributes ¶
AssertHasAttributes asserts that all Datapoints or HistogramDataPoints have all passed attrs.
Code:play
Output:Example¶
package main
import (
"context"
"fmt"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
)
func main() {
ctx := context.Background()
// Create a meterprovider with a reader
reader := sdkmetric.NewManualReader()
mp := sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader))
defer func() {
_ = mp.Shutdown(ctx)
}()
// Simulate an operation using an instrument(eg: counter)
meter := mp.Meter("payment-service")
counter, _ := meter.Int64Counter("payment.requests")
// Add attribute to the measurement
attributes := attribute.NewSet(attribute.String("payment.method", "credit_card"))
counter.Add(ctx, 5, metric.WithAttributeSet(attributes))
// Collect the metrics
rm := &metricdata.ResourceMetrics{}
_ = reader.Collect(ctx, rm)
metrics, _ := getMetrics("payment.requests", rm)
// Verify the attributes in the received metrics
t := &mockTestingT{}
hasAttributes := metricdatatest.AssertHasAttributes(t, metrics, attributes.ToSlice()...)
fmt.Printf("Metrics contains attributes: %t\n", hasAttributes)
}
// Helper function to retrieve the metrics.
// nolint:unparam // 'bool' return value currently unused, but retained for completeness
func getMetrics(name string, rm *metricdata.ResourceMetrics) (metricdata.Metrics, bool) {
for _, scopeMetrics := range rm.ScopeMetrics {
for _, m := range scopeMetrics.Metrics {
if m.Name == name {
return m, true
}
}
}
return metricdata.Metrics{}, false
}
// mockTestingT implements the [metricdatatest.TestingT] interface for examples.
// Usually, we use [*testing.T] as a substitute.
type mockTestingT struct{}
func (*mockTestingT) Helper() {}
func (*mockTestingT) Error(...any) {}
Metrics contains attributes: true
Types ¶
type Datatypes ¶
type Datatypes interface {
metricdata.DataPoint[float64] |
metricdata.DataPoint[int64] |
metricdata.Gauge[float64] |
metricdata.Gauge[int64] |
metricdata.Histogram[float64] |
metricdata.Histogram[int64] |
metricdata.HistogramDataPoint[float64] |
metricdata.HistogramDataPoint[int64] |
metricdata.Extrema[int64] |
metricdata.Extrema[float64] |
metricdata.Metrics |
metricdata.ResourceMetrics |
metricdata.ScopeMetrics |
metricdata.Sum[float64] |
metricdata.Sum[int64] |
metricdata.Exemplar[float64] |
metricdata.Exemplar[int64] |
metricdata.ExponentialHistogram[float64] |
metricdata.ExponentialHistogram[int64] |
metricdata.ExponentialHistogramDataPoint[float64] |
metricdata.ExponentialHistogramDataPoint[int64] |
metricdata.ExponentialBucket |
metricdata.Summary |
metricdata.SummaryDataPoint |
metricdata.QuantileValue
}
Datatypes are the concrete data-types the metricdata package provides.
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option allows for fine grain control over how AssertEqual operates.
func IgnoreExemplars ¶
func IgnoreExemplars() Option
IgnoreExemplars disables checking if Exemplars are different.
Code:play
Output:Example¶
package main
import (
"fmt"
"time"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
)
func main() {
// Histogram data with Exemplars
want := metricdata.Metrics{
Name: "payment.duration",
Data: metricdata.Histogram[float64]{
DataPoints: []metricdata.HistogramDataPoint[float64]{
{
Count: 2,
Sum: 224.0,
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000},
BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0},
Exemplars: []metricdata.Exemplar[float64]{
{
FilteredAttributes: []attribute.KeyValue{
attribute.String("payment.type", "recurring"),
},
Time: time.Now(),
Value: 15.0,
SpanID: []byte{1, 2, 3, 4, 5, 6, 7, 8},
TraceID: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
},
},
},
},
Temporality: metricdata.CumulativeTemporality,
},
}
// Histogram data without Exemplars
got := metricdata.Metrics{
Name: "payment.duration",
Data: metricdata.Histogram[float64]{
// Aggregate measurements are different in received metrics(exemplars)
DataPoints: []metricdata.HistogramDataPoint[float64]{
{
Count: 2,
Sum: 224.0,
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000},
BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0},
},
},
Temporality: metricdata.CumulativeTemporality,
},
}
t := &mockTestingT{}
// Compare metrics
ignoreExemplars := metricdatatest.AssertEqual(
t,
want,
got,
metricdatatest.IgnoreExemplars(),
)
fmt.Printf("Metrics are equal(ignoring exemplars): %t\n", ignoreExemplars)
}
// mockTestingT implements the [metricdatatest.TestingT] interface for examples.
// Usually, we use [*testing.T] as a substitute.
type mockTestingT struct{}
func (*mockTestingT) Helper() {}
func (*mockTestingT) Error(...any) {}
Metrics are equal(ignoring exemplars): true
func IgnoreTimestamp ¶
func IgnoreTimestamp() Option
IgnoreTimestamp disables checking if timestamps are different.
func IgnoreValue ¶
func IgnoreValue() Option
IgnoreValue disables checking if values are different. This can be useful for non-deterministic values, like measured durations.
This will ignore the value and trace information for Exemplars;
the buckets, zero count, scale, sum, max, min, and counts of
ExponentialHistogramDataPoints; the buckets, sum, count, max,
and min of HistogramDataPoints; the value of DataPoints.
Code:play
Output:Example¶
package main
import (
"fmt"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
)
func main() {
want := metricdata.Metrics{
Name: "payment.duration",
Data: metricdata.Histogram[float64]{
DataPoints: []metricdata.HistogramDataPoint[float64]{
{
Count: 2,
Sum: 224.0,
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000},
BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0},
},
},
Temporality: metricdata.CumulativeTemporality,
},
}
got := metricdata.Metrics{
Name: "payment.duration",
Data: metricdata.Histogram[float64]{
// Aggregate measurements are different in received metrics
DataPoints: []metricdata.HistogramDataPoint[float64]{
{
Count: 10,
Sum: 0,
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000},
BucketCounts: []uint64{1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0},
},
},
Temporality: metricdata.CumulativeTemporality,
},
}
t := &mockTestingT{}
// Compare metrics without values
ignoreValue := metricdatatest.AssertEqual(
t,
want,
got,
metricdatatest.IgnoreValue(),
)
fmt.Printf("Metrics are equal(ignoring values): %t\n", ignoreValue)
}
// mockTestingT implements the [metricdatatest.TestingT] interface for examples.
// Usually, we use [*testing.T] as a substitute.
type mockTestingT struct{}
func (*mockTestingT) Helper() {}
func (*mockTestingT) Error(...any) {}
Metrics are equal(ignoring values): true
type TestingT ¶
type TestingT interface {
Helper()
Error(...any)
}
TestingT is an interface that implements testing.T, but without the private method of testing.TB, so other testing packages can rely on it as well. The methods in this interface must match the testing.TB interface.
Source Files ¶
assertion.go comparisons.go
- Version
- v1.43.0 (latest)
- Published
- Apr 3, 2026
- Platform
- linux/amd64
- Imports
- 7 packages
- Last checked
- 1 day ago –
Tools for package owners.