From 645163c56334f764ed2e9d1a8f742a22c0eac9f8 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sat, 14 Jan 2023 16:57:55 -0800 Subject: [PATCH] [internal/comparetest] Add support for all metric types --- ...test-add-support-for-all-metric-types.yaml | 11 + internal/comparetest/metrics.go | 342 +++++++++++++++++- internal/comparetest/metrics_test.go | 119 +++++- .../actual.json | 22 ++ .../expected.json | 22 ++ .../actual.json | 24 ++ .../expected.json | 24 ++ .../actual.json | 24 ++ .../expected.json | 24 ++ .../actual.json | 22 ++ .../expected.json | 22 ++ .../actual.json | 22 ++ .../expected.json | 22 ++ .../actual.json | 22 ++ .../expected.json | 22 ++ .../actual.json | 22 ++ .../expected.json | 22 ++ .../actual.json | 22 ++ .../expected.json | 22 ++ .../actual.json | 31 ++ .../expected.json | 35 ++ .../actual.json | 35 ++ .../expected.json | 35 ++ .../actual.json | 22 ++ .../expected.json | 22 ++ internal/comparetest/util.go | 4 + 26 files changed, 994 insertions(+), 22 deletions(-) create mode 100644 .chloggen/comparetest-add-support-for-all-metric-types.yaml create mode 100644 internal/comparetest/testdata/metrics/exp-histogram-data-point-count-mismatch/actual.json create mode 100644 internal/comparetest/testdata/metrics/exp-histogram-data-point-count-mismatch/expected.json create mode 100644 internal/comparetest/testdata/metrics/exp-histogram-data-point-negative-offset-mismatch/actual.json create mode 100644 internal/comparetest/testdata/metrics/exp-histogram-data-point-negative-offset-mismatch/expected.json create mode 100644 internal/comparetest/testdata/metrics/exp-histogram-data-point-positive-buckets-mismatch/actual.json create mode 100644 internal/comparetest/testdata/metrics/exp-histogram-data-point-positive-buckets-mismatch/expected.json create mode 100644 internal/comparetest/testdata/metrics/exp-histogram-data-point-sum-mismatch/actual.json create mode 100644 internal/comparetest/testdata/metrics/exp-histogram-data-point-sum-mismatch/expected.json create mode 100644 internal/comparetest/testdata/metrics/histogram-data-point-buckets-mismatch/actual.json create mode 100644 internal/comparetest/testdata/metrics/histogram-data-point-buckets-mismatch/expected.json create mode 100644 internal/comparetest/testdata/metrics/histogram-data-point-count-mismatch/actual.json create mode 100644 internal/comparetest/testdata/metrics/histogram-data-point-count-mismatch/expected.json create mode 100644 internal/comparetest/testdata/metrics/histogram-data-point-sum-mismatch/actual.json create mode 100644 internal/comparetest/testdata/metrics/histogram-data-point-sum-mismatch/expected.json create mode 100644 internal/comparetest/testdata/metrics/summary-data-point-count-mismatch/actual.json create mode 100644 internal/comparetest/testdata/metrics/summary-data-point-count-mismatch/expected.json create mode 100644 internal/comparetest/testdata/metrics/summary-data-point-quantile-values-length-mismatch/actual.json create mode 100644 internal/comparetest/testdata/metrics/summary-data-point-quantile-values-length-mismatch/expected.json create mode 100644 internal/comparetest/testdata/metrics/summary-data-point-quantile-values-mismatch/actual.json create mode 100644 internal/comparetest/testdata/metrics/summary-data-point-quantile-values-mismatch/expected.json create mode 100644 internal/comparetest/testdata/metrics/summary-data-point-sum-mismatch/actual.json create mode 100644 internal/comparetest/testdata/metrics/summary-data-point-sum-mismatch/expected.json diff --git a/.chloggen/comparetest-add-support-for-all-metric-types.yaml b/.chloggen/comparetest-add-support-for-all-metric-types.yaml new file mode 100644 index 000000000000..299ab02f4add --- /dev/null +++ b/.chloggen/comparetest-add-support-for-all-metric-types.yaml @@ -0,0 +1,11 @@ +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: internal/comparetest + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add support for all metric types + +# One or more tracking issues related to the change +issues: [17538] diff --git a/internal/comparetest/metrics.go b/internal/comparetest/metrics.go index c0d7ee7ca8fc..ec3d260793d9 100644 --- a/internal/comparetest/metrics.go +++ b/internal/comparetest/metrics.go @@ -168,13 +168,11 @@ func CompareMetricSlices(expected, actual pmetric.MetricSlice) error { return fmt.Errorf("metric DataType does not match expected: %s, actual: %s", expectedMetric.Type(), actualMetric.Type()) } - var expectedDataPoints pmetric.NumberDataPointSlice - var actualDataPoints pmetric.NumberDataPointSlice - switch actualMetric.Type() { case pmetric.MetricTypeGauge: - expectedDataPoints = expectedMetric.Gauge().DataPoints() - actualDataPoints = actualMetric.Gauge().DataPoints() + if err := CompareNumberDataPointSlices(expectedMetric.Gauge().DataPoints(), actualMetric.Gauge().DataPoints()); err != nil { + return multierr.Combine(fmt.Errorf("datapoints for metric: `%s`, do not match expected", actualMetric.Name()), err) + } case pmetric.MetricTypeSum: if actualMetric.Sum().AggregationTemporality() != expectedMetric.Sum().AggregationTemporality() { return fmt.Errorf("metric AggregationTemporality does not match expected: %s, actual: %s", expectedMetric.Sum().AggregationTemporality(), actualMetric.Sum().AggregationTemporality()) @@ -182,12 +180,27 @@ func CompareMetricSlices(expected, actual pmetric.MetricSlice) error { if actualMetric.Sum().IsMonotonic() != expectedMetric.Sum().IsMonotonic() { return fmt.Errorf("metric IsMonotonic does not match expected: %t, actual: %t", expectedMetric.Sum().IsMonotonic(), actualMetric.Sum().IsMonotonic()) } - expectedDataPoints = expectedMetric.Sum().DataPoints() - actualDataPoints = actualMetric.Sum().DataPoints() - } - - if err := CompareNumberDataPointSlices(expectedDataPoints, actualDataPoints); err != nil { - return multierr.Combine(fmt.Errorf("datapoints for metric: `%s`, do not match expected", actualMetric.Name()), err) + if err := CompareNumberDataPointSlices(expectedMetric.Sum().DataPoints(), actualMetric.Sum().DataPoints()); err != nil { + return multierr.Combine(fmt.Errorf("datapoints for metric: `%s`, do not match expected", actualMetric.Name()), err) + } + case pmetric.MetricTypeHistogram: + if actualMetric.Histogram().AggregationTemporality() != expectedMetric.Histogram().AggregationTemporality() { + return fmt.Errorf("metric AggregationTemporality does not match expected: %s, actual: %s", expectedMetric.Histogram().AggregationTemporality(), actualMetric.Histogram().AggregationTemporality()) + } + if err := CompareHistogramDataPointSlices(expectedMetric.Histogram().DataPoints(), actualMetric.Histogram().DataPoints()); err != nil { + return multierr.Combine(fmt.Errorf("datapoints for metric: `%s`, do not match expected", actualMetric.Name()), err) + } + case pmetric.MetricTypeExponentialHistogram: + if actualMetric.ExponentialHistogram().AggregationTemporality() != expectedMetric.ExponentialHistogram().AggregationTemporality() { + return fmt.Errorf("metric AggregationTemporality does not match expected: %s, actual: %s", expectedMetric.ExponentialHistogram().AggregationTemporality(), actualMetric.ExponentialHistogram().AggregationTemporality()) + } + if err := CompareExponentialHistogramDataPointSlices(expectedMetric.ExponentialHistogram().DataPoints(), actualMetric.ExponentialHistogram().DataPoints()); err != nil { + return multierr.Combine(fmt.Errorf("datapoints for metric: `%s`, do not match expected", actualMetric.Name()), err) + } + case pmetric.MetricTypeSummary: + if err := CompareSummaryDataPointSlices(expectedMetric.Summary().DataPoints(), actualMetric.Summary().DataPoints()); err != nil { + return multierr.Combine(fmt.Errorf("datapoints for metric: `%s`, do not match expected", actualMetric.Name()), err) + } } } return nil @@ -248,7 +261,7 @@ func CompareNumberDataPointSlices(expected, actual pmetric.NumberDataPointSlice) // an error if they don't match. The error describes what didn't match. func CompareNumberDataPoints(expected, actual pmetric.NumberDataPoint) error { if expected.ValueType() != actual.ValueType() { - return fmt.Errorf("metric datapoint types don't match: expected type: %s, actual type: %s", numberTypeToString(expected.ValueType()), numberTypeToString(actual.ValueType())) + return fmt.Errorf("metric datapoint types don't match: expected type: %s, actual type: %s", expected.ValueType(), actual.ValueType()) } if expected.IntValue() != actual.IntValue() { return fmt.Errorf("metric datapoint IntVal doesn't match expected: %d, actual: %d", expected.IntValue(), actual.IntValue()) @@ -259,13 +272,302 @@ func CompareNumberDataPoints(expected, actual pmetric.NumberDataPoint) error { return nil } -func numberTypeToString(t pmetric.NumberDataPointValueType) string { - switch t { - case pmetric.NumberDataPointValueTypeInt: - return "int" - case pmetric.NumberDataPointValueTypeDouble: - return "double" - default: - return "none" +// CompareHistogramDataPointSlices compares each part of two given HistogramDataPointSlices and returns +// an error if they don't match. The error describes what didn't match. +func CompareHistogramDataPointSlices(expected, actual pmetric.HistogramDataPointSlice) error { + if expected.Len() != actual.Len() { + return fmt.Errorf("number of datapoints does not match expected: %d, actual: %d", expected.Len(), actual.Len()) + } + + numPoints := expected.Len() + + // Keep track of matching data points so that each point can only be matched once + matchingDPS := make(map[pmetric.HistogramDataPoint]pmetric.HistogramDataPoint, numPoints) + + var errs error + for e := 0; e < numPoints; e++ { + edp := expected.At(e) + var foundMatch bool + for a := 0; a < numPoints; a++ { + adp := actual.At(a) + if _, ok := matchingDPS[adp]; ok { + continue + } + if reflect.DeepEqual(edp.Attributes().AsRaw(), adp.Attributes().AsRaw()) { + foundMatch = true + matchingDPS[adp] = edp + break + } + } + + if !foundMatch { + errs = multierr.Append(errs, fmt.Errorf("metric missing expected datapoint with attributes: %v", edp.Attributes().AsRaw())) + } + } + + for i := 0; i < numPoints; i++ { + if _, ok := matchingDPS[actual.At(i)]; !ok { + errs = multierr.Append(errs, fmt.Errorf("metric has extra datapoint with attributes: %v", actual.At(i).Attributes().AsRaw())) + } + } + + if errs != nil { + return errs + } + + for adp, edp := range matchingDPS { + if err := CompareHistogramDataPoints(edp, adp); err != nil { + return multierr.Combine(fmt.Errorf("datapoint with attributes: %v, does not match expected", adp.Attributes().AsRaw()), err) + } + } + return nil +} + +// CompareHistogramDataPoints compares each part of two given HistogramDataPoints and returns +// an error if they don't match. The error describes what didn't match. +func CompareHistogramDataPoints(expected, actual pmetric.HistogramDataPoint) error { + if expected.HasSum() != actual.HasSum() { + return fmt.Errorf("metric datapoint HasSum doesn't match expected: %t, actual: %t", expected.HasSum(), actual.HasSum()) + } + if expected.HasSum() && expected.Sum() != actual.Sum() { + return fmt.Errorf("metric datapoint Sum doesn't match expected: %f, actual: %f", expected.Sum(), actual.Sum()) + } + if expected.HasMin() != actual.HasMin() { + return fmt.Errorf("metric datapoint HasMin doesn't match expected: %t, actual: %t", expected.HasMin(), actual.HasMin()) + } + if expected.HasMin() && expected.Min() != actual.Min() { + return fmt.Errorf("metric datapoint Min doesn't match expected: %f, actual: %f", expected.Min(), actual.Min()) + } + if expected.HasMax() != actual.HasMax() { + return fmt.Errorf("metric datapoint HasMax doesn't match expected: %t, actual: %t", expected.HasMax(), actual.HasMax()) + } + if expected.HasMax() && expected.Max() != actual.Max() { + return fmt.Errorf("metric datapoint Max doesn't match expected: %f, actual: %f", expected.Max(), actual.Max()) + } + if expected.Count() != actual.Count() { + return fmt.Errorf("metric datapoint Count doesn't match expected: %d, actual: %d", expected.Count(), actual.Count()) + } + if expected.StartTimestamp() != actual.StartTimestamp() { + return fmt.Errorf("metric datapoint StartTimestamp doesn't match expected: %d, actual: %d", expected.StartTimestamp(), actual.StartTimestamp()) + } + if expected.Timestamp() != actual.Timestamp() { + return fmt.Errorf("metric datapoint Timestamp doesn't match expected: %d, actual: %d", expected.Timestamp(), actual.Timestamp()) + } + if expected.Flags() != actual.Flags() { + return fmt.Errorf("metric datapoint Flags doesn't match expected: %d, actual: %d", expected.Flags(), actual.Flags()) + } + if !reflect.DeepEqual(expected.BucketCounts(), actual.BucketCounts()) { + return fmt.Errorf("metric datapoint BucketCounts doesn't match expected: %v, actual: %v", expected.BucketCounts().AsRaw(), actual.BucketCounts().AsRaw()) + } + if !reflect.DeepEqual(expected.ExplicitBounds(), actual.ExplicitBounds()) { + return fmt.Errorf("metric datapoint ExplicitBounds doesn't match expected: %v, actual: %v", expected.ExplicitBounds().AsRaw(), actual.ExplicitBounds().AsRaw()) + } + if !reflect.DeepEqual(expected.Attributes().AsRaw(), actual.Attributes().AsRaw()) { + return fmt.Errorf("metric datapoint Attributes doesn't match expected: %v, actual: %v", expected.Attributes().AsRaw(), actual.Attributes().AsRaw()) + } + return nil +} + +// CompareExponentialHistogramDataPointSlices compares each part of two given ExponentialHistogramDataPointSlices and returns +// an error if they don't match. The error describes what didn't match. +func CompareExponentialHistogramDataPointSlices(expected, actual pmetric.ExponentialHistogramDataPointSlice) error { + if expected.Len() != actual.Len() { + return fmt.Errorf("number of datapoints does not match expected: %d, actual: %d", expected.Len(), actual.Len()) } + + numPoints := expected.Len() + + // Keep track of matching data points so that each point can only be matched once + matchingDPS := make(map[pmetric.ExponentialHistogramDataPoint]pmetric.ExponentialHistogramDataPoint, numPoints) + + var errs error + for e := 0; e < numPoints; e++ { + edp := expected.At(e) + var foundMatch bool + for a := 0; a < numPoints; a++ { + adp := actual.At(a) + if _, ok := matchingDPS[adp]; ok { + continue + } + if reflect.DeepEqual(edp.Attributes().AsRaw(), adp.Attributes().AsRaw()) { + foundMatch = true + matchingDPS[adp] = edp + break + } + } + + if !foundMatch { + errs = multierr.Append(errs, fmt.Errorf("metric missing expected datapoint with attributes: %v", edp.Attributes().AsRaw())) + } + } + + for i := 0; i < numPoints; i++ { + if _, ok := matchingDPS[actual.At(i)]; !ok { + errs = multierr.Append(errs, fmt.Errorf("metric has extra datapoint with attributes: %v", actual.At(i).Attributes().AsRaw())) + } + } + + if errs != nil { + return errs + } + + for adp, edp := range matchingDPS { + if err := CompareExponentialHistogramDataPoints(edp, adp); err != nil { + return multierr.Combine(fmt.Errorf("datapoint with attributes: %v, does not match expected", adp.Attributes().AsRaw()), err) + } + } + return nil +} + +// CompareExponentialHistogramDataPoints compares each part of two given ExponentialHistogramDataPoints and returns +// an error if they don't match. The error describes what didn't match. +func CompareExponentialHistogramDataPoints(expected, actual pmetric.ExponentialHistogramDataPoint) error { + if expected.HasSum() != actual.HasSum() { + return fmt.Errorf("metric datapoint HasSum doesn't match expected: %t, actual: %t", expected.HasSum(), actual.HasSum()) + } + if expected.HasSum() && expected.Sum() != actual.Sum() { + return fmt.Errorf("metric datapoint Sum doesn't match expected: %f, actual: %f", expected.Sum(), actual.Sum()) + } + if expected.HasMin() != actual.HasMin() { + return fmt.Errorf("metric datapoint HasMin doesn't match expected: %t, actual: %t", expected.HasMin(), actual.HasMin()) + } + if expected.HasMin() && expected.Min() != actual.Min() { + return fmt.Errorf("metric datapoint Min doesn't match expected: %f, actual: %f", expected.Min(), actual.Min()) + } + if expected.HasMax() != actual.HasMax() { + return fmt.Errorf("metric datapoint HasMax doesn't match expected: %t, actual: %t", expected.HasMax(), actual.HasMax()) + } + if expected.HasMax() && expected.Max() != actual.Max() { + return fmt.Errorf("metric datapoint Max doesn't match expected: %f, actual: %f", expected.Max(), actual.Max()) + } + if expected.Count() != actual.Count() { + return fmt.Errorf("metric datapoint Count doesn't match expected: %d, actual: %d", expected.Count(), actual.Count()) + } + if expected.ZeroCount() != actual.ZeroCount() { + return fmt.Errorf("metric datapoint ZeroCount doesn't match expected: %d, actual: %d", expected.ZeroCount(), actual.ZeroCount()) + } + if expected.StartTimestamp() != actual.StartTimestamp() { + return fmt.Errorf("metric datapoint StartTimestamp doesn't match expected: %d, actual: %d", expected.StartTimestamp(), actual.StartTimestamp()) + } + if expected.Timestamp() != actual.Timestamp() { + return fmt.Errorf("metric datapoint Timestamp doesn't match expected: %d, actual: %d", expected.Timestamp(), actual.Timestamp()) + } + if expected.Flags() != actual.Flags() { + return fmt.Errorf("metric datapoint Flags doesn't match expected: %d, actual: %d", expected.Flags(), actual.Flags()) + } + if expected.Scale() != actual.Scale() { + return fmt.Errorf("metric datapoint Scale doesn't match expected: %v, actual: %v", expected.Scale(), actual.Scale()) + } + if expected.Negative().Offset() != actual.Negative().Offset() { + return fmt.Errorf("metric datapoint Negative Offset doesn't match expected: %v, actual: %v", expected.Negative().Offset(), actual.Negative().Offset()) + } + if !reflect.DeepEqual(expected.Negative().BucketCounts(), actual.Negative().BucketCounts()) { + return fmt.Errorf("metric datapoint Negative BucketCounts doesn't match expected: %v, actual: %v", + expected.Negative().BucketCounts().AsRaw(), actual.Negative().BucketCounts().AsRaw()) + } + if expected.Positive().Offset() != actual.Positive().Offset() { + return fmt.Errorf("metric datapoint Positive Offset doesn't match expected: %v, actual: %v", expected.Positive().Offset(), actual.Positive().Offset()) + } + if !reflect.DeepEqual(expected.Positive().BucketCounts(), actual.Positive().BucketCounts()) { + return fmt.Errorf("metric datapoint Positive BucketCounts doesn't match expected: %v, actual: %v", + expected.Positive().BucketCounts().AsRaw(), actual.Positive().BucketCounts().AsRaw()) + } + if !reflect.DeepEqual(expected.Attributes().AsRaw(), actual.Attributes().AsRaw()) { + return fmt.Errorf("metric datapoint Attributes doesn't match expected: %v, actual: %v", expected.Attributes().AsRaw(), actual.Attributes().AsRaw()) + } + return nil +} + +// CompareSummaryDataPointSlices compares each part of two given SummaryDataPoint slices and returns +// an error if they don't match. The error describes what didn't match. +func CompareSummaryDataPointSlices(expected, actual pmetric.SummaryDataPointSlice) error { + numPoints := expected.Len() + if numPoints != actual.Len() { + return fmt.Errorf("metric datapoint slice length doesn't match expected: %d, actual: %d", numPoints, actual.Len()) + } + + matchingDPS := map[pmetric.SummaryDataPoint]pmetric.SummaryDataPoint{} + var errs error + for e := 0; e < numPoints; e++ { + edp := expected.At(e) + var foundMatch bool + for a := 0; a < numPoints; a++ { + adp := actual.At(a) + if _, ok := matchingDPS[adp]; ok { + continue + } + if reflect.DeepEqual(edp.Attributes().AsRaw(), adp.Attributes().AsRaw()) { + foundMatch = true + matchingDPS[adp] = edp + break + } + } + + if !foundMatch { + errs = multierr.Append(errs, fmt.Errorf("metric missing expected datapoint with attributes: %v", edp.Attributes().AsRaw())) + } + } + + for i := 0; i < numPoints; i++ { + if _, ok := matchingDPS[actual.At(i)]; !ok { + errs = multierr.Append(errs, fmt.Errorf("metric has extra datapoint with attributes: %v", actual.At(i).Attributes().AsRaw())) + } + } + + if errs != nil { + return errs + } + + for adp, edp := range matchingDPS { + if err := CompareSummaryDataPoints(edp, adp); err != nil { + return multierr.Combine(fmt.Errorf("datapoint with attributes: %v, does not match expected", adp.Attributes().AsRaw()), err) + } + } + return nil +} + +// CompareSummaryDataPoints compares each part of two given SummaryDataPoint and returns +// an error if they don't match. The error describes what didn't match. +func CompareSummaryDataPoints(expected, actual pmetric.SummaryDataPoint) error { + if expected.Count() != actual.Count() { + return fmt.Errorf("metric datapoint Count doesn't match expected: %d, actual: %d", expected.Count(), actual.Count()) + } + if expected.Sum() != actual.Sum() { + return fmt.Errorf("metric datapoint Sum doesn't match expected: %f, actual: %f", expected.Sum(), actual.Sum()) + } + if expected.StartTimestamp() != actual.StartTimestamp() { + return fmt.Errorf("metric datapoint StartTimestamp doesn't match expected: %d, actual: %d", expected.StartTimestamp(), actual.StartTimestamp()) + } + if expected.Timestamp() != actual.Timestamp() { + return fmt.Errorf("metric datapoint Timestamp doesn't match expected: %d, actual: %d", expected.Timestamp(), actual.Timestamp()) + } + if expected.Flags() != actual.Flags() { + return fmt.Errorf("metric datapoint Flags doesn't match expected: %d, actual: %d", expected.Flags(), actual.Flags()) + } + if !reflect.DeepEqual(expected.Attributes().AsRaw(), actual.Attributes().AsRaw()) { + return fmt.Errorf("metric datapoint Attributes doesn't match expected: %v, actual: %v", expected.Attributes().AsRaw(), actual.Attributes().AsRaw()) + } + if expected.QuantileValues().Len() != actual.QuantileValues().Len() { + return fmt.Errorf("metric datapoint QuantileValues length doesn't match expected: %d, actual: %d", expected.QuantileValues().Len(), actual.QuantileValues().Len()) + } + + eqvs, acvs := pmetric.NewSummaryDataPointValueAtQuantileSlice(), pmetric.NewSummaryDataPointValueAtQuantileSlice() + expected.QuantileValues().CopyTo(eqvs) + actual.QuantileValues().CopyTo(acvs) + + eqvs.Sort(sortSummaryDataPointValueAtQuantileSlice) + acvs.Sort(sortSummaryDataPointValueAtQuantileSlice) + + for i := 0; i < eqvs.Len(); i++ { + eqv, acv := eqvs.At(i), acvs.At(i) + if eqv.Quantile() != acv.Quantile() { + return fmt.Errorf("metric datapoint quantile doesn't match expected: %f, actual: %f", eqv.Quantile(), acv.Quantile()) + } + if eqv.Value() != acv.Value() { + return fmt.Errorf("metric datapoint value at quantile %f doesn't match expected: %f, actual: %f", + eqv.Quantile(), eqv.Value(), acv.Value()) + } + } + + return nil } diff --git a/internal/comparetest/metrics_test.go b/internal/comparetest/metrics_test.go index e3f7de33207f..19fb75dc066f 100644 --- a/internal/comparetest/metrics_test.go +++ b/internal/comparetest/metrics_test.go @@ -270,7 +270,7 @@ func TestCompareMetrics(t *testing.T) { err: multierr.Combine( errors.New("datapoints for metric: `gauge.one`, do not match expected"), errors.New("datapoint with attributes: map[], does not match expected"), - errors.New("metric datapoint types don't match: expected type: int, actual type: double"), + errors.New("metric datapoint types don't match: expected type: Int, actual type: Double"), ), reason: "A data point with the wrong type of value should cause a failure.", }, @@ -281,11 +281,126 @@ func TestCompareMetrics(t *testing.T) { err: multierr.Combine( errors.New("datapoints for metric: `gauge.one`, do not match expected"), errors.New("datapoint with attributes: map[], does not match expected"), - errors.New("metric datapoint types don't match: expected type: double, actual type: int"), + errors.New("metric datapoint types don't match: expected type: Double, actual type: Int"), ), reason: "A data point with the wrong type of value should cause a failure.", }, }, + { + name: "histogram-data-point-count-mismatch", + withoutOptions: expectation{ + err: multierr.Combine( + errors.New("datapoints for metric: `histogram.one`, do not match expected"), + errors.New("datapoint with attributes: map[], does not match expected"), + errors.New("metric datapoint Count doesn't match expected: 123, actual: 654"), + ), + reason: "A data point with the wrong bucket count should cause a failure.", + }, + }, + { + name: "histogram-data-point-sum-mismatch", + withoutOptions: expectation{ + err: multierr.Combine( + errors.New("datapoints for metric: `histogram.one`, do not match expected"), + errors.New("datapoint with attributes: map[], does not match expected"), + errors.New("metric datapoint Sum doesn't match expected: 123.456000, actual: 654.321000"), + ), + }, + }, + { + name: "histogram-data-point-buckets-mismatch", + withoutOptions: expectation{ + err: multierr.Combine( + errors.New("datapoints for metric: `histogram.one`, do not match expected"), + errors.New("datapoint with attributes: map[], does not match expected"), + errors.New("metric datapoint BucketCounts doesn't match expected: [1 2 3], actual: [3 2 1]"), + ), + }, + }, + { + name: "exp-histogram-data-point-count-mismatch", + withoutOptions: expectation{ + err: multierr.Combine( + errors.New("datapoints for metric: `exponential_histogram.one`, do not match expected"), + errors.New("datapoint with attributes: map[], does not match expected"), + errors.New("metric datapoint Count doesn't match expected: 123, actual: 654"), + ), + reason: "A data point with the wrong bucket count should cause a failure.", + }, + }, + { + name: "exp-histogram-data-point-sum-mismatch", + withoutOptions: expectation{ + err: multierr.Combine( + errors.New("datapoints for metric: `exponential_histogram.one`, do not match expected"), + errors.New("datapoint with attributes: map[], does not match expected"), + errors.New("metric datapoint Sum doesn't match expected: 123.456000, actual: 654.321000"), + ), + }, + }, + { + name: "exp-histogram-data-point-positive-buckets-mismatch", + withoutOptions: expectation{ + err: multierr.Combine( + errors.New("datapoints for metric: `exponential_histogram.one`, do not match expected"), + errors.New("datapoint with attributes: map[], does not match expected"), + errors.New("metric datapoint Positive BucketCounts doesn't match expected: [1 2 3], "+ + "actual: [3 2 1]"), + ), + }, + }, + { + name: "exp-histogram-data-point-negative-offset-mismatch", + withoutOptions: expectation{ + err: multierr.Combine( + errors.New("datapoints for metric: `exponential_histogram.one`, do not match expected"), + errors.New("datapoint with attributes: map[], does not match expected"), + errors.New("metric datapoint Negative Offset doesn't match expected: 10, actual: 1"), + ), + }, + }, + { + name: "summary-data-point-count-mismatch", + withoutOptions: expectation{ + err: multierr.Combine( + errors.New("datapoints for metric: `summary.one`, do not match expected"), + errors.New("datapoint with attributes: map[], does not match expected"), + errors.New("metric datapoint Count doesn't match expected: 123, actual: 654"), + ), + reason: "A data point with the wrong bucket count should cause a failure.", + }, + }, + { + name: "summary-data-point-sum-mismatch", + withoutOptions: expectation{ + err: multierr.Combine( + errors.New("datapoints for metric: `summary.one`, do not match expected"), + errors.New("datapoint with attributes: map[], does not match expected"), + errors.New("metric datapoint Sum doesn't match expected: 123.456000, actual: 654.321000"), + ), + }, + }, + { + name: "summary-data-point-quantile-values-length-mismatch", + withoutOptions: expectation{ + err: multierr.Combine( + errors.New("datapoints for metric: `summary.one`, do not match expected"), + errors.New("datapoint with attributes: map[], does not match expected"), + errors.New("metric datapoint QuantileValues length doesn't match expected: 3, actual: 2"), + ), + }, + }, + { + name: "summary-data-point-quantile-values-mismatch", + withoutOptions: expectation{ + err: multierr.Combine( + errors.New("datapoints for metric: `summary.one`, do not match expected"), + errors.New("datapoint with attributes: map[], does not match expected"), + errors.New("metric datapoint value at quantile 0.990000 doesn't match expected: 99.000000, "+ + "actual: 110.000000"), + ), + }, + }, { name: "ignore-timestamp", withoutOptions: expectation{ diff --git a/internal/comparetest/testdata/metrics/exp-histogram-data-point-count-mismatch/actual.json b/internal/comparetest/testdata/metrics/exp-histogram-data-point-count-mismatch/actual.json new file mode 100644 index 000000000000..52b43dd72310 --- /dev/null +++ b/internal/comparetest/testdata/metrics/exp-histogram-data-point-count-mismatch/actual.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "exponential_histogram.one", + "exponentialHistogram": { + "dataPoints": [ + { + "count": 654 + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/exp-histogram-data-point-count-mismatch/expected.json b/internal/comparetest/testdata/metrics/exp-histogram-data-point-count-mismatch/expected.json new file mode 100644 index 000000000000..3f72759d9d0b --- /dev/null +++ b/internal/comparetest/testdata/metrics/exp-histogram-data-point-count-mismatch/expected.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "exponential_histogram.one", + "exponentialHistogram": { + "dataPoints": [ + { + "count": 123 + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/exp-histogram-data-point-negative-offset-mismatch/actual.json b/internal/comparetest/testdata/metrics/exp-histogram-data-point-negative-offset-mismatch/actual.json new file mode 100644 index 000000000000..7a1db8e6e2cb --- /dev/null +++ b/internal/comparetest/testdata/metrics/exp-histogram-data-point-negative-offset-mismatch/actual.json @@ -0,0 +1,24 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "exponential_histogram.one", + "exponentialHistogram": { + "dataPoints": [ + { + "negative": { + "offset": 1 + } + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/exp-histogram-data-point-negative-offset-mismatch/expected.json b/internal/comparetest/testdata/metrics/exp-histogram-data-point-negative-offset-mismatch/expected.json new file mode 100644 index 000000000000..93c291cc4275 --- /dev/null +++ b/internal/comparetest/testdata/metrics/exp-histogram-data-point-negative-offset-mismatch/expected.json @@ -0,0 +1,24 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "exponential_histogram.one", + "exponentialHistogram": { + "dataPoints": [ + { + "negative": { + "offset": 10 + } + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/exp-histogram-data-point-positive-buckets-mismatch/actual.json b/internal/comparetest/testdata/metrics/exp-histogram-data-point-positive-buckets-mismatch/actual.json new file mode 100644 index 000000000000..f949d858bef9 --- /dev/null +++ b/internal/comparetest/testdata/metrics/exp-histogram-data-point-positive-buckets-mismatch/actual.json @@ -0,0 +1,24 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "exponential_histogram.one", + "exponentialHistogram": { + "dataPoints": [ + { + "positive": { + "bucketCounts": [3, 2, 1] + } + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/exp-histogram-data-point-positive-buckets-mismatch/expected.json b/internal/comparetest/testdata/metrics/exp-histogram-data-point-positive-buckets-mismatch/expected.json new file mode 100644 index 000000000000..738077604ce6 --- /dev/null +++ b/internal/comparetest/testdata/metrics/exp-histogram-data-point-positive-buckets-mismatch/expected.json @@ -0,0 +1,24 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "exponential_histogram.one", + "exponentialHistogram": { + "dataPoints": [ + { + "positive": { + "bucketCounts": [1, 2, 3] + } + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/exp-histogram-data-point-sum-mismatch/actual.json b/internal/comparetest/testdata/metrics/exp-histogram-data-point-sum-mismatch/actual.json new file mode 100644 index 000000000000..c362b7b70d68 --- /dev/null +++ b/internal/comparetest/testdata/metrics/exp-histogram-data-point-sum-mismatch/actual.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "exponential_histogram.one", + "exponentialHistogram": { + "dataPoints": [ + { + "sum": 654.321000 + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/exp-histogram-data-point-sum-mismatch/expected.json b/internal/comparetest/testdata/metrics/exp-histogram-data-point-sum-mismatch/expected.json new file mode 100644 index 000000000000..54b0ad2fb1e9 --- /dev/null +++ b/internal/comparetest/testdata/metrics/exp-histogram-data-point-sum-mismatch/expected.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "exponential_histogram.one", + "exponentialHistogram": { + "dataPoints": [ + { + "sum": 123.456000 + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/histogram-data-point-buckets-mismatch/actual.json b/internal/comparetest/testdata/metrics/histogram-data-point-buckets-mismatch/actual.json new file mode 100644 index 000000000000..f1814d4d30c1 --- /dev/null +++ b/internal/comparetest/testdata/metrics/histogram-data-point-buckets-mismatch/actual.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "histogram.one", + "histogram": { + "dataPoints": [ + { + "bucketCounts": [3, 2, 1] + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/histogram-data-point-buckets-mismatch/expected.json b/internal/comparetest/testdata/metrics/histogram-data-point-buckets-mismatch/expected.json new file mode 100644 index 000000000000..bde972a4a212 --- /dev/null +++ b/internal/comparetest/testdata/metrics/histogram-data-point-buckets-mismatch/expected.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "histogram.one", + "histogram": { + "dataPoints": [ + { + "bucketCounts": [1, 2, 3] + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/histogram-data-point-count-mismatch/actual.json b/internal/comparetest/testdata/metrics/histogram-data-point-count-mismatch/actual.json new file mode 100644 index 000000000000..df5b43144418 --- /dev/null +++ b/internal/comparetest/testdata/metrics/histogram-data-point-count-mismatch/actual.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "histogram.one", + "histogram": { + "dataPoints": [ + { + "count": 654 + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/histogram-data-point-count-mismatch/expected.json b/internal/comparetest/testdata/metrics/histogram-data-point-count-mismatch/expected.json new file mode 100644 index 000000000000..36f751a2dc79 --- /dev/null +++ b/internal/comparetest/testdata/metrics/histogram-data-point-count-mismatch/expected.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "histogram.one", + "histogram": { + "dataPoints": [ + { + "count": 123 + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/histogram-data-point-sum-mismatch/actual.json b/internal/comparetest/testdata/metrics/histogram-data-point-sum-mismatch/actual.json new file mode 100644 index 000000000000..2fece498fd82 --- /dev/null +++ b/internal/comparetest/testdata/metrics/histogram-data-point-sum-mismatch/actual.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "histogram.one", + "histogram": { + "dataPoints": [ + { + "sum": 654.321000 + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/histogram-data-point-sum-mismatch/expected.json b/internal/comparetest/testdata/metrics/histogram-data-point-sum-mismatch/expected.json new file mode 100644 index 000000000000..214b927735f5 --- /dev/null +++ b/internal/comparetest/testdata/metrics/histogram-data-point-sum-mismatch/expected.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "histogram.one", + "histogram": { + "dataPoints": [ + { + "sum": 123.456000 + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/summary-data-point-count-mismatch/actual.json b/internal/comparetest/testdata/metrics/summary-data-point-count-mismatch/actual.json new file mode 100644 index 000000000000..f884d7b7e826 --- /dev/null +++ b/internal/comparetest/testdata/metrics/summary-data-point-count-mismatch/actual.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "summary.one", + "summary": { + "dataPoints": [ + { + "count": 654 + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/summary-data-point-count-mismatch/expected.json b/internal/comparetest/testdata/metrics/summary-data-point-count-mismatch/expected.json new file mode 100644 index 000000000000..77e3783d1767 --- /dev/null +++ b/internal/comparetest/testdata/metrics/summary-data-point-count-mismatch/expected.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "summary.one", + "summary": { + "dataPoints": [ + { + "count": 123 + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/summary-data-point-quantile-values-length-mismatch/actual.json b/internal/comparetest/testdata/metrics/summary-data-point-quantile-values-length-mismatch/actual.json new file mode 100644 index 000000000000..8a1b24df75ff --- /dev/null +++ b/internal/comparetest/testdata/metrics/summary-data-point-quantile-values-length-mismatch/actual.json @@ -0,0 +1,31 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "summary.one", + "summary": { + "dataPoints": [ + { + "quantileValues" : [ + { + "quantile": 0.9, + "value": 90 + }, + { + "quantile": 0.99, + "value": 99 + } + ] + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/summary-data-point-quantile-values-length-mismatch/expected.json b/internal/comparetest/testdata/metrics/summary-data-point-quantile-values-length-mismatch/expected.json new file mode 100644 index 000000000000..11a71db5f19b --- /dev/null +++ b/internal/comparetest/testdata/metrics/summary-data-point-quantile-values-length-mismatch/expected.json @@ -0,0 +1,35 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "summary.one", + "summary": { + "dataPoints": [ + { + "quantileValues" : [ + { + "quantile": 0.5, + "value": 50 + }, + { + "quantile": 0.9, + "value": 90 + }, + { + "quantile": 0.99, + "value": 99 + } + ] + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/summary-data-point-quantile-values-mismatch/actual.json b/internal/comparetest/testdata/metrics/summary-data-point-quantile-values-mismatch/actual.json new file mode 100644 index 000000000000..f764e9608a7e --- /dev/null +++ b/internal/comparetest/testdata/metrics/summary-data-point-quantile-values-mismatch/actual.json @@ -0,0 +1,35 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "summary.one", + "summary": { + "dataPoints": [ + { + "quantileValues" : [ + { + "quantile": 0.99, + "value": 110 + }, + { + "quantile": 0.9, + "value": 90 + }, + { + "quantile": 0.5, + "value": 50 + } + ] + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/summary-data-point-quantile-values-mismatch/expected.json b/internal/comparetest/testdata/metrics/summary-data-point-quantile-values-mismatch/expected.json new file mode 100644 index 000000000000..11a71db5f19b --- /dev/null +++ b/internal/comparetest/testdata/metrics/summary-data-point-quantile-values-mismatch/expected.json @@ -0,0 +1,35 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "summary.one", + "summary": { + "dataPoints": [ + { + "quantileValues" : [ + { + "quantile": 0.5, + "value": 50 + }, + { + "quantile": 0.9, + "value": 90 + }, + { + "quantile": 0.99, + "value": 99 + } + ] + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/summary-data-point-sum-mismatch/actual.json b/internal/comparetest/testdata/metrics/summary-data-point-sum-mismatch/actual.json new file mode 100644 index 000000000000..e6a6f9a7188e --- /dev/null +++ b/internal/comparetest/testdata/metrics/summary-data-point-sum-mismatch/actual.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "summary.one", + "summary": { + "dataPoints": [ + { + "sum": 654.321000 + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/testdata/metrics/summary-data-point-sum-mismatch/expected.json b/internal/comparetest/testdata/metrics/summary-data-point-sum-mismatch/expected.json new file mode 100644 index 000000000000..52aad86874c8 --- /dev/null +++ b/internal/comparetest/testdata/metrics/summary-data-point-sum-mismatch/expected.json @@ -0,0 +1,22 @@ +{ + "resourceMetrics": [ + { + "scopeMetrics": [ + { + "metrics": [ + { + "name": "summary.one", + "summary": { + "dataPoints": [ + { + "sum": 123.456000 + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/internal/comparetest/util.go b/internal/comparetest/util.go index b225b01a46f2..fd25a93a442a 100644 --- a/internal/comparetest/util.go +++ b/internal/comparetest/util.go @@ -128,3 +128,7 @@ func sortSpanSlice(a, b ptrace.Span) bool { bAttrs := pdatautil.MapHash(b.Attributes()) return bytes.Compare(aAttrs[:], bAttrs[:]) < 0 } + +func sortSummaryDataPointValueAtQuantileSlice(a, b pmetric.SummaryDataPointValueAtQuantile) bool { + return a.Quantile() < b.Quantile() +}