Latest Results
metricdatatest: Improve printing of diffs (#8073)
I've been getting tired of trying to parse blobs of OTLP-like text when
debugging metrics SDK test failures. This PR updating the printing of
diffs between metrics.
### Changes
This combines the `compareDiff`, and `diffSlices` functions into a
single `diffSlices` function. The `compare` parameter now returns a
`[]string` instead of a bool, to allow us to get a list of specific
differences between elements. `diffSlices` now also accepts a
`formatContext` parameter that provides the context (e.g. which scope,
which metric, etc) to print before printing the difference itself.
I've chosen to use the scope name, metric name, and attributes as the
context for scope, metric, and datapoint respectively. We could print
out more (as those are not the only identifying fields), but that is
usually enough to point to the problem.
### Example
I "broke" one of the OpenCensus tests by changing the expected SpanID
from 2 -> 1. You can see the resulting error message before and after
below:
Before:
```
--- FAIL: TestConvertMetrics (0.00s)
--- FAIL: TestConvertMetrics/normal_Histogram,_summary,_gauges,_and_sums (0.00s)
metric_test.go:940: [ScopeMetrics Metrics not equal:
missing expected values:
metricdata.Metrics{Name:"foo.com/histogram-a", Description:"a testing histogram", Unit:"1",
Data:metricdata.Histogram[float64]{DataPoints:[]metricdata.HistogramDataPoint[float64]
{metricdata.HistogramDataPoint[float64]{Attributes:attribute.Set{hash:0x83dbf482c8017da3, data:
[2]attribute.KeyValue{attribute.KeyValue{Key:"a", Value:attribute.Value{vtype:4, numeric:0x0, stringly:"hello",
slice:interface {}(nil)}}, attribute.KeyValue{Key:"b", Value:attribute.Value{vtype:4, numeric:0x0, stringly:"world",
slice:interface {}(nil)}}}}, StartTime:time.Date(2026, time.March, 18, 15, 46, 53, 76753334, time.Local),
Time:time.Date(2026, time.March, 18, 15, 47, 53, 77753334, time.Local), Count:0x8, Bounds:[]float64{1, 2, 3},
BucketCounts:[]uint64{0x1, 0x2, 0x5}, Min:metricdata.Extrema[float64]{value:0, valid:false},
Max:metricdata.Extrema[float64]{value:0, valid:false}, Sum:100, Exemplars:[]metricdata.Exemplar[float64]
{metricdata.Exemplar[float64]{FilteredAttributes:[]attribute.KeyValue{attribute.KeyValue{Key:"bool",
Value:attribute.Value{vtype:1, numeric:0x1, stringly:"", slice:interface {}(nil)}}}, Time:time.Date(2026, time.March, 18, 15,
47, 43, 77753334, time.Local), Value:0.8, SpanID:[]uint8{0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, TraceID:[]uint8{0x1, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, metricdata.Exemplar[float64]{FilteredAttributes:
[]attribute.KeyValue(nil), Time:time.Date(2026, time.March, 18, 15, 47, 43, 77753334, time.Local), Value:1.5, SpanID:
[]uint8{0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, TraceID:[]uint8{0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0}}, metricdata.Exemplar[float64]{FilteredAttributes:[]attribute.KeyValue(nil), Time:time.Date(2026,
time.March, 18, 15, 47, 43, 77753334, time.Local), Value:2.6, SpanID:[]uint8{0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
TraceID:[]uint8{0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}},
metricdata.HistogramDataPoint[float64]{Attributes:attribute.Set{hash:0x83dbf482c8017da3, data:
[2]attribute.KeyValue{attribute.KeyValue{Key:"a", Value:attribute.Value{vtype:4, numeric:0x0, stringly:"hello",
slice:interface {}(nil)}}, attribute.KeyValue{Key:"b", Value:attribute.Value{vtype:4, numeric:0x0, stringly:"world",
slice:interface {}(nil)}}}}, StartTime:time.Date(2026, time.March, 18, 15, 46, 53, 76753334, time.Local),
Time:time.Date(2026, time.March, 18, 15, 47, 53, 76753334, time.Local), Count:0xa, Bounds:[]float64{1, 2, 3},
BucketCounts:[]uint64{0x1, 0x4, 0x5}, Min:metricdata.Extrema[float64]{value:0, valid:false},
Max:metricdata.Extrema[float64]{value:0, valid:false}, Sum:110, Exemplars:[]metricdata.Exemplar[float64]
{metricdata.Exemplar[float64]{FilteredAttributes:[]attribute.KeyValue(nil), Time:time.Date(2026, time.March, 18, 15, 47,
43, 77753334, time.Local), Value:0.9, SpanID:[]uint8{0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, TraceID:[]uint8{0x7, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, metricdata.Exemplar[float64]{FilteredAttributes:
[]attribute.KeyValue(nil), Time:time.Date(2026, time.March, 18, 15, 47, 43, 77753334, time.Local), Value:1.1, SpanID:
[]uint8{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, TraceID:[]uint8{0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0}}, metricdata.Exemplar[float64]{FilteredAttributes:[]attribute.KeyValue(nil), Time:time.Date(2026,
time.March, 18, 15, 47, 43, 77753334, time.Local), Value:2.7, SpanID:[]uint8{0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
TraceID:[]uint8{0xb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}}}, Temporality:0x1}}
unexpected additional values:
metricdata.Metrics{Name:"foo.com/histogram-a", Description:"a testing histogram", Unit:"1",
Data:metricdata.Histogram[float64]{DataPoints:[]metricdata.HistogramDataPoint[float64]
{metricdata.HistogramDataPoint[float64]{Attributes:attribute.Set{hash:0x83dbf482c8017da3, data:
[2]attribute.KeyValue{attribute.KeyValue{Key:"a", Value:attribute.Value{vtype:4, numeric:0x0, stringly:"hello",
slice:interface {}(nil)}}, attribute.KeyValue{Key:"b", Value:attribute.Value{vtype:4, numeric:0x0, stringly:"world",
slice:interface {}(nil)}}}}, StartTime:time.Date(2026, time.March, 18, 15, 46, 53, 76753334, time.Local),
Time:time.Date(2026, time.March, 18, 15, 47, 53, 77753334, time.Local), Count:0x8, Bounds:[]float64{1, 2, 3},
BucketCounts:[]uint64{0x1, 0x2, 0x5}, Min:metricdata.Extrema[float64]{value:0, valid:false},
Max:metricdata.Extrema[float64]{value:0, valid:false}, Sum:100, Exemplars:[]metricdata.Exemplar[float64]
{metricdata.Exemplar[float64]{FilteredAttributes:[]attribute.KeyValue{attribute.KeyValue{Key:"bool",
Value:attribute.Value{vtype:1, numeric:0x1, stringly:"", slice:interface {}(nil)}}}, Time:time.Date(2026, time.March, 18, 15,
47, 43, 77753334, time.Local), Value:0.8, SpanID:[]uint8{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, TraceID:[]uint8{0x1, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, metricdata.Exemplar[float64]{FilteredAttributes:
[]attribute.KeyValue(nil), Time:time.Date(2026, time.March, 18, 15, 47, 43, 77753334, time.Local), Value:1.5, SpanID:
[]uint8{0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, TraceID:[]uint8{0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0}}, metricdata.Exemplar[float64]{FilteredAttributes:[]attribute.KeyValue(nil), Time:time.Date(2026,
time.March, 18, 15, 47, 43, 77753334, time.Local), Value:2.6, SpanID:[]uint8{0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
TraceID:[]uint8{0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}},
metricdata.HistogramDataPoint[float64]{Attributes:attribute.Set{hash:0x83dbf482c8017da3, data:
[2]attribute.KeyValue{attribute.KeyValue{Key:"a", Value:attribute.Value{vtype:4, numeric:0x0, stringly:"hello",
slice:interface {}(nil)}}, attribute.KeyValue{Key:"b", Value:attribute.Value{vtype:4, numeric:0x0, stringly:"world",
slice:interface {}(nil)}}}}, StartTime:time.Date(2026, time.March, 18, 15, 46, 53, 76753334, time.Local),
Time:time.Date(2026, time.March, 18, 15, 47, 53, 76753334, time.Local), Count:0xa, Bounds:[]float64{1, 2, 3},
BucketCounts:[]uint64{0x1, 0x4, 0x5}, Min:metricdata.Extrema[float64]{value:0, valid:false},
Max:metricdata.Extrema[float64]{value:0, valid:false}, Sum:110, Exemplars:[]metricdata.Exemplar[float64]
{metricdata.Exemplar[float64]{FilteredAttributes:[]attribute.KeyValue(nil), Time:time.Date(2026, time.March, 18, 15, 47,
43, 77753334, time.Local), Value:0.9, SpanID:[]uint8{0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, TraceID:[]uint8{0x7, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, metricdata.Exemplar[float64]{FilteredAttributes:
[]attribute.KeyValue(nil), Time:time.Date(2026, time.March, 18, 15, 47, 43, 77753334, time.Local), Value:1.1, SpanID:
[]uint8{0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, TraceID:[]uint8{0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0}}, metricdata.Exemplar[float64]{FilteredAttributes:[]attribute.KeyValue(nil), Time:time.Date(2026,
time.March, 18, 15, 47, 43, 77753334, time.Local), Value:2.7, SpanID:[]uint8{0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
TraceID:[]uint8{0xb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}}}, Temporality:0x1}}
]
FAIL
FAIL go.opentelemetry.io/otel/bridge/opencensus/internal/ocmetric 0.037s
```
After:
```
--- FAIL: TestConvertMetrics (0.00s)
--- FAIL: TestConvertMetrics/normal_Histogram,_summary,_gauges,_and_sums (0.00s)
metric_test.go:940: [ScopeMetrics Metrics not equal:
Metric "foo.com/histogram-a":
Metrics Data not equal:
Histogram not equal:
Histogram DataPoints not equal:
HistogramDataPoint [a=hello,b=world]:
Exemplars not equal:
Exemplar:
SpanID not equal:
expected: [2 0 0 0 0 0 0 0]
actual: [1 0 0 0 0 0 0 0]
]
FAIL
FAIL go.opentelemetry.io/otel/bridge/opencensus/internal/ocmetric 0.036s
``` Latest Branches
N/A
ยฉ 2026 CodSpeed Technology