From 59ad6e7dcad9c7e4ea96f5ee78476b3bf8ad123d Mon Sep 17 00:00:00 2001 From: jeremyh Date: Mon, 9 Sep 2024 17:46:27 -0400 Subject: [PATCH] add test function and data --- pkg/pdatatest/pmetrictest/metrics_test.go | 7 +++ pkg/pdatatest/pmetrictest/options.go | 51 +++++++++++++++++++ .../actual.yaml | 9 ++++ .../expected.yaml | 9 ++++ 4 files changed, 76 insertions(+) create mode 100644 pkg/pdatatest/pmetrictest/testdata/ignore-data-point-value-double-precision/actual.yaml create mode 100644 pkg/pdatatest/pmetrictest/testdata/ignore-data-point-value-double-precision/expected.yaml diff --git a/pkg/pdatatest/pmetrictest/metrics_test.go b/pkg/pdatatest/pmetrictest/metrics_test.go index d83379948dcf..6f09b1be5edc 100644 --- a/pkg/pdatatest/pmetrictest/metrics_test.go +++ b/pkg/pdatatest/pmetrictest/metrics_test.go @@ -240,6 +240,13 @@ func TestCompareMetrics(t *testing.T) { }, withoutOptions: errors.New(`resource "map[]": scope "": metric "gauge.one": datapoint "map[]": double value doesn't match expected: 123.456000, actual: 654.321000`), }, + { + name: "ignore-data-point-value-double-precision", + compareOptions: []CompareMetricsOption{ + IgnoreMetricFloatPrecision(3), + }, + withoutOptions: errors.New(`resource "map[]": scope "": metric "gauge.one": datapoint "map[]": double value doesn't match expected: 654.321110, actual: 654.321000`), + }, { name: "ignore-data-point-value-int-mismatch", compareOptions: []CompareMetricsOption{ diff --git a/pkg/pdatatest/pmetrictest/options.go b/pkg/pdatatest/pmetrictest/options.go index da983e585833..2c050536ec25 100644 --- a/pkg/pdatatest/pmetrictest/options.go +++ b/pkg/pdatatest/pmetrictest/options.go @@ -6,6 +6,7 @@ package pmetrictest // import "github.com/open-telemetry/opentelemetry-collector import ( "bytes" "fmt" + "math" "regexp" "sort" "time" @@ -110,6 +111,56 @@ func maskHistogramDataPointSliceValues(dataPoints pmetric.HistogramDataPointSlic } } +// IgnoreMetricFloatPrecision is a CompareMetricsOption that rounds away float precision discrepancies in metric values. +func IgnoreMetricFloatPrecision(precision int, metricNames ...string) CompareMetricsOption { + return compareMetricsOptionFunc(func(expected, actual pmetric.Metrics) { + floatMetricValues(precision, expected, metricNames...) + floatMetricValues(precision, actual, metricNames...) + }) +} + +func floatMetricValues(precision int, metrics pmetric.Metrics, metricNames ...string) { + rms := metrics.ResourceMetrics() + for i := 0; i < rms.Len(); i++ { + ilms := rms.At(i).ScopeMetrics() + for j := 0; j < ilms.Len(); j++ { + floatMetricSliceValues(precision, ilms.At(j).Metrics(), metricNames...) + } + } +} + +// floatMetricSliceValues sets all data point values to zero. +func floatMetricSliceValues(precision int, metrics pmetric.MetricSlice, metricNames ...string) { + metricNameSet := make(map[string]bool, len(metricNames)) + for _, metricName := range metricNames { + metricNameSet[metricName] = true + } + for i := 0; i < metrics.Len(); i++ { + if len(metricNames) == 0 || metricNameSet[metrics.At(i).Name()] { + switch metrics.At(i).Type() { + case pmetric.MetricTypeEmpty, pmetric.MetricTypeSum, pmetric.MetricTypeGauge: + roundDataPointSliceValues(getDataPointSlice(metrics.At(i)), precision) + default: + panic(fmt.Sprintf("data type not supported: %s", metrics.At(i).Type())) + } + } + } +} + +// maskDataPointSliceValues rounds all data point values at a given decimal. +func roundDataPointSliceValues(dataPoints pmetric.NumberDataPointSlice, precision int) { + for i := 0; i < dataPoints.Len(); i++ { + dataPoint := dataPoints.At(i) + factor := math.Pow(10, float64(precision)) + switch { + case dataPoint.DoubleValue() != 0.0: + dataPoint.SetDoubleValue(math.Round(dataPoint.DoubleValue()*factor) / factor) + case dataPoint.IntValue() != 0: + panic(fmt.Sprintf("integers can not have float precision ignored: %v", dataPoints.At(i))) + } + } +} + // IgnoreTimestamp is a CompareMetricsOption that clears Timestamp fields on all the data points. func IgnoreTimestamp() CompareMetricsOption { return compareMetricsOptionFunc(func(expected, actual pmetric.Metrics) { diff --git a/pkg/pdatatest/pmetrictest/testdata/ignore-data-point-value-double-precision/actual.yaml b/pkg/pdatatest/pmetrictest/testdata/ignore-data-point-value-double-precision/actual.yaml new file mode 100644 index 000000000000..046dd763e6be --- /dev/null +++ b/pkg/pdatatest/pmetrictest/testdata/ignore-data-point-value-double-precision/actual.yaml @@ -0,0 +1,9 @@ +resourceMetrics: + - resource: {} + scopeMetrics: + - metrics: + - gauge: + dataPoints: + - asDouble: 654.321 + name: gauge.one + scope: {} diff --git a/pkg/pdatatest/pmetrictest/testdata/ignore-data-point-value-double-precision/expected.yaml b/pkg/pdatatest/pmetrictest/testdata/ignore-data-point-value-double-precision/expected.yaml new file mode 100644 index 000000000000..8472ce9e9ba2 --- /dev/null +++ b/pkg/pdatatest/pmetrictest/testdata/ignore-data-point-value-double-precision/expected.yaml @@ -0,0 +1,9 @@ +resourceMetrics: + - resource: {} + scopeMetrics: + - metrics: + - gauge: + dataPoints: + - asDouble: 654.32111 + name: gauge.one + scope: {}