Skip to content

Commit 6d1bbf9

Browse files
committed
feat(metric): use metricdata for unit tests
1 parent 624bb6c commit 6d1bbf9

File tree

6 files changed

+1386
-27
lines changed

6 files changed

+1386
-27
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package metrics
18+
19+
import (
20+
"context"
21+
"testing"
22+
23+
"go.opentelemetry.io/otel/attribute"
24+
"go.opentelemetry.io/otel/metric"
25+
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
26+
"go.opentelemetry.io/otel/sdk/metric/metricdata"
27+
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
28+
29+
otelutil "k8s.io/node-problem-detector/pkg/util/otel"
30+
)
31+
32+
func TestFloat64GaugeSetValueSemantics(t *testing.T) {
33+
// Set up SDK with ManualReader for testing
34+
reader := sdkmetric.NewManualReader()
35+
provider := sdkmetric.NewMeterProvider(
36+
sdkmetric.WithResource(otelutil.GetResource()),
37+
sdkmetric.WithReader(reader),
38+
)
39+
meter := provider.Meter("test")
40+
41+
// Create a gauge metric
42+
gauge, err := meter.Float64Gauge("test_float_gauge",
43+
metric.WithDescription("Test float64 gauge metric"),
44+
metric.WithUnit("percent"),
45+
)
46+
if err != nil {
47+
t.Fatalf("Failed to create gauge metric: %v", err)
48+
}
49+
50+
ctx := context.Background()
51+
attrs := []attribute.KeyValue{
52+
attribute.String("component", "cpu"),
53+
attribute.String("state", "usage"),
54+
}
55+
56+
// Set initial value to 0.0 (initialization)
57+
gauge.Record(ctx, 0.0, metric.WithAttributes(attrs...))
58+
59+
// Set value to 42.5 (current reading)
60+
gauge.Record(ctx, 42.5, metric.WithAttributes(attrs...))
61+
62+
// Collect metrics and verify gauge shows the last value (42.5)
63+
var rm metricdata.ResourceMetrics
64+
if err := reader.Collect(ctx, &rm); err != nil {
65+
t.Fatalf("Failed to collect metrics: %v", err)
66+
}
67+
68+
expected := metricdata.Metrics{
69+
Name: "test_float_gauge",
70+
Description: "Test float64 gauge metric",
71+
Unit: "percent",
72+
Data: metricdata.Gauge[float64]{
73+
DataPoints: []metricdata.DataPoint[float64]{
74+
{
75+
Attributes: attribute.NewSet(attrs...),
76+
Value: 42.5,
77+
},
78+
},
79+
},
80+
}
81+
82+
metricdatatest.AssertEqual(t, expected, rm.ScopeMetrics[0].Metrics[0], metricdatatest.IgnoreTimestamp())
83+
84+
// Set value to 15.3 (new reading)
85+
gauge.Record(ctx, 15.3, metric.WithAttributes(attrs...))
86+
87+
// Collect again and verify gauge now shows 15.3
88+
rm = metricdata.ResourceMetrics{}
89+
if err := reader.Collect(ctx, &rm); err != nil {
90+
t.Fatalf("Failed to collect metrics: %v", err)
91+
}
92+
93+
expected.Data = metricdata.Gauge[float64]{
94+
DataPoints: []metricdata.DataPoint[float64]{
95+
{
96+
Attributes: attribute.NewSet(attrs...),
97+
Value: 15.3,
98+
},
99+
},
100+
}
101+
102+
metricdatatest.AssertEqual(t, expected, rm.ScopeMetrics[0].Metrics[0], metricdatatest.IgnoreTimestamp())
103+
}
104+
105+
func TestFloat64CounterAddSemantics(t *testing.T) {
106+
// Set up SDK with ManualReader for testing
107+
reader := sdkmetric.NewManualReader()
108+
provider := sdkmetric.NewMeterProvider(
109+
sdkmetric.WithResource(otelutil.GetResource()),
110+
sdkmetric.WithReader(reader),
111+
)
112+
meter := provider.Meter("test")
113+
114+
// Create a counter metric
115+
counter, err := meter.Float64Counter("test_float_counter",
116+
metric.WithDescription("Test float64 counter metric"),
117+
metric.WithUnit("bytes"),
118+
)
119+
if err != nil {
120+
t.Fatalf("Failed to create counter metric: %v", err)
121+
}
122+
123+
ctx := context.Background()
124+
attrs := []attribute.KeyValue{
125+
attribute.String("operation", "read"),
126+
}
127+
128+
// Add to counter multiple times with fractional values
129+
counter.Add(ctx, 1024.5, metric.WithAttributes(attrs...))
130+
counter.Add(ctx, 2048.75, metric.WithAttributes(attrs...))
131+
132+
// Collect metrics and verify counter accumulated the sum
133+
var rm metricdata.ResourceMetrics
134+
if err := reader.Collect(ctx, &rm); err != nil {
135+
t.Fatalf("Failed to collect metrics: %v", err)
136+
}
137+
138+
expected := metricdata.Metrics{
139+
Name: "test_float_counter",
140+
Description: "Test float64 counter metric",
141+
Unit: "bytes",
142+
Data: metricdata.Sum[float64]{
143+
Temporality: metricdata.CumulativeTemporality,
144+
IsMonotonic: true,
145+
DataPoints: []metricdata.DataPoint[float64]{
146+
{
147+
Attributes: attribute.NewSet(attrs...),
148+
Value: 3073.25, // 1024.5 + 2048.75
149+
},
150+
},
151+
},
152+
}
153+
154+
metricdatatest.AssertEqual(t, expected, rm.ScopeMetrics[0].Metrics[0], metricdatatest.IgnoreTimestamp())
155+
}

pkg/util/metrics/metric_int64_test.go

Lines changed: 106 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,60 +17,139 @@ limitations under the License.
1717
package metrics
1818

1919
import (
20+
"context"
2021
"testing"
22+
23+
"go.opentelemetry.io/otel/attribute"
24+
"go.opentelemetry.io/otel/metric"
25+
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
26+
"go.opentelemetry.io/otel/sdk/metric/metricdata"
27+
"go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest"
28+
29+
otelutil "k8s.io/node-problem-detector/pkg/util/otel"
2130
)
2231

2332
func TestGaugeSetValueSemantics(t *testing.T) {
33+
// Set up SDK with ManualReader for testing
34+
reader := sdkmetric.NewManualReader()
35+
provider := sdkmetric.NewMeterProvider(
36+
sdkmetric.WithResource(otelutil.GetResource()),
37+
sdkmetric.WithReader(reader),
38+
)
39+
meter := provider.Meter("test")
40+
2441
// Create a gauge metric
25-
gauge, err := NewInt64Metric("test_gauge", "test_gauge", "Test gauge metric", "1", LastValue, []string{"reason", "type"})
42+
gauge, err := meter.Int64Gauge("test_gauge",
43+
metric.WithDescription("Test gauge metric"),
44+
metric.WithUnit("1"),
45+
)
2646
if err != nil {
2747
t.Fatalf("Failed to create gauge metric: %v", err)
2848
}
2949

30-
// Set initial value to 0 (initialization)
31-
labels1 := map[string]string{"reason": "TestReason", "type": "TestType"}
32-
err = gauge.Record(labels1, 0)
33-
if err != nil {
34-
t.Fatalf("Failed to record initial value: %v", err)
50+
ctx := context.Background()
51+
attrs1 := []attribute.KeyValue{
52+
attribute.String("reason", "TestReason"),
53+
attribute.String("type", "TestType"),
3554
}
3655

56+
// Set initial value to 0 (initialization)
57+
gauge.Record(ctx, 0, metric.WithAttributes(attrs1...))
58+
3759
// Set value to 1 (problem detected)
38-
err = gauge.Record(labels1, 1)
39-
if err != nil {
40-
t.Fatalf("Failed to record updated value: %v", err)
60+
gauge.Record(ctx, 1, metric.WithAttributes(attrs1...))
61+
62+
// Collect metrics and verify gauge shows the last value (1)
63+
var rm metricdata.ResourceMetrics
64+
if err := reader.Collect(ctx, &rm); err != nil {
65+
t.Fatalf("Failed to collect metrics: %v", err)
4166
}
4267

68+
expected := metricdata.Metrics{
69+
Name: "test_gauge",
70+
Description: "Test gauge metric",
71+
Unit: "1",
72+
Data: metricdata.Gauge[int64]{
73+
DataPoints: []metricdata.DataPoint[int64]{
74+
{
75+
Attributes: attribute.NewSet(attrs1...),
76+
Value: 1,
77+
},
78+
},
79+
},
80+
}
81+
82+
metricdatatest.AssertEqual(t, expected, rm.ScopeMetrics[0].Metrics[0], metricdatatest.IgnoreTimestamp())
83+
4384
// Set value back to 0 (problem resolved)
44-
err = gauge.Record(labels1, 0)
45-
if err != nil {
46-
t.Fatalf("Failed to record resolved value: %v", err)
85+
gauge.Record(ctx, 0, metric.WithAttributes(attrs1...))
86+
87+
// Collect again and verify gauge now shows 0
88+
rm = metricdata.ResourceMetrics{}
89+
if err := reader.Collect(ctx, &rm); err != nil {
90+
t.Fatalf("Failed to collect metrics: %v", err)
4791
}
4892

49-
// Test with different labels
50-
labels2 := map[string]string{"reason": "AnotherReason", "type": "TestType"}
51-
err = gauge.Record(labels2, 0)
52-
if err != nil {
53-
t.Fatalf("Failed to record value for different labels: %v", err)
93+
expected.Data = metricdata.Gauge[int64]{
94+
DataPoints: []metricdata.DataPoint[int64]{
95+
{
96+
Attributes: attribute.NewSet(attrs1...),
97+
Value: 0,
98+
},
99+
},
54100
}
101+
102+
metricdatatest.AssertEqual(t, expected, rm.ScopeMetrics[0].Metrics[0], metricdatatest.IgnoreTimestamp())
55103
}
56104

57105
func TestCounterAddSemantics(t *testing.T) {
106+
// Set up SDK with ManualReader for testing
107+
reader := sdkmetric.NewManualReader()
108+
provider := sdkmetric.NewMeterProvider(
109+
sdkmetric.WithResource(otelutil.GetResource()),
110+
sdkmetric.WithReader(reader),
111+
)
112+
meter := provider.Meter("test")
113+
58114
// Create a counter metric
59-
counter, err := NewInt64Metric("test_counter", "test_counter", "Test counter metric", "1", Sum, []string{"reason"})
115+
counter, err := meter.Int64Counter("test_counter",
116+
metric.WithDescription("Test counter metric"),
117+
metric.WithUnit("1"),
118+
)
60119
if err != nil {
61120
t.Fatalf("Failed to create counter metric: %v", err)
62121
}
63122

64-
// Initialize counter to 0
65-
labels := map[string]string{"reason": "TestReason"}
66-
err = counter.Record(labels, 0)
67-
if err != nil {
68-
t.Fatalf("Failed to record initial value: %v", err)
123+
ctx := context.Background()
124+
attrs := []attribute.KeyValue{
125+
attribute.String("reason", "TestReason"),
69126
}
70127

71-
// Increment counter
72-
err = counter.Record(labels, 1)
73-
if err != nil {
74-
t.Fatalf("Failed to increment counter: %v", err)
128+
// Add to counter twice
129+
counter.Add(ctx, 5, metric.WithAttributes(attrs...))
130+
counter.Add(ctx, 3, metric.WithAttributes(attrs...))
131+
132+
// Collect metrics and verify counter accumulated the sum
133+
var rm metricdata.ResourceMetrics
134+
if err := reader.Collect(ctx, &rm); err != nil {
135+
t.Fatalf("Failed to collect metrics: %v", err)
75136
}
137+
138+
expected := metricdata.Metrics{
139+
Name: "test_counter",
140+
Description: "Test counter metric",
141+
Unit: "1",
142+
Data: metricdata.Sum[int64]{
143+
Temporality: metricdata.CumulativeTemporality,
144+
IsMonotonic: true,
145+
DataPoints: []metricdata.DataPoint[int64]{
146+
{
147+
Attributes: attribute.NewSet(attrs...),
148+
Value: 8, // 5 + 3
149+
},
150+
},
151+
},
152+
}
153+
154+
metricdatatest.AssertEqual(t, expected, rm.ScopeMetrics[0].Metrics[0], metricdatatest.IgnoreTimestamp())
76155
}

vendor/go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest/README.md

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)