Skip to content

Commit

Permalink
Add helper to get a metric for componentest.Telemetry
Browse files Browse the repository at this point in the history
Signed-off-by: Bogdan Drutu <bogdandrutu@gmail.com>
  • Loading branch information
bogdandrutu committed Jan 30, 2025
1 parent c119b2a commit b7c6922
Show file tree
Hide file tree
Showing 12 changed files with 148 additions and 156 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 2 additions & 7 deletions cmd/mdatagen/internal/templates/telemetrytest.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,13 @@ func AssertEqual{{ $name.Render }}(t *testing.T, tt componenttest.Telemetry, dps
DataPoints: dps,
},
}
got := getMetric(t, tt, "otelcol_{{ $name }}")
got, err := tt.GetMetric("otelcol_{{ $name }}")
require.NoError(t, err)
metricdatatest.AssertEqual(t, want, got, opts...)
}

{{- end }}

func getMetric(t *testing.T, tt componenttest.Telemetry, name string) metricdata.Metrics {
var md metricdata.ResourceMetrics
require.NoError(t, tt.Reader.Collect(context.Background(), &md))
return getMetricFromResource(name, md)
}

func getMetricFromResource(name string, got metricdata.ResourceMetrics) metricdata.Metrics {
for _, sm := range got.ScopeMetrics {
for _, m := range sm.Metrics {
Expand Down
20 changes: 10 additions & 10 deletions component/componenttest/obsreporttest.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,55 +33,55 @@ type TestTelemetry struct {
// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead.
// CheckExporterTraces checks that for the current exported values for trace exporter metrics match given values.
func (tts *TestTelemetry) CheckExporterTraces(sentSpans, sendFailedSpans int64) error {
return checkExporterTraces(tts.Reader, tts.id, sentSpans, sendFailedSpans)
return checkExporterTraces(&tts.Telemetry, tts.id, sentSpans, sendFailedSpans)
}

// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead.
// CheckExporterMetrics checks that for the current exported values for metrics exporter metrics match given values.
func (tts *TestTelemetry) CheckExporterMetrics(sentMetricsPoints, sendFailedMetricsPoints int64) error {
return checkExporterMetrics(tts.Reader, tts.id, sentMetricsPoints, sendFailedMetricsPoints)
return checkExporterMetrics(&tts.Telemetry, tts.id, sentMetricsPoints, sendFailedMetricsPoints)
}

// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead.
func (tts *TestTelemetry) CheckExporterEnqueueFailedMetrics(enqueueFailed int64) error {
return checkExporterEnqueueFailed(tts.Reader, tts.id, "metric_points", enqueueFailed)
return checkExporterEnqueueFailed(&tts.Telemetry, tts.id, "metric_points", enqueueFailed)
}

// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead.
func (tts *TestTelemetry) CheckExporterEnqueueFailedTraces(enqueueFailed int64) error {
return checkExporterEnqueueFailed(tts.Reader, tts.id, "spans", enqueueFailed)
return checkExporterEnqueueFailed(&tts.Telemetry, tts.id, "spans", enqueueFailed)
}

// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead.
func (tts *TestTelemetry) CheckExporterEnqueueFailedLogs(enqueueFailed int64) error {
return checkExporterEnqueueFailed(tts.Reader, tts.id, "log_records", enqueueFailed)
return checkExporterEnqueueFailed(&tts.Telemetry, tts.id, "log_records", enqueueFailed)
}

// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead.
// CheckExporterLogs checks that for the current exported values for logs exporter metrics match given values.
func (tts *TestTelemetry) CheckExporterLogs(sentLogRecords, sendFailedLogRecords int64) error {
return checkExporterLogs(tts.Reader, tts.id, sentLogRecords, sendFailedLogRecords)
return checkExporterLogs(&tts.Telemetry, tts.id, sentLogRecords, sendFailedLogRecords)
}

func (tts *TestTelemetry) CheckExporterMetricGauge(metric string, val int64, extraAttrs ...attribute.KeyValue) error {
attrs := attributesForExporterMetrics(tts.id, extraAttrs...)
return checkIntGauge(tts.Reader, metric, val, attrs)
return checkIntGauge(&tts.Telemetry, metric, val, attrs)
}

// CheckReceiverTraces checks that for the current exported values for trace receiver metrics match given values.
func (tts *TestTelemetry) CheckReceiverTraces(protocol string, acceptedSpans, droppedSpans int64) error {
return checkReceiverTraces(tts.Reader, tts.id, protocol, acceptedSpans, droppedSpans)
return checkReceiverTraces(&tts.Telemetry, tts.id, protocol, acceptedSpans, droppedSpans)
}

// Deprecated: [v0.119.0] use the metadatatest.AssertEqualMetric series of functions instead.
// CheckReceiverLogs checks that for the current exported values for logs receiver metrics match given values.
func (tts *TestTelemetry) CheckReceiverLogs(protocol string, acceptedLogRecords, droppedLogRecords int64) error {
return checkReceiverLogs(tts.Reader, tts.id, protocol, acceptedLogRecords, droppedLogRecords)
return checkReceiverLogs(&tts.Telemetry, tts.id, protocol, acceptedLogRecords, droppedLogRecords)
}

// CheckReceiverMetrics checks that for the current exported values for metrics receiver metrics match given values.
func (tts *TestTelemetry) CheckReceiverMetrics(protocol string, acceptedMetricPoints, droppedMetricPoints int64) error {
return checkReceiverMetrics(tts.Reader, tts.id, protocol, acceptedMetricPoints, droppedMetricPoints)
return checkReceiverMetrics(&tts.Telemetry, tts.id, protocol, acceptedMetricPoints, droppedMetricPoints)
}

// TelemetrySettings returns the TestTelemetry's TelemetrySettings
Expand Down
74 changes: 28 additions & 46 deletions component/componenttest/otelchecker.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,68 +4,66 @@
package componenttest // import "go.opentelemetry.io/collector/component/componenttest"

import (
"context"
"fmt"

"go.opentelemetry.io/otel/attribute"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
"go.uber.org/multierr"

"go.opentelemetry.io/collector/component"
)

func checkReceiverTraces(reader *sdkmetric.ManualReader, receiver component.ID, protocol string, accepted, dropped int64) error {
return checkReceiver(reader, receiver, "spans", protocol, accepted, dropped)
func checkReceiverTraces(tel *Telemetry, receiver component.ID, protocol string, accepted, dropped int64) error {
return checkReceiver(tel, receiver, "spans", protocol, accepted, dropped)
}

func checkReceiverLogs(reader *sdkmetric.ManualReader, receiver component.ID, protocol string, accepted, dropped int64) error {
return checkReceiver(reader, receiver, "log_records", protocol, accepted, dropped)
func checkReceiverLogs(tel *Telemetry, receiver component.ID, protocol string, accepted, dropped int64) error {
return checkReceiver(tel, receiver, "log_records", protocol, accepted, dropped)
}

func checkReceiverMetrics(reader *sdkmetric.ManualReader, receiver component.ID, protocol string, accepted, dropped int64) error {
return checkReceiver(reader, receiver, "metric_points", protocol, accepted, dropped)
func checkReceiverMetrics(tel *Telemetry, receiver component.ID, protocol string, accepted, dropped int64) error {
return checkReceiver(tel, receiver, "metric_points", protocol, accepted, dropped)
}

func checkReceiver(reader *sdkmetric.ManualReader, receiver component.ID, datatype, protocol string, acceptedMetricPoints, droppedMetricPoints int64) error {
func checkReceiver(tel *Telemetry, receiver component.ID, datatype, protocol string, acceptedMetricPoints, droppedMetricPoints int64) error {
receiverAttrs := attributesForReceiverMetrics(receiver, protocol)
return multierr.Combine(
checkIntSum(reader, "otelcol_receiver_accepted_"+datatype, acceptedMetricPoints, receiverAttrs),
checkIntSum(reader, "otelcol_receiver_refused_"+datatype, droppedMetricPoints, receiverAttrs))
checkIntSum(tel, "otelcol_receiver_accepted_"+datatype, acceptedMetricPoints, receiverAttrs),
checkIntSum(tel, "otelcol_receiver_refused_"+datatype, droppedMetricPoints, receiverAttrs))
}

func checkExporterTraces(reader *sdkmetric.ManualReader, exporter component.ID, sent, sendFailed int64) error {
return checkExporter(reader, exporter, "spans", sent, sendFailed)
func checkExporterTraces(tel *Telemetry, exporter component.ID, sent, sendFailed int64) error {
return checkExporter(tel, exporter, "spans", sent, sendFailed)
}

func checkExporterLogs(reader *sdkmetric.ManualReader, exporter component.ID, sent, sendFailed int64) error {
return checkExporter(reader, exporter, "log_records", sent, sendFailed)
func checkExporterLogs(tel *Telemetry, exporter component.ID, sent, sendFailed int64) error {
return checkExporter(tel, exporter, "log_records", sent, sendFailed)
}

func checkExporterMetrics(reader *sdkmetric.ManualReader, exporter component.ID, sent, sendFailed int64) error {
return checkExporter(reader, exporter, "metric_points", sent, sendFailed)
func checkExporterMetrics(tel *Telemetry, exporter component.ID, sent, sendFailed int64) error {
return checkExporter(tel, exporter, "metric_points", sent, sendFailed)
}

func checkExporter(reader *sdkmetric.ManualReader, exporter component.ID, datatype string, sent, sendFailed int64) error {
func checkExporter(tel *Telemetry, exporter component.ID, datatype string, sent, sendFailed int64) error {
exporterAttrs := attributesForExporterMetrics(exporter)
errs := checkIntSum(reader, "otelcol_exporter_sent_"+datatype, sent, exporterAttrs)
errs := checkIntSum(tel, "otelcol_exporter_sent_"+datatype, sent, exporterAttrs)
if sendFailed > 0 {
errs = multierr.Append(errs,
checkIntSum(reader, "otelcol_exporter_send_failed_"+datatype, sendFailed, exporterAttrs))
checkIntSum(tel, "otelcol_exporter_send_failed_"+datatype, sendFailed, exporterAttrs))
}
return errs
}

func checkExporterEnqueueFailed(reader *sdkmetric.ManualReader, exporter component.ID, datatype string, enqueueFailed int64) error {
func checkExporterEnqueueFailed(tel *Telemetry, exporter component.ID, datatype string, enqueueFailed int64) error {
if enqueueFailed == 0 {
return nil
}
exporterAttrs := attributesForExporterMetrics(exporter)
return checkIntSum(reader, "otelcol_exporter_enqueue_failed_"+datatype, enqueueFailed, exporterAttrs)
return checkIntSum(tel, "otelcol_exporter_enqueue_failed_"+datatype, enqueueFailed, exporterAttrs)
}

func checkIntGauge(reader *sdkmetric.ManualReader, metric string, expected int64, expectedAttrs attribute.Set) error {
dp, err := getGaugeDataPoint[int64](reader, metric, expectedAttrs)
func checkIntGauge(tel *Telemetry, metric string, expected int64, expectedAttrs attribute.Set) error {
dp, err := getGaugeDataPoint[int64](tel, metric, expectedAttrs)
if err != nil {
return err
}
Expand All @@ -77,8 +75,8 @@ func checkIntGauge(reader *sdkmetric.ManualReader, metric string, expected int64
return nil
}

func checkIntSum(reader *sdkmetric.ManualReader, expectedMetric string, expected int64, expectedAttrs attribute.Set) error {
dp, err := getSumDataPoint[int64](reader, expectedMetric, expectedAttrs)
func checkIntSum(tel *Telemetry, expectedMetric string, expected int64, expectedAttrs attribute.Set) error {
dp, err := getSumDataPoint[int64](tel, expectedMetric, expectedAttrs)
if err != nil {
return err
}
Expand All @@ -90,8 +88,8 @@ func checkIntSum(reader *sdkmetric.ManualReader, expectedMetric string, expected
return nil
}

func getSumDataPoint[N int64 | float64](reader *sdkmetric.ManualReader, expectedName string, expectedAttrs attribute.Set) (metricdata.DataPoint[N], error) {
m, err := getMetric(reader, expectedName)
func getSumDataPoint[N int64 | float64](tel *Telemetry, expectedName string, expectedAttrs attribute.Set) (metricdata.DataPoint[N], error) {
m, err := tel.GetMetric(expectedName)
if err != nil {
return metricdata.DataPoint[N]{}, err
}
Expand All @@ -104,8 +102,8 @@ func getSumDataPoint[N int64 | float64](reader *sdkmetric.ManualReader, expected
}
}

func getGaugeDataPoint[N int64 | float64](reader *sdkmetric.ManualReader, expectedName string, expectedAttrs attribute.Set) (metricdata.DataPoint[N], error) {
m, err := getMetric(reader, expectedName)
func getGaugeDataPoint[N int64 | float64](tel *Telemetry, expectedName string, expectedAttrs attribute.Set) (metricdata.DataPoint[N], error) {
m, err := tel.GetMetric(expectedName)
if err != nil {
return metricdata.DataPoint[N]{}, err
}
Expand All @@ -127,22 +125,6 @@ func getDataPoint[N int64 | float64](dps []metricdata.DataPoint[N], expectedName
return metricdata.DataPoint[N]{}, fmt.Errorf("metric '%s' doesn't have a data point with the given attributes: %s", expectedName, expectedAttrs.Encoded(attribute.DefaultEncoder()))
}

func getMetric(reader *sdkmetric.ManualReader, expectedName string) (metricdata.Metrics, error) {
var rm metricdata.ResourceMetrics
if err := reader.Collect(context.Background(), &rm); err != nil {
return metricdata.Metrics{}, err
}

for _, sm := range rm.ScopeMetrics {
for _, m := range sm.Metrics {
if m.Name == expectedName {
return m, nil
}
}
}
return metricdata.Metrics{}, fmt.Errorf("metric '%s' not found", expectedName)
}

// attributesForReceiverMetrics returns the attributes that are needed for the receiver metrics.
func attributesForReceiverMetrics(receiver component.ID, transport string) attribute.Set {
return attribute.NewSet(
Expand Down
18 changes: 18 additions & 0 deletions component/componenttest/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ package componenttest // import "go.opentelemetry.io/collector/component/compone
import (
"context"
"errors"
"fmt"

sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/sdk/trace/tracetest"

Expand Down Expand Up @@ -73,6 +75,22 @@ func (tt *Telemetry) NewTelemetrySettings() component.TelemetrySettings {
return set
}

func (tt *Telemetry) GetMetric(name string) (metricdata.Metrics, error) {
var rm metricdata.ResourceMetrics
if err := tt.Reader.Collect(context.Background(), &rm); err != nil {
return metricdata.Metrics{}, err
}

for _, sm := range rm.ScopeMetrics {
for _, m := range sm.Metrics {
if m.Name == name {
return m, nil
}
}
}
return metricdata.Metrics{}, fmt.Errorf("metric '%s' not found", name)
}

func (tt *Telemetry) Shutdown(ctx context.Context) error {
return errors.Join(
tt.meterProvider.Shutdown(ctx),
Expand Down
Loading

0 comments on commit b7c6922

Please sign in to comment.