From 16ce491d38237ce273ff1b2ff08defdd604bad90 Mon Sep 17 00:00:00 2001
From: Tyler Yahn <MrAlias@users.noreply.github.com>
Date: Fri, 18 Aug 2023 06:43:09 -0700
Subject: [PATCH] Fix guard of measured value to not record empty (#4452)

A guard was added in #4446 to prevent non-normal float64 from being
recorded. This was added in the low-level `record` method meaning that
the higher-level `measure` method will still keep a record of the
invalid value measurement, just with a zero-value.

This fixes that issue by moving the guard to the `measure` method.
---
 .../aggregate/exponential_histogram.go         | 10 +++++-----
 .../aggregate/exponential_histogram_test.go    | 18 ++++++++++--------
 2 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/sdk/metric/internal/aggregate/exponential_histogram.go b/sdk/metric/internal/aggregate/exponential_histogram.go
index e9ba04eea5e..368f0027ec3 100644
--- a/sdk/metric/internal/aggregate/exponential_histogram.go
+++ b/sdk/metric/internal/aggregate/exponential_histogram.go
@@ -76,11 +76,6 @@ func newExpoHistogramDataPoint[N int64 | float64](maxSize, maxScale int, noMinMa
 
 // record adds a new measurement to the histogram. It will rescale the buckets if needed.
 func (p *expoHistogramDataPoint[N]) record(v N) {
-	// Ignore NaN and infinity.
-	if math.IsInf(float64(v), 0) || math.IsNaN(float64(v)) {
-		return
-	}
-
 	p.count++
 
 	if !p.noMinMax {
@@ -321,6 +316,11 @@ type expoHistogram[N int64 | float64] struct {
 }
 
 func (e *expoHistogram[N]) measure(_ context.Context, value N, attr attribute.Set) {
+	// Ignore NaN and infinity.
+	if math.IsInf(float64(value), 0) || math.IsNaN(float64(value)) {
+		return
+	}
+
 	e.valuesMu.Lock()
 	defer e.valuesMu.Unlock()
 
diff --git a/sdk/metric/internal/aggregate/exponential_histogram_test.go b/sdk/metric/internal/aggregate/exponential_histogram_test.go
index 040370d4729..cac734c9312 100644
--- a/sdk/metric/internal/aggregate/exponential_histogram_test.go
+++ b/sdk/metric/internal/aggregate/exponential_histogram_test.go
@@ -45,10 +45,10 @@ func withHandler(t *testing.T) func() {
 
 func TestExpoHistogramDataPointRecord(t *testing.T) {
 	t.Run("float64", testExpoHistogramDataPointRecord[float64])
-	t.Run("float64 MinMaxSum", testExpoHistogramDataPointRecordMinMaxSumFloat64)
+	t.Run("float64 MinMaxSum", testExpoHistogramMinMaxSumFloat64)
 	t.Run("float64-2", testExpoHistogramDataPointRecordFloat64)
 	t.Run("int64", testExpoHistogramDataPointRecord[int64])
-	t.Run("int64 MinMaxSum", testExpoHistogramDataPointRecordMinMaxSumInt64)
+	t.Run("int64 MinMaxSum", testExpoHistogramMinMaxSumInt64)
 }
 
 // TODO: This can be defined in the test after we drop support for go1.19.
@@ -171,7 +171,7 @@ type expoHistogramDataPointRecordMinMaxSumTestCase[N int64 | float64] struct {
 	expected expectedMinMaxSum[N]
 }
 
-func testExpoHistogramDataPointRecordMinMaxSumInt64(t *testing.T) {
+func testExpoHistogramMinMaxSumInt64(t *testing.T) {
 	testCases := []expoHistogramDataPointRecordMinMaxSumTestCase[int64]{
 		{
 			values:   []int64{2, 4, 1},
@@ -188,10 +188,11 @@ func testExpoHistogramDataPointRecordMinMaxSumInt64(t *testing.T) {
 			restore := withHandler(t)
 			defer restore()
 
-			dp := newExpoHistogramDataPoint[int64](4, 20, false, false)
+			h := newExponentialHistogram[int64](4, 20, false, false)
 			for _, v := range tt.values {
-				dp.record(v)
+				h.measure(context.Background(), v, alice)
 			}
+			dp := h.values[alice]
 
 			assert.Equal(t, tt.expected.max, dp.max)
 			assert.Equal(t, tt.expected.min, dp.min)
@@ -200,7 +201,7 @@ func testExpoHistogramDataPointRecordMinMaxSumInt64(t *testing.T) {
 	}
 }
 
-func testExpoHistogramDataPointRecordMinMaxSumFloat64(t *testing.T) {
+func testExpoHistogramMinMaxSumFloat64(t *testing.T) {
 	testCases := []expoHistogramDataPointRecordMinMaxSumTestCase[float64]{
 		{
 			values:   []float64{2, 4, 1},
@@ -229,10 +230,11 @@ func testExpoHistogramDataPointRecordMinMaxSumFloat64(t *testing.T) {
 			restore := withHandler(t)
 			defer restore()
 
-			dp := newExpoHistogramDataPoint[float64](4, 20, false, false)
+			h := newExponentialHistogram[float64](4, 20, false, false)
 			for _, v := range tt.values {
-				dp.record(v)
+				h.measure(context.Background(), v, alice)
 			}
+			dp := h.values[alice]
 
 			assert.Equal(t, tt.expected.max, dp.max)
 			assert.Equal(t, tt.expected.min, dp.min)