From 128b385f48c2f3d3e726a23edc57ae52a71bcf62 Mon Sep 17 00:00:00 2001 From: Jeff Dupont Date: Tue, 16 Sep 2025 09:37:14 -0700 Subject: [PATCH 1/5] added a find metric helper, useful for testing --- otmetric/find.go | 47 ++++++++++++++++++++++++++++++++++++++++ otmetric/find_test.go | 50 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 otmetric/find.go create mode 100644 otmetric/find_test.go diff --git a/otmetric/find.go b/otmetric/find.go new file mode 100644 index 0000000..0a29544 --- /dev/null +++ b/otmetric/find.go @@ -0,0 +1,47 @@ +package otmetric + +import ( + "context" + "fmt" + + "go.opentelemetry.io/otel/attribute" + otsdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" +) + +// FindMetricVal returns the current value of a [metricName] from the [ManualReader]. +func FindMetricVal[V int64 | float64](ctx context.Context, r *otsdkmetric.ManualReader, metricName string, kvs attribute.Set) (V, error) { + var zv V + res := metricdata.ResourceMetrics{} + if err := r.Collect(ctx, &res); err != nil { + return zv, err + } + + for _, sm := range res.ScopeMetrics { + for _, m := range sm.Metrics { + if m.Name != metricName { + continue + } + switch vs := m.Data.(type) { + case metricdata.Gauge[V]: + for _, d := range vs.DataPoints { + if !kvs.Equals(&d.Attributes) { + continue + } + return d.Value, nil + } + case metricdata.Sum[V]: + for _, d := range vs.DataPoints { + if !kvs.Equals(&d.Attributes) { + continue + } + return d.Value, nil + } + default: + // wrong metric-type (or histogram, which we'll have to implement later) + continue + } + } + } + return zv, fmt.Errorf("metric %s not found", metricName) +} diff --git a/otmetric/find_test.go b/otmetric/find_test.go new file mode 100644 index 0000000..b4ef5b5 --- /dev/null +++ b/otmetric/find_test.go @@ -0,0 +1,50 @@ +package otmetric + +import ( + "context" + "testing" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" + otsdkmetric "go.opentelemetry.io/otel/sdk/metric" +) + +func TestFindMetricVal(t *testing.T) { + ctx := context.Background() + + r := otsdkmetric.NewManualReader() + mp := otsdkmetric.NewMeterProvider(otsdkmetric.WithReader(r)) + + otM := mp.Meter("foobar") + attrSet := attribute.NewSet(attribute.String("fizzlebit", "foobar"), attribute.String("ouch", "icky")) + + // read an int64 counter + counter, countErr := otM.Int64Counter("a_counter_int") + if countErr != nil { + t.Fatalf("failed to register counter metric: %s", countErr) + } + counter.Add(ctx, 2, metric.WithAttributeSet(attrSet)) + + counterVal, counterValErr := FindMetricVal[int64](ctx, r, "a_counter_int", attrSet) + if counterValErr != nil { + t.Errorf("failed to fetch counter metric value: %s", counterValErr) + } + if counterVal != 2 { + t.Errorf("unexpected counter metric value: want %d; got %d", 2, counterVal) + } + + // read an int64 gauge + gauge, gaugeErr := otM.Int64Gauge("a_gauge_int") + if gaugeErr != nil { + t.Fatalf("failed to register gauge metric: %s", gaugeErr) + } + gauge.Record(ctx, 3, metric.WithAttributeSet(attrSet)) + + gaugeVal, gaugeValErr := FindMetricVal[int64](ctx, r, "a_gauge_int", attrSet) + if gaugeValErr != nil { + t.Errorf("failed to fetch gauge metric value: %s", gaugeValErr) + } + if gaugeVal != 3 { + t.Errorf("unexpected gauge metric value: want %d; got %d", 3, gaugeVal) + } +} From 1ee8d7b4abce9e60fd5f109c38031d767060607e Mon Sep 17 00:00:00 2001 From: Jeff Dupont Date: Tue, 16 Sep 2025 13:06:58 -0700 Subject: [PATCH 2/5] updated the doc comment and renamed the package --- {otmetric => otmetricreader}/find.go | 12 ++++++++++-- {otmetric => otmetricreader}/find_test.go | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) rename {otmetric => otmetricreader}/find.go (61%) rename {otmetric => otmetricreader}/find_test.go (89%) diff --git a/otmetric/find.go b/otmetricreader/find.go similarity index 61% rename from otmetric/find.go rename to otmetricreader/find.go index 0a29544..393bee9 100644 --- a/otmetric/find.go +++ b/otmetricreader/find.go @@ -9,8 +9,16 @@ import ( "go.opentelemetry.io/otel/sdk/metric/metricdata" ) -// FindMetricVal returns the current value of a [metricName] from the [ManualReader]. -func FindMetricVal[V int64 | float64](ctx context.Context, r *otsdkmetric.ManualReader, metricName string, kvs attribute.Set) (V, error) { +// FindVal is a testing utility to find the value of a specific metric +// collected by the sdk metric.ManualReader. +// +// It searches for a metric matching the provided metricName and attribute.Set. +// The type parameter V specifies the expected value type, which must be +// either int64 or float64. +// +// An error is returned if a metric matching the name and attributes is not found, +// or if the found metric's value type does not match V. +func FindVal[V int64 | float64](ctx context.Context, r *otsdkmetric.ManualReader, metricName string, kvs attribute.Set) (V, error) { var zv V res := metricdata.ResourceMetrics{} if err := r.Collect(ctx, &res); err != nil { diff --git a/otmetric/find_test.go b/otmetricreader/find_test.go similarity index 89% rename from otmetric/find_test.go rename to otmetricreader/find_test.go index b4ef5b5..62d046f 100644 --- a/otmetric/find_test.go +++ b/otmetricreader/find_test.go @@ -25,7 +25,7 @@ func TestFindMetricVal(t *testing.T) { } counter.Add(ctx, 2, metric.WithAttributeSet(attrSet)) - counterVal, counterValErr := FindMetricVal[int64](ctx, r, "a_counter_int", attrSet) + counterVal, counterValErr := FindVal[int64](ctx, r, "a_counter_int", attrSet) if counterValErr != nil { t.Errorf("failed to fetch counter metric value: %s", counterValErr) } @@ -40,7 +40,7 @@ func TestFindMetricVal(t *testing.T) { } gauge.Record(ctx, 3, metric.WithAttributeSet(attrSet)) - gaugeVal, gaugeValErr := FindMetricVal[int64](ctx, r, "a_gauge_int", attrSet) + gaugeVal, gaugeValErr := FindVal[int64](ctx, r, "a_gauge_int", attrSet) if gaugeValErr != nil { t.Errorf("failed to fetch gauge metric value: %s", gaugeValErr) } From 3efac367b2e948d46bffe9546d7c908cb19e1689 Mon Sep 17 00:00:00 2001 From: Jeff Dupont Date: Tue, 16 Sep 2025 13:30:22 -0700 Subject: [PATCH 3/5] Update otmetricreader/find.go Co-authored-by: dfinkel --- otmetricreader/find.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/otmetricreader/find.go b/otmetricreader/find.go index 393bee9..b0a0724 100644 --- a/otmetricreader/find.go +++ b/otmetricreader/find.go @@ -10,7 +10,7 @@ import ( ) // FindVal is a testing utility to find the value of a specific metric -// collected by the sdk metric.ManualReader. +// collected by the sdk [metric.ManualReader]. // // It searches for a metric matching the provided metricName and attribute.Set. // The type parameter V specifies the expected value type, which must be From 841175416e8d629517fc8b7742eb296a23c7e0e6 Mon Sep 17 00:00:00 2001 From: Jeff Dupont Date: Tue, 16 Sep 2025 13:30:27 -0700 Subject: [PATCH 4/5] Update otmetricreader/find.go Co-authored-by: dfinkel --- otmetricreader/find.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/otmetricreader/find.go b/otmetricreader/find.go index b0a0724..889ab6c 100644 --- a/otmetricreader/find.go +++ b/otmetricreader/find.go @@ -12,7 +12,7 @@ import ( // FindVal is a testing utility to find the value of a specific metric // collected by the sdk [metric.ManualReader]. // -// It searches for a metric matching the provided metricName and attribute.Set. +// It searches for a metric matching the provided metricName and [attribute.Set]. // The type parameter V specifies the expected value type, which must be // either int64 or float64. // From 2ec2de225a7ce4965f71d196352129ba94c4e698 Mon Sep 17 00:00:00 2001 From: Jeff Dupont Date: Tue, 16 Sep 2025 13:35:36 -0700 Subject: [PATCH 5/5] corrected the package name to match the directory leaf --- otmetricreader/find.go | 2 +- otmetricreader/find_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/otmetricreader/find.go b/otmetricreader/find.go index 889ab6c..18df6b8 100644 --- a/otmetricreader/find.go +++ b/otmetricreader/find.go @@ -1,4 +1,4 @@ -package otmetric +package otmetricreader import ( "context" diff --git a/otmetricreader/find_test.go b/otmetricreader/find_test.go index 62d046f..a32e8d4 100644 --- a/otmetricreader/find_test.go +++ b/otmetricreader/find_test.go @@ -1,4 +1,4 @@ -package otmetric +package otmetricreader import ( "context"