diff --git a/.chloggen/dep-comp-test.yaml b/.chloggen/dep-comp-test.yaml new file mode 100644 index 00000000000..c2f0b62c0cc --- /dev/null +++ b/.chloggen/dep-comp-test.yaml @@ -0,0 +1,25 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: deprecation + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: mdatagen + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Deprecate component_test in favor of metadatatest + +# One or more tracking issues or pull requests related to the change +issues: [11812] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: + +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [api] diff --git a/cmd/mdatagen/internal/command.go b/cmd/mdatagen/internal/command.go index 9d64f4492af..2f2ba19e287 100644 --- a/cmd/mdatagen/internal/command.go +++ b/cmd/mdatagen/internal/command.go @@ -78,6 +78,10 @@ func run(ymlPath string) error { if err = os.MkdirAll(codeDir, 0700); err != nil { return fmt.Errorf("unable to create output directory %q: %w", codeDir, err) } + testDir := filepath.Join(ymlDir, "internal", md.GeneratedPackageName+"test") + if err = os.MkdirAll(testDir, 0700); err != nil { + return fmt.Errorf("unable to create output test directory %q: %w", codeDir, err) + } if md.Status != nil { if md.Status.Class != "cmd" && md.Status.Class != "pkg" && !md.Status.NotComponent { if err = generateFile(filepath.Join(tmplDir, "status.go.tmpl"), @@ -114,6 +118,8 @@ func run(ymlPath string) error { } toGenerate[filepath.Join(tmplDir, "telemetry.go.tmpl")] = filepath.Join(codeDir, "generated_telemetry.go") toGenerate[filepath.Join(tmplDir, "telemetry_test.go.tmpl")] = filepath.Join(codeDir, "generated_telemetry_test.go") + toGenerate[filepath.Join(tmplDir, "telemetrytest.go.tmpl")] = filepath.Join(testDir, "generated_telemetrytest.go") + toGenerate[filepath.Join(tmplDir, "telemetrytest_test.go.tmpl")] = filepath.Join(testDir, "generated_telemetrytest_test.go") } if len(md.Metrics) != 0 || len(md.Telemetry.Metrics) != 0 || len(md.ResourceAttributes) != 0 { // if there's metrics or internal metrics, generate documentation for them diff --git a/cmd/mdatagen/internal/embedded_templates_test.go b/cmd/mdatagen/internal/embedded_templates_test.go index 5ffdc562c13..f521a083cf5 100644 --- a/cmd/mdatagen/internal/embedded_templates_test.go +++ b/cmd/mdatagen/internal/embedded_templates_test.go @@ -36,6 +36,8 @@ func TestEnsureTemplatesLoaded(t *testing.T) { path.Join(rootDir, "telemetry.go.tmpl"): {}, path.Join(rootDir, "telemetry_test.go.tmpl"): {}, path.Join(rootDir, "testdata", "config.yaml.tmpl"): {}, + path.Join(rootDir, "telemetrytest.go.tmpl"): {}, + path.Join(rootDir, "telemetrytest_test.go.tmpl"): {}, } count = 0 ) diff --git a/cmd/mdatagen/internal/samplereceiver/generated_component_telemetry_test.go b/cmd/mdatagen/internal/samplereceiver/generated_component_telemetry_test.go index 6077e61cd02..d7bf3b465f4 100644 --- a/cmd/mdatagen/internal/samplereceiver/generated_component_telemetry_test.go +++ b/cmd/mdatagen/internal/samplereceiver/generated_component_telemetry_test.go @@ -18,6 +18,7 @@ import ( "go.opentelemetry.io/collector/receiver/receivertest" ) +// Deprecated: [v0.116.0] use metadatatest.TestTelemetry type componentTestTelemetry struct { reader *sdkmetric.ManualReader meterProvider *sdkmetric.MeterProvider @@ -37,6 +38,7 @@ func (tt *componentTestTelemetry) newTelemetrySettings() component.TelemetrySett return set } +// Deprecated: [v0.116.0] use metadatatest.SetupTestTelemetry func setupTestTelemetry() componentTestTelemetry { reader := sdkmetric.NewManualReader() return componentTestTelemetry{ diff --git a/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry.go b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry.go index 71d4e1e78d6..003b313cfab 100644 --- a/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry.go +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadata/generated_telemetry.go @@ -7,7 +7,7 @@ import ( "errors" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/noop" + noopmetric "go.opentelemetry.io/otel/metric/noop" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -109,5 +109,5 @@ func getLeveledMeter(meter metric.Meter, cfgLevel, srvLevel configtelemetry.Leve if cfgLevel <= srvLevel { return meter } - return noop.Meter{} + return noopmetric.Meter{} } diff --git a/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest.go b/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest.go new file mode 100644 index 00000000000..1abdd4d2c47 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest.go @@ -0,0 +1,83 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +type TestTelemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTestTelemetry() TestTelemetry { + reader := sdkmetric.NewManualReader() + return TestTelemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *TestTelemetry) NewSettings() receiver.Settings { + set := receivertest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("sample")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *TestTelemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *TestTelemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { + var md metricdata.ResourceMetrics + require.NoError(t, tt.reader.Collect(context.Background(), &md)) + // ensure all required metrics are present + for _, want := range expected { + got := getMetric(want.Name, md) + metricdatatest.AssertEqual(t, want, got, opts...) + } + + // ensure no additional metrics are emitted + require.Equal(t, len(expected), lenMetrics(md)) +} + +func (tt *TestTelemetry) Shutdown(ctx context.Context) error { + return tt.meterProvider.Shutdown(ctx) +} + +func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { + for _, sm := range got.ScopeMetrics { + for _, m := range sm.Metrics { + if m.Name == name { + return m + } + } + } + + return metricdata.Metrics{} +} + +func lenMetrics(got metricdata.ResourceMetrics) int { + metricsCount := 0 + for _, sm := range got.ScopeMetrics { + metricsCount += len(sm.Metrics) + } + + return metricsCount +} diff --git a/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest_test.go b/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest_test.go new file mode 100644 index 00000000000..bc4c0708bf9 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,64 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplereceiver/internal/metadata" +) + +func TestSetupTestTelemetry(t *testing.T) { + testTel := SetupTestTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + metadata.WithProcessRuntimeTotalAllocBytesCallback(func() int64 { return 1 }), + ) + require.NoError(t, err) + tb.BatchSizeTriggerSend.Add(context.Background(), 1) + tb.RequestDuration.Record(context.Background(), 1) + + testTel.AssertMetrics(t, []metricdata.Metrics{ + { + Name: "otelcol_batch_size_trigger_send", + Description: "Number of times the batch was sent due to a size trigger [deprecated since v0.110.0]", + Unit: "{times}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_runtime_total_alloc_bytes", + Description: "Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc')", + Unit: "By", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_request_duration", + Description: "Duration of request [alpha]", + Unit: "s", + Data: metricdata.Histogram[float64]{ + Temporality: metricdata.CumulativeTemporality, + DataPoints: []metricdata.HistogramDataPoint[float64]{ + {}, + }, + }, + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + require.NoError(t, testTel.Shutdown(context.Background())) +} diff --git a/cmd/mdatagen/internal/samplereceiver/metrics_test.go b/cmd/mdatagen/internal/samplereceiver/metrics_test.go index f055254ac9a..49f52c73cc8 100644 --- a/cmd/mdatagen/internal/samplereceiver/metrics_test.go +++ b/cmd/mdatagen/internal/samplereceiver/metrics_test.go @@ -9,8 +9,10 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplereceiver/internal/metadata" + "go.opentelemetry.io/collector/cmd/mdatagen/internal/samplereceiver/internal/metadatatest" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/receiver/receivertest" @@ -24,11 +26,11 @@ func TestGeneratedMetrics(t *testing.T) { } func TestComponentTelemetry(t *testing.T) { - tt := setupTestTelemetry() + tt := metadatatest.SetupTestTelemetry() factory := NewFactory() receiver, err := factory.CreateMetrics(context.Background(), tt.NewSettings(), componenttest.NewNopHost(), new(consumertest.MetricsSink)) require.NoError(t, err) - tt.assertMetrics(t, []metricdata.Metrics{ + tt.AssertMetrics(t, []metricdata.Metrics{ { Name: "otelcol_batch_size_trigger_send", Description: "Number of times the batch was sent due to a size trigger [deprecated since v0.110.0]", @@ -57,11 +59,11 @@ func TestComponentTelemetry(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) rcv, ok := receiver.(nopReceiver) require.True(t, ok) rcv.initOptionalMetric() - tt.assertMetrics(t, []metricdata.Metrics{ + tt.AssertMetrics(t, []metricdata.Metrics{ { Name: "otelcol_batch_size_trigger_send", Description: "Number of times the batch was sent due to a size trigger [deprecated since v0.110.0]", @@ -102,6 +104,6 @@ func TestComponentTelemetry(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) require.NoError(t, tt.Shutdown(context.Background())) } diff --git a/cmd/mdatagen/internal/templates/component_telemetry_test.go.tmpl b/cmd/mdatagen/internal/templates/component_telemetry_test.go.tmpl index 93949f9f60b..94fbe394708 100644 --- a/cmd/mdatagen/internal/templates/component_telemetry_test.go.tmpl +++ b/cmd/mdatagen/internal/templates/component_telemetry_test.go.tmpl @@ -23,6 +23,7 @@ import ( {{- end }} ) +// Deprecated: [v0.116.0] use metadatatest.TestTelemetry type componentTestTelemetry struct { reader *sdkmetric.ManualReader meterProvider *sdkmetric.MeterProvider @@ -44,6 +45,7 @@ func (tt *componentTestTelemetry) newTelemetrySettings() component.TelemetrySett return set } +// Deprecated: [v0.116.0] use metadatatest.SetupTestTelemetry func setupTestTelemetry() componentTestTelemetry { reader := sdkmetric.NewManualReader() return componentTestTelemetry{ diff --git a/cmd/mdatagen/internal/templates/telemetry.go.tmpl b/cmd/mdatagen/internal/templates/telemetry.go.tmpl index 8b6c6e7d1dc..07a5e7d25d9 100644 --- a/cmd/mdatagen/internal/templates/telemetry.go.tmpl +++ b/cmd/mdatagen/internal/templates/telemetry.go.tmpl @@ -14,6 +14,7 @@ import ( {{- end }} "go.opentelemetry.io/otel/metric" + noopmetric "go.opentelemetry.io/otel/metric/noop" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -128,7 +129,7 @@ func getLeveledMeter(meter metric.Meter, cfgLevel, srvLevel configtelemetry.Leve if cfgLevel <= srvLevel { return meter } - return noop.Meter{} + return noopmetric.Meter{} } {{- end }} diff --git a/cmd/mdatagen/internal/templates/telemetry_test.go.tmpl b/cmd/mdatagen/internal/templates/telemetry_test.go.tmpl index 170ad0872ea..55c1579e685 100644 --- a/cmd/mdatagen/internal/templates/telemetry_test.go.tmpl +++ b/cmd/mdatagen/internal/templates/telemetry_test.go.tmpl @@ -15,7 +15,6 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" - "go.opentelemetry.io/collector/config/configtelemetry" ) type mockMeter struct { diff --git a/cmd/mdatagen/internal/templates/telemetrytest.go.tmpl b/cmd/mdatagen/internal/templates/telemetrytest.go.tmpl new file mode 100644 index 00000000000..d34c0cc3bf7 --- /dev/null +++ b/cmd/mdatagen/internal/templates/telemetrytest.go.tmpl @@ -0,0 +1,89 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package {{ .Package }}test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/configtelemetry" + {{- if or isConnector isExporter isExtension isProcessor isReceiver }} + "go.opentelemetry.io/collector/{{ .Status.Class }}" + "go.opentelemetry.io/collector/{{ .Status.Class }}/{{ .Status.Class }}test" + {{- end }} +) + +type TestTelemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTestTelemetry() TestTelemetry { + reader := sdkmetric.NewManualReader() + return TestTelemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} + +{{- if or isConnector isExporter isExtension isProcessor isReceiver }} +func (tt *TestTelemetry) NewSettings() {{ .Status.Class }}.Settings { + set := {{ .Status.Class }}test.NewNopSettings() + set.ID = component.NewID(component.MustNewType("{{ .Type }}")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} +{{- end }} + +func (tt *TestTelemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *TestTelemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { + var md metricdata.ResourceMetrics + require.NoError(t, tt.reader.Collect(context.Background(), &md)) + // ensure all required metrics are present + for _, want := range expected { + got := getMetric(want.Name, md) + metricdatatest.AssertEqual(t, want, got, opts...) + } + + // ensure no additional metrics are emitted + require.Equal(t, len(expected), lenMetrics(md)) +} + +func (tt *TestTelemetry) Shutdown(ctx context.Context) error { + return tt.meterProvider.Shutdown(ctx) +} + +func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { + for _, sm := range got.ScopeMetrics { + for _, m := range sm.Metrics { + if m.Name == name { + return m + } + } + } + + return metricdata.Metrics{} +} + +func lenMetrics(got metricdata.ResourceMetrics) int { + metricsCount := 0 + for _, sm := range got.ScopeMetrics { + metricsCount += len(sm.Metrics) + } + + return metricsCount +} + diff --git a/cmd/mdatagen/internal/templates/telemetrytest_test.go.tmpl b/cmd/mdatagen/internal/templates/telemetrytest_test.go.tmpl new file mode 100644 index 00000000000..602b4fddb87 --- /dev/null +++ b/cmd/mdatagen/internal/templates/telemetrytest_test.go.tmpl @@ -0,0 +1,73 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package {{ .Package }}test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" +) + +func TestSetupTestTelemetry(t *testing.T) { + testTel := SetupTestTelemetry() + tb, err := {{ .Package }}.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + {{- $package := .Package -}} + {{- range $name, $metric := .Telemetry.Metrics }} + {{- if (and (not $metric.Optional) $metric.Data.Async) }} + {{ $package }}.With{{ $name.Render }}Callback(func() {{ $metric.Data.BasicType }} { return 1 }), + {{- end }} + {{- end }} + ) + require.NoError(t, err) + {{- range $name, $metric := .Telemetry.Metrics }} + {{- if (and (not $metric.Optional) (not $metric.Data.Async)) }} + {{ if eq $metric.Data.Type "Gauge" -}} + tb.{{ $name.Render }}.Set(context.Background(), 1) + {{- else if eq $metric.Data.Type "Sum" -}} + tb.{{ $name.Render }}.Add(context.Background(), 1) + {{- else if eq $metric.Data.Type "Histogram" -}} + tb.{{ $name.Render }}.Record(context.Background(), 1) + {{- end }} + {{- end }} + {{- end }} + + testTel.AssertMetrics(t, []metricdata.Metrics{ + {{- range $name, $metric := .Telemetry.Metrics }} + {{- if not $metric.Optional }} + { + Name: "otelcol_{{ $name }}", + Description: "{{ $metric.Description }}{{ $metric.Stability }}", + Unit: "{{ $metric.Unit }}", + {{ if eq $metric.Data.Type "Gauge" -}} + Data: metricdata.Gauge[{{ $metric.Gauge.MetricValueType.BasicType }}]{ + DataPoints: []metricdata.DataPoint[{{ $metric.Gauge.MetricValueType.BasicType }}]{ + {}, + }, + }, + {{- else if eq $metric.Data.Type "Sum" -}} + Data: metricdata.Sum[{{ $metric.Sum.MetricValueType.BasicType }}]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: {{ $metric.Sum.Mono.Monotonic }}, + DataPoints: []metricdata.DataPoint[{{ $metric.Sum.MetricValueType.BasicType }}]{ + {}, + }, + }, + {{- else if eq $metric.Data.Type "Histogram" -}} + Data: metricdata.Histogram[{{ $metric.Histogram.MetricValueType.BasicType }}]{ + Temporality: metricdata.CumulativeTemporality, + DataPoints: []metricdata.HistogramDataPoint[{{ $metric.Histogram.MetricValueType.BasicType }}]{ + {}, + }, + }, + {{- end }} + }, + {{- end }} + {{- end }} + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + require.NoError(t, testTel.Shutdown(context.Background())) +} + diff --git a/exporter/exporterhelper/generated_component_telemetry_test.go b/exporter/exporterhelper/generated_component_telemetry_test.go index 3d811dedf01..59a96f0530a 100644 --- a/exporter/exporterhelper/generated_component_telemetry_test.go +++ b/exporter/exporterhelper/generated_component_telemetry_test.go @@ -18,6 +18,7 @@ import ( "go.opentelemetry.io/collector/exporter/exportertest" ) +// Deprecated: [v0.116.0] use metadatatest.TestTelemetry type componentTestTelemetry struct { reader *sdkmetric.ManualReader meterProvider *sdkmetric.MeterProvider @@ -37,6 +38,7 @@ func (tt *componentTestTelemetry) newTelemetrySettings() component.TelemetrySett return set } +// Deprecated: [v0.116.0] use metadatatest.SetupTestTelemetry func setupTestTelemetry() componentTestTelemetry { reader := sdkmetric.NewManualReader() return componentTestTelemetry{ diff --git a/exporter/exporterhelper/internal/metadata/generated_telemetry.go b/exporter/exporterhelper/internal/metadata/generated_telemetry.go index 9522b231122..1ddf416d602 100644 --- a/exporter/exporterhelper/internal/metadata/generated_telemetry.go +++ b/exporter/exporterhelper/internal/metadata/generated_telemetry.go @@ -7,7 +7,7 @@ import ( "errors" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/noop" + noopmetric "go.opentelemetry.io/otel/metric/noop" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -156,5 +156,5 @@ func getLeveledMeter(meter metric.Meter, cfgLevel, srvLevel configtelemetry.Leve if cfgLevel <= srvLevel { return meter } - return noop.Meter{} + return noopmetric.Meter{} } diff --git a/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest.go b/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest.go new file mode 100644 index 00000000000..75e1e82bcf6 --- /dev/null +++ b/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest.go @@ -0,0 +1,83 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/collector/exporter" + "go.opentelemetry.io/collector/exporter/exportertest" +) + +type TestTelemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTestTelemetry() TestTelemetry { + reader := sdkmetric.NewManualReader() + return TestTelemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *TestTelemetry) NewSettings() exporter.Settings { + set := exportertest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("exporterhelper")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *TestTelemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *TestTelemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { + var md metricdata.ResourceMetrics + require.NoError(t, tt.reader.Collect(context.Background(), &md)) + // ensure all required metrics are present + for _, want := range expected { + got := getMetric(want.Name, md) + metricdatatest.AssertEqual(t, want, got, opts...) + } + + // ensure no additional metrics are emitted + require.Equal(t, len(expected), lenMetrics(md)) +} + +func (tt *TestTelemetry) Shutdown(ctx context.Context) error { + return tt.meterProvider.Shutdown(ctx) +} + +func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { + for _, sm := range got.ScopeMetrics { + for _, m := range sm.Metrics { + if m.Name == name { + return m + } + } + } + + return metricdata.Metrics{} +} + +func lenMetrics(got metricdata.ResourceMetrics) int { + metricsCount := 0 + for _, sm := range got.ScopeMetrics { + metricsCount += len(sm.Metrics) + } + + return metricsCount +} diff --git a/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest_test.go b/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest_test.go new file mode 100644 index 00000000000..12e5ae368df --- /dev/null +++ b/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,143 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/exporter/exporterhelper/internal/metadata" +) + +func TestSetupTestTelemetry(t *testing.T) { + testTel := SetupTestTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + ) + require.NoError(t, err) + tb.ExporterEnqueueFailedLogRecords.Add(context.Background(), 1) + tb.ExporterEnqueueFailedMetricPoints.Add(context.Background(), 1) + tb.ExporterEnqueueFailedSpans.Add(context.Background(), 1) + tb.ExporterSendFailedLogRecords.Add(context.Background(), 1) + tb.ExporterSendFailedMetricPoints.Add(context.Background(), 1) + tb.ExporterSendFailedSpans.Add(context.Background(), 1) + tb.ExporterSentLogRecords.Add(context.Background(), 1) + tb.ExporterSentMetricPoints.Add(context.Background(), 1) + tb.ExporterSentSpans.Add(context.Background(), 1) + + testTel.AssertMetrics(t, []metricdata.Metrics{ + { + Name: "otelcol_exporter_enqueue_failed_log_records", + Description: "Number of log records failed to be added to the sending queue. [alpha]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_exporter_enqueue_failed_metric_points", + Description: "Number of metric points failed to be added to the sending queue. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_exporter_enqueue_failed_spans", + Description: "Number of spans failed to be added to the sending queue. [alpha]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_exporter_send_failed_log_records", + Description: "Number of log records in failed attempts to send to destination. [alpha]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_exporter_send_failed_metric_points", + Description: "Number of metric points in failed attempts to send to destination. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_exporter_send_failed_spans", + Description: "Number of spans in failed attempts to send to destination. [alpha]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_exporter_sent_log_records", + Description: "Number of log record successfully sent to destination. [alpha]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_exporter_sent_metric_points", + Description: "Number of metric points successfully sent to destination. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_exporter_sent_spans", + Description: "Number of spans successfully sent to destination. [alpha]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + require.NoError(t, testTel.Shutdown(context.Background())) +} diff --git a/processor/batchprocessor/batch_processor_test.go b/processor/batchprocessor/batch_processor_test.go index 5791ddbd694..5467c35c731 100644 --- a/processor/batchprocessor/batch_processor_test.go +++ b/processor/batchprocessor/batch_processor_test.go @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" "go.opentelemetry.io/collector/client" "go.opentelemetry.io/collector/component/componenttest" @@ -26,6 +27,7 @@ import ( "go.opentelemetry.io/collector/pdata/pmetric" "go.opentelemetry.io/collector/pdata/ptrace" "go.opentelemetry.io/collector/pdata/testdata" + "go.opentelemetry.io/collector/processor/batchprocessor/internal/metadatatest" "go.opentelemetry.io/collector/processor/processortest" ) @@ -171,7 +173,7 @@ func TestBatchProcessorSentBySize(t *testing.T) { expectedBatchingFactor = sendBatchSize / spansPerRequest ) - tel := setupTestTelemetry() + tel := metadatatest.SetupTestTelemetry() sizer := &ptrace.ProtoMarshaler{} sink := new(consumertest.TracesSink) cfg := createDefaultConfig().(*Config) @@ -207,7 +209,7 @@ func TestBatchProcessorSentBySize(t *testing.T) { } } - tel.assertMetrics(t, []metricdata.Metrics{ + tel.AssertMetrics(t, []metricdata.Metrics{ { Name: "otelcol_processor_batch_batch_send_size_bytes", Description: "Number of bytes in batch that was sent", @@ -278,7 +280,7 @@ func TestBatchProcessorSentBySize(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) require.NoError(t, tel.Shutdown(context.Background())) } @@ -291,7 +293,7 @@ func TestBatchProcessorSentBySizeWithMaxSize(t *testing.T) { totalSpans = requestCount * spansPerRequest ) - tel := setupTestTelemetry() + tel := metadatatest.SetupTestTelemetry() sizer := &ptrace.ProtoMarshaler{} sink := new(consumertest.TracesSink) cfg := createDefaultConfig().(*Config) @@ -332,7 +334,7 @@ func TestBatchProcessorSentBySizeWithMaxSize(t *testing.T) { sizeSum += sizer.TracesSize(td) } - tel.assertMetrics(t, []metricdata.Metrics{ + tel.AssertMetrics(t, []metricdata.Metrics{ { Name: "otelcol_processor_batch_batch_send_size_bytes", Description: "Number of bytes in batch that was sent", @@ -418,7 +420,7 @@ func TestBatchProcessorSentBySizeWithMaxSize(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) require.NoError(t, tel.Shutdown(context.Background())) } @@ -543,7 +545,7 @@ func TestBatchMetricProcessor_ReceivingData(t *testing.T) { } func TestBatchMetricProcessorBatchSize(t *testing.T) { - tel := setupTestTelemetry() + tel := metadatatest.SetupTestTelemetry() sizer := &pmetric.ProtoMarshaler{} // Instantiate the batch processor with low config values to test data @@ -590,7 +592,7 @@ func TestBatchMetricProcessorBatchSize(t *testing.T) { } } - tel.assertMetrics(t, []metricdata.Metrics{ + tel.AssertMetrics(t, []metricdata.Metrics{ { Name: "otelcol_processor_batch_batch_send_size_bytes", Description: "Number of bytes in batch that was sent", @@ -661,7 +663,7 @@ func TestBatchMetricProcessorBatchSize(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) require.NoError(t, tel.Shutdown(context.Background())) } @@ -919,7 +921,7 @@ func TestBatchLogProcessor_ReceivingData(t *testing.T) { } func TestBatchLogProcessor_BatchSize(t *testing.T) { - tel := setupTestTelemetry() + tel := metadatatest.SetupTestTelemetry() sizer := &plog.ProtoMarshaler{} // Instantiate the batch processor with low config values to test data @@ -964,7 +966,7 @@ func TestBatchLogProcessor_BatchSize(t *testing.T) { } } - tel.assertMetrics(t, []metricdata.Metrics{ + tel.AssertMetrics(t, []metricdata.Metrics{ { Name: "otelcol_processor_batch_batch_send_size_bytes", Description: "Number of bytes in batch that was sent", @@ -1035,7 +1037,7 @@ func TestBatchLogProcessor_BatchSize(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) require.NoError(t, tel.Shutdown(context.Background())) } diff --git a/processor/batchprocessor/generated_component_telemetry_test.go b/processor/batchprocessor/generated_component_telemetry_test.go index a8dc46c02c2..800f23f0ed1 100644 --- a/processor/batchprocessor/generated_component_telemetry_test.go +++ b/processor/batchprocessor/generated_component_telemetry_test.go @@ -18,6 +18,7 @@ import ( "go.opentelemetry.io/collector/processor/processortest" ) +// Deprecated: [v0.116.0] use metadatatest.TestTelemetry type componentTestTelemetry struct { reader *sdkmetric.ManualReader meterProvider *sdkmetric.MeterProvider @@ -37,6 +38,7 @@ func (tt *componentTestTelemetry) newTelemetrySettings() component.TelemetrySett return set } +// Deprecated: [v0.116.0] use metadatatest.SetupTestTelemetry func setupTestTelemetry() componentTestTelemetry { reader := sdkmetric.NewManualReader() return componentTestTelemetry{ diff --git a/processor/batchprocessor/internal/metadata/generated_telemetry.go b/processor/batchprocessor/internal/metadata/generated_telemetry.go index 01b879e5d47..77d69ddde62 100644 --- a/processor/batchprocessor/internal/metadata/generated_telemetry.go +++ b/processor/batchprocessor/internal/metadata/generated_telemetry.go @@ -7,7 +7,7 @@ import ( "errors" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/noop" + noopmetric "go.opentelemetry.io/otel/metric/noop" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -105,5 +105,5 @@ func getLeveledMeter(meter metric.Meter, cfgLevel, srvLevel configtelemetry.Leve if cfgLevel <= srvLevel { return meter } - return noop.Meter{} + return noopmetric.Meter{} } diff --git a/processor/batchprocessor/internal/metadatatest/generated_telemetrytest.go b/processor/batchprocessor/internal/metadatatest/generated_telemetrytest.go new file mode 100644 index 00000000000..9976fef2b8c --- /dev/null +++ b/processor/batchprocessor/internal/metadatatest/generated_telemetrytest.go @@ -0,0 +1,83 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/collector/processor" + "go.opentelemetry.io/collector/processor/processortest" +) + +type TestTelemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTestTelemetry() TestTelemetry { + reader := sdkmetric.NewManualReader() + return TestTelemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *TestTelemetry) NewSettings() processor.Settings { + set := processortest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("batch")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *TestTelemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *TestTelemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { + var md metricdata.ResourceMetrics + require.NoError(t, tt.reader.Collect(context.Background(), &md)) + // ensure all required metrics are present + for _, want := range expected { + got := getMetric(want.Name, md) + metricdatatest.AssertEqual(t, want, got, opts...) + } + + // ensure no additional metrics are emitted + require.Equal(t, len(expected), lenMetrics(md)) +} + +func (tt *TestTelemetry) Shutdown(ctx context.Context) error { + return tt.meterProvider.Shutdown(ctx) +} + +func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { + for _, sm := range got.ScopeMetrics { + for _, m := range sm.Metrics { + if m.Name == name { + return m + } + } + } + + return metricdata.Metrics{} +} + +func lenMetrics(got metricdata.ResourceMetrics) int { + metricsCount := 0 + for _, sm := range got.ScopeMetrics { + metricsCount += len(sm.Metrics) + } + + return metricsCount +} diff --git a/processor/batchprocessor/internal/metadatatest/generated_telemetrytest_test.go b/processor/batchprocessor/internal/metadatatest/generated_telemetrytest_test.go new file mode 100644 index 00000000000..ffeb53e8083 --- /dev/null +++ b/processor/batchprocessor/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,89 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/processor/batchprocessor/internal/metadata" +) + +func TestSetupTestTelemetry(t *testing.T) { + testTel := SetupTestTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + metadata.WithProcessorBatchMetadataCardinalityCallback(func() int64 { return 1 }), + ) + require.NoError(t, err) + tb.ProcessorBatchBatchSendSize.Record(context.Background(), 1) + tb.ProcessorBatchBatchSendSizeBytes.Record(context.Background(), 1) + tb.ProcessorBatchBatchSizeTriggerSend.Add(context.Background(), 1) + tb.ProcessorBatchTimeoutTriggerSend.Add(context.Background(), 1) + + testTel.AssertMetrics(t, []metricdata.Metrics{ + { + Name: "otelcol_processor_batch_batch_send_size", + Description: "Number of units in the batch", + Unit: "{units}", + Data: metricdata.Histogram[int64]{ + Temporality: metricdata.CumulativeTemporality, + DataPoints: []metricdata.HistogramDataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_processor_batch_batch_send_size_bytes", + Description: "Number of bytes in batch that was sent", + Unit: "By", + Data: metricdata.Histogram[int64]{ + Temporality: metricdata.CumulativeTemporality, + DataPoints: []metricdata.HistogramDataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_processor_batch_batch_size_trigger_send", + Description: "Number of times the batch was sent due to a size trigger", + Unit: "{times}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_processor_batch_metadata_cardinality", + Description: "Number of distinct metadata value combinations being processed", + Unit: "{combinations}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: false, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_processor_batch_timeout_trigger_send", + Description: "Number of times the batch was sent due to a timeout trigger", + Unit: "{times}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + require.NoError(t, testTel.Shutdown(context.Background())) +} diff --git a/processor/memorylimiterprocessor/generated_component_telemetry_test.go b/processor/memorylimiterprocessor/generated_component_telemetry_test.go index 2fbe02be819..7845a4d018b 100644 --- a/processor/memorylimiterprocessor/generated_component_telemetry_test.go +++ b/processor/memorylimiterprocessor/generated_component_telemetry_test.go @@ -18,6 +18,7 @@ import ( "go.opentelemetry.io/collector/processor/processortest" ) +// Deprecated: [v0.116.0] use metadatatest.TestTelemetry type componentTestTelemetry struct { reader *sdkmetric.ManualReader meterProvider *sdkmetric.MeterProvider @@ -37,6 +38,7 @@ func (tt *componentTestTelemetry) newTelemetrySettings() component.TelemetrySett return set } +// Deprecated: [v0.116.0] use metadatatest.SetupTestTelemetry func setupTestTelemetry() componentTestTelemetry { reader := sdkmetric.NewManualReader() return componentTestTelemetry{ diff --git a/processor/memorylimiterprocessor/internal/metadata/generated_telemetry.go b/processor/memorylimiterprocessor/internal/metadata/generated_telemetry.go index e4d64ec3cc9..619a63db9ed 100644 --- a/processor/memorylimiterprocessor/internal/metadata/generated_telemetry.go +++ b/processor/memorylimiterprocessor/internal/metadata/generated_telemetry.go @@ -6,7 +6,7 @@ import ( "errors" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/noop" + noopmetric "go.opentelemetry.io/otel/metric/noop" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -96,5 +96,5 @@ func getLeveledMeter(meter metric.Meter, cfgLevel, srvLevel configtelemetry.Leve if cfgLevel <= srvLevel { return meter } - return noop.Meter{} + return noopmetric.Meter{} } diff --git a/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest.go b/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest.go new file mode 100644 index 00000000000..c4a2f4a2fff --- /dev/null +++ b/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest.go @@ -0,0 +1,83 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/collector/processor" + "go.opentelemetry.io/collector/processor/processortest" +) + +type TestTelemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTestTelemetry() TestTelemetry { + reader := sdkmetric.NewManualReader() + return TestTelemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *TestTelemetry) NewSettings() processor.Settings { + set := processortest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("memory_limiter")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *TestTelemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *TestTelemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { + var md metricdata.ResourceMetrics + require.NoError(t, tt.reader.Collect(context.Background(), &md)) + // ensure all required metrics are present + for _, want := range expected { + got := getMetric(want.Name, md) + metricdatatest.AssertEqual(t, want, got, opts...) + } + + // ensure no additional metrics are emitted + require.Equal(t, len(expected), lenMetrics(md)) +} + +func (tt *TestTelemetry) Shutdown(ctx context.Context) error { + return tt.meterProvider.Shutdown(ctx) +} + +func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { + for _, sm := range got.ScopeMetrics { + for _, m := range sm.Metrics { + if m.Name == name { + return m + } + } + } + + return metricdata.Metrics{} +} + +func lenMetrics(got metricdata.ResourceMetrics) int { + metricsCount := 0 + for _, sm := range got.ScopeMetrics { + metricsCount += len(sm.Metrics) + } + + return metricsCount +} diff --git a/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest_test.go b/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest_test.go new file mode 100644 index 00000000000..1c31a3ad1d6 --- /dev/null +++ b/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,104 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/processor/memorylimiterprocessor/internal/metadata" +) + +func TestSetupTestTelemetry(t *testing.T) { + testTel := SetupTestTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + ) + require.NoError(t, err) + tb.ProcessorAcceptedLogRecords.Add(context.Background(), 1) + tb.ProcessorAcceptedMetricPoints.Add(context.Background(), 1) + tb.ProcessorAcceptedSpans.Add(context.Background(), 1) + tb.ProcessorRefusedLogRecords.Add(context.Background(), 1) + tb.ProcessorRefusedMetricPoints.Add(context.Background(), 1) + tb.ProcessorRefusedSpans.Add(context.Background(), 1) + + testTel.AssertMetrics(t, []metricdata.Metrics{ + { + Name: "otelcol_processor_accepted_log_records", + Description: "Number of log records successfully pushed into the next component in the pipeline. [deprecated since v0.110.0]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_processor_accepted_metric_points", + Description: "Number of metric points successfully pushed into the next component in the pipeline. [deprecated since v0.110.0]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_processor_accepted_spans", + Description: "Number of spans successfully pushed into the next component in the pipeline. [deprecated since v0.110.0]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_processor_refused_log_records", + Description: "Number of log records that were rejected by the next component in the pipeline. [deprecated since v0.110.0]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_processor_refused_metric_points", + Description: "Number of metric points that were rejected by the next component in the pipeline. [deprecated since v0.110.0]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_processor_refused_spans", + Description: "Number of spans that were rejected by the next component in the pipeline. [deprecated since v0.110.0]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + require.NoError(t, testTel.Shutdown(context.Background())) +} diff --git a/processor/memorylimiterprocessor/memorylimiter_test.go b/processor/memorylimiterprocessor/memorylimiter_test.go index 055efce43b1..dd9f5738aa8 100644 --- a/processor/memorylimiterprocessor/memorylimiter_test.go +++ b/processor/memorylimiterprocessor/memorylimiter_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" @@ -24,6 +25,7 @@ import ( "go.opentelemetry.io/collector/pdata/ptrace" "go.opentelemetry.io/collector/processor" "go.opentelemetry.io/collector/processor/memorylimiterprocessor/internal" + "go.opentelemetry.io/collector/processor/memorylimiterprocessor/internal/metadatatest" "go.opentelemetry.io/collector/processor/processorhelper" "go.opentelemetry.io/collector/processor/processortest" ) @@ -208,7 +210,7 @@ func TestMetricsMemoryPressureResponse(t *testing.T) { } func TestMetricsTelemetry(t *testing.T) { - tel := setupTestTelemetry() + tel := metadatatest.SetupTestTelemetry() cfg := &Config{ CheckInterval: time.Second, MemoryLimitPercentage: 50, @@ -225,7 +227,7 @@ func TestMetricsTelemetry(t *testing.T) { } require.NoError(t, metrics.Shutdown(context.Background())) - tel.assertMetrics(t, []metricdata.Metrics{ + tel.AssertMetrics(t, []metricdata.Metrics{ { Name: "otelcol_processor_accepted_metric_points", Description: "Number of metric points successfully pushed into the next component in the pipeline. [deprecated since v0.110.0]", @@ -271,7 +273,7 @@ func TestMetricsTelemetry(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) require.NoError(t, tel.Shutdown(context.Background())) } diff --git a/processor/processorhelper/generated_component_telemetry_test.go b/processor/processorhelper/generated_component_telemetry_test.go index 40784557120..ad241e58533 100644 --- a/processor/processorhelper/generated_component_telemetry_test.go +++ b/processor/processorhelper/generated_component_telemetry_test.go @@ -18,6 +18,7 @@ import ( "go.opentelemetry.io/collector/processor/processortest" ) +// Deprecated: [v0.116.0] use metadatatest.TestTelemetry type componentTestTelemetry struct { reader *sdkmetric.ManualReader meterProvider *sdkmetric.MeterProvider @@ -37,6 +38,7 @@ func (tt *componentTestTelemetry) newTelemetrySettings() component.TelemetrySett return set } +// Deprecated: [v0.116.0] use metadatatest.SetupTestTelemetry func setupTestTelemetry() componentTestTelemetry { reader := sdkmetric.NewManualReader() return componentTestTelemetry{ diff --git a/processor/processorhelper/internal/metadata/generated_telemetry.go b/processor/processorhelper/internal/metadata/generated_telemetry.go index 0cc9d5c5245..06ad630679b 100644 --- a/processor/processorhelper/internal/metadata/generated_telemetry.go +++ b/processor/processorhelper/internal/metadata/generated_telemetry.go @@ -6,7 +6,7 @@ import ( "errors" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/noop" + noopmetric "go.opentelemetry.io/otel/metric/noop" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -68,5 +68,5 @@ func getLeveledMeter(meter metric.Meter, cfgLevel, srvLevel configtelemetry.Leve if cfgLevel <= srvLevel { return meter } - return noop.Meter{} + return noopmetric.Meter{} } diff --git a/processor/processorhelper/internal/metadatatest/generated_telemetrytest.go b/processor/processorhelper/internal/metadatatest/generated_telemetrytest.go new file mode 100644 index 00000000000..18d46d51a17 --- /dev/null +++ b/processor/processorhelper/internal/metadatatest/generated_telemetrytest.go @@ -0,0 +1,83 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/collector/processor" + "go.opentelemetry.io/collector/processor/processortest" +) + +type TestTelemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTestTelemetry() TestTelemetry { + reader := sdkmetric.NewManualReader() + return TestTelemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *TestTelemetry) NewSettings() processor.Settings { + set := processortest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("processorhelper")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *TestTelemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *TestTelemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { + var md metricdata.ResourceMetrics + require.NoError(t, tt.reader.Collect(context.Background(), &md)) + // ensure all required metrics are present + for _, want := range expected { + got := getMetric(want.Name, md) + metricdatatest.AssertEqual(t, want, got, opts...) + } + + // ensure no additional metrics are emitted + require.Equal(t, len(expected), lenMetrics(md)) +} + +func (tt *TestTelemetry) Shutdown(ctx context.Context) error { + return tt.meterProvider.Shutdown(ctx) +} + +func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { + for _, sm := range got.ScopeMetrics { + for _, m := range sm.Metrics { + if m.Name == name { + return m + } + } + } + + return metricdata.Metrics{} +} + +func lenMetrics(got metricdata.ResourceMetrics) int { + metricsCount := 0 + for _, sm := range got.ScopeMetrics { + metricsCount += len(sm.Metrics) + } + + return metricsCount +} diff --git a/processor/processorhelper/internal/metadatatest/generated_telemetrytest_test.go b/processor/processorhelper/internal/metadatatest/generated_telemetrytest_test.go new file mode 100644 index 00000000000..8bb57a3f2af --- /dev/null +++ b/processor/processorhelper/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,52 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/processor/processorhelper/internal/metadata" +) + +func TestSetupTestTelemetry(t *testing.T) { + testTel := SetupTestTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + ) + require.NoError(t, err) + tb.ProcessorIncomingItems.Add(context.Background(), 1) + tb.ProcessorOutgoingItems.Add(context.Background(), 1) + + testTel.AssertMetrics(t, []metricdata.Metrics{ + { + Name: "otelcol_processor_incoming_items", + Description: "Number of items passed to the processor. [alpha]", + Unit: "{items}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_processor_outgoing_items", + Description: "Number of items emitted from the processor. [alpha]", + Unit: "{items}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + require.NoError(t, testTel.Shutdown(context.Background())) +} diff --git a/processor/processorhelper/logs_test.go b/processor/processorhelper/logs_test.go index 9a6c5592745..1ada5aab41c 100644 --- a/processor/processorhelper/logs_test.go +++ b/processor/processorhelper/logs_test.go @@ -13,12 +13,14 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/processor/processorhelper/internal/metadatatest" "go.opentelemetry.io/collector/processor/processortest" ) @@ -118,7 +120,7 @@ func TestLogs_RecordInOut(t *testing.T) { incomingLogRecords.AppendEmpty() incomingLogRecords.AppendEmpty() - testTelemetry := setupTestTelemetry() + testTelemetry := metadatatest.SetupTestTelemetry() lp, err := NewLogs(context.Background(), testTelemetry.NewSettings(), &testLogsCfg, consumertest.NewNop(), mockAggregate) require.NoError(t, err) @@ -126,7 +128,7 @@ func TestLogs_RecordInOut(t *testing.T) { assert.NoError(t, lp.ConsumeLogs(context.Background(), incomingLogs)) assert.NoError(t, lp.Shutdown(context.Background())) - testTelemetry.assertMetrics(t, []metricdata.Metrics{ + testTelemetry.AssertMetrics(t, []metricdata.Metrics{ { Name: "otelcol_processor_incoming_items", Description: "Number of items passed to the processor. [alpha]", @@ -157,7 +159,7 @@ func TestLogs_RecordInOut(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) } func TestLogs_RecordIn_ErrorOut(t *testing.T) { @@ -174,7 +176,7 @@ func TestLogs_RecordIn_ErrorOut(t *testing.T) { incomingLogRecords.AppendEmpty() incomingLogRecords.AppendEmpty() - testTelemetry := setupTestTelemetry() + testTelemetry := metadatatest.SetupTestTelemetry() lp, err := NewLogs(context.Background(), testTelemetry.NewSettings(), &testLogsCfg, consumertest.NewNop(), mockErr) require.NoError(t, err) @@ -182,7 +184,7 @@ func TestLogs_RecordIn_ErrorOut(t *testing.T) { require.Error(t, lp.ConsumeLogs(context.Background(), incomingLogs)) require.NoError(t, lp.Shutdown(context.Background())) - testTelemetry.assertMetrics(t, []metricdata.Metrics{ + testTelemetry.AssertMetrics(t, []metricdata.Metrics{ { Name: "otelcol_processor_incoming_items", Description: "Number of items passed to the processor. [alpha]", @@ -213,5 +215,5 @@ func TestLogs_RecordIn_ErrorOut(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) } diff --git a/processor/processorhelper/metrics_test.go b/processor/processorhelper/metrics_test.go index cb841abfa74..a8bdc3a3354 100644 --- a/processor/processorhelper/metrics_test.go +++ b/processor/processorhelper/metrics_test.go @@ -13,12 +13,14 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/processor/processorhelper/internal/metadatatest" "go.opentelemetry.io/collector/processor/processortest" ) @@ -118,7 +120,7 @@ func TestMetrics_RecordInOut(t *testing.T) { dps.AppendEmpty() dps.AppendEmpty() - testTelemetry := setupTestTelemetry() + testTelemetry := metadatatest.SetupTestTelemetry() mp, err := NewMetrics(context.Background(), testTelemetry.NewSettings(), &testMetricsCfg, consumertest.NewNop(), mockAggregate) require.NoError(t, err) @@ -126,7 +128,7 @@ func TestMetrics_RecordInOut(t *testing.T) { assert.NoError(t, mp.ConsumeMetrics(context.Background(), incomingMetrics)) assert.NoError(t, mp.Shutdown(context.Background())) - testTelemetry.assertMetrics(t, []metricdata.Metrics{ + testTelemetry.AssertMetrics(t, []metricdata.Metrics{ { Name: "otelcol_processor_incoming_items", Description: "Number of items passed to the processor. [alpha]", @@ -157,7 +159,7 @@ func TestMetrics_RecordInOut(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) } func TestMetrics_RecordIn_ErrorOut(t *testing.T) { @@ -173,7 +175,7 @@ func TestMetrics_RecordIn_ErrorOut(t *testing.T) { dps.AppendEmpty() dps.AppendEmpty() - testTelemetry := setupTestTelemetry() + testTelemetry := metadatatest.SetupTestTelemetry() mp, err := NewMetrics(context.Background(), testTelemetry.NewSettings(), &testMetricsCfg, consumertest.NewNop(), mockErr) require.NoError(t, err) @@ -181,7 +183,7 @@ func TestMetrics_RecordIn_ErrorOut(t *testing.T) { require.Error(t, mp.ConsumeMetrics(context.Background(), incomingMetrics)) require.NoError(t, mp.Shutdown(context.Background())) - testTelemetry.assertMetrics(t, []metricdata.Metrics{ + testTelemetry.AssertMetrics(t, []metricdata.Metrics{ { Name: "otelcol_processor_incoming_items", Description: "Number of items passed to the processor. [alpha]", @@ -212,5 +214,5 @@ func TestMetrics_RecordIn_ErrorOut(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) } diff --git a/processor/processorhelper/traces_test.go b/processor/processorhelper/traces_test.go index a55e99aa42b..7923e107368 100644 --- a/processor/processorhelper/traces_test.go +++ b/processor/processorhelper/traces_test.go @@ -13,12 +13,14 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" "go.opentelemetry.io/collector/pdata/ptrace" + "go.opentelemetry.io/collector/processor/processorhelper/internal/metadatatest" "go.opentelemetry.io/collector/processor/processortest" ) @@ -120,7 +122,7 @@ func TestTraces_RecordInOut(t *testing.T) { incomingSpans.AppendEmpty() incomingSpans.AppendEmpty() - testTelemetry := setupTestTelemetry() + testTelemetry := metadatatest.SetupTestTelemetry() tp, err := NewTraces(context.Background(), testTelemetry.NewSettings(), &testLogsCfg, consumertest.NewNop(), mockAggregate) require.NoError(t, err) @@ -128,7 +130,7 @@ func TestTraces_RecordInOut(t *testing.T) { assert.NoError(t, tp.ConsumeTraces(context.Background(), incomingTraces)) assert.NoError(t, tp.Shutdown(context.Background())) - testTelemetry.assertMetrics(t, []metricdata.Metrics{ + testTelemetry.AssertMetrics(t, []metricdata.Metrics{ { Name: "otelcol_processor_incoming_items", Description: "Number of items passed to the processor. [alpha]", @@ -159,7 +161,7 @@ func TestTraces_RecordInOut(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) } func TestTraces_RecordIn_ErrorOut(t *testing.T) { @@ -177,7 +179,7 @@ func TestTraces_RecordIn_ErrorOut(t *testing.T) { incomingSpans.AppendEmpty() incomingSpans.AppendEmpty() - testTelemetry := setupTestTelemetry() + testTelemetry := metadatatest.SetupTestTelemetry() tp, err := NewTraces(context.Background(), testTelemetry.NewSettings(), &testLogsCfg, consumertest.NewNop(), mockErr) require.NoError(t, err) @@ -185,7 +187,7 @@ func TestTraces_RecordIn_ErrorOut(t *testing.T) { require.Error(t, tp.ConsumeTraces(context.Background(), incomingTraces)) require.NoError(t, tp.Shutdown(context.Background())) - testTelemetry.assertMetrics(t, []metricdata.Metrics{ + testTelemetry.AssertMetrics(t, []metricdata.Metrics{ { Name: "otelcol_processor_incoming_items", Description: "Number of items passed to the processor. [alpha]", @@ -216,5 +218,5 @@ func TestTraces_RecordIn_ErrorOut(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) } diff --git a/receiver/receiverhelper/generated_component_telemetry_test.go b/receiver/receiverhelper/generated_component_telemetry_test.go index fb03a51e830..4ee27edf52a 100644 --- a/receiver/receiverhelper/generated_component_telemetry_test.go +++ b/receiver/receiverhelper/generated_component_telemetry_test.go @@ -18,6 +18,7 @@ import ( "go.opentelemetry.io/collector/receiver/receivertest" ) +// Deprecated: [v0.116.0] use metadatatest.TestTelemetry type componentTestTelemetry struct { reader *sdkmetric.ManualReader meterProvider *sdkmetric.MeterProvider @@ -37,6 +38,7 @@ func (tt *componentTestTelemetry) newTelemetrySettings() component.TelemetrySett return set } +// Deprecated: [v0.116.0] use metadatatest.SetupTestTelemetry func setupTestTelemetry() componentTestTelemetry { reader := sdkmetric.NewManualReader() return componentTestTelemetry{ diff --git a/receiver/receiverhelper/internal/metadata/generated_telemetry.go b/receiver/receiverhelper/internal/metadata/generated_telemetry.go index 0600af1470a..17955ac81e6 100644 --- a/receiver/receiverhelper/internal/metadata/generated_telemetry.go +++ b/receiver/receiverhelper/internal/metadata/generated_telemetry.go @@ -6,7 +6,7 @@ import ( "errors" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/noop" + noopmetric "go.opentelemetry.io/otel/metric/noop" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -96,5 +96,5 @@ func getLeveledMeter(meter metric.Meter, cfgLevel, srvLevel configtelemetry.Leve if cfgLevel <= srvLevel { return meter } - return noop.Meter{} + return noopmetric.Meter{} } diff --git a/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest.go b/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest.go new file mode 100644 index 00000000000..bcb08d113fe --- /dev/null +++ b/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest.go @@ -0,0 +1,83 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +type TestTelemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTestTelemetry() TestTelemetry { + reader := sdkmetric.NewManualReader() + return TestTelemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *TestTelemetry) NewSettings() receiver.Settings { + set := receivertest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("receiverhelper")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *TestTelemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *TestTelemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { + var md metricdata.ResourceMetrics + require.NoError(t, tt.reader.Collect(context.Background(), &md)) + // ensure all required metrics are present + for _, want := range expected { + got := getMetric(want.Name, md) + metricdatatest.AssertEqual(t, want, got, opts...) + } + + // ensure no additional metrics are emitted + require.Equal(t, len(expected), lenMetrics(md)) +} + +func (tt *TestTelemetry) Shutdown(ctx context.Context) error { + return tt.meterProvider.Shutdown(ctx) +} + +func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { + for _, sm := range got.ScopeMetrics { + for _, m := range sm.Metrics { + if m.Name == name { + return m + } + } + } + + return metricdata.Metrics{} +} + +func lenMetrics(got metricdata.ResourceMetrics) int { + metricsCount := 0 + for _, sm := range got.ScopeMetrics { + metricsCount += len(sm.Metrics) + } + + return metricsCount +} diff --git a/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest_test.go b/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest_test.go new file mode 100644 index 00000000000..1d99700fab0 --- /dev/null +++ b/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,104 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/receiver/receiverhelper/internal/metadata" +) + +func TestSetupTestTelemetry(t *testing.T) { + testTel := SetupTestTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + ) + require.NoError(t, err) + tb.ReceiverAcceptedLogRecords.Add(context.Background(), 1) + tb.ReceiverAcceptedMetricPoints.Add(context.Background(), 1) + tb.ReceiverAcceptedSpans.Add(context.Background(), 1) + tb.ReceiverRefusedLogRecords.Add(context.Background(), 1) + tb.ReceiverRefusedMetricPoints.Add(context.Background(), 1) + tb.ReceiverRefusedSpans.Add(context.Background(), 1) + + testTel.AssertMetrics(t, []metricdata.Metrics{ + { + Name: "otelcol_receiver_accepted_log_records", + Description: "Number of log records successfully pushed into the pipeline. [alpha]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_receiver_accepted_metric_points", + Description: "Number of metric points successfully pushed into the pipeline. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_receiver_accepted_spans", + Description: "Number of spans successfully pushed into the pipeline. [alpha]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_receiver_refused_log_records", + Description: "Number of log records that could not be pushed into the pipeline. [alpha]", + Unit: "{records}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_receiver_refused_metric_points", + Description: "Number of metric points that could not be pushed into the pipeline. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_receiver_refused_spans", + Description: "Number of spans that could not be pushed into the pipeline. [alpha]", + Unit: "{spans}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + require.NoError(t, testTel.Shutdown(context.Background())) +} diff --git a/receiver/scraperhelper/generated_component_telemetry_test.go b/receiver/scraperhelper/generated_component_telemetry_test.go index a60c59fe220..90f864aa570 100644 --- a/receiver/scraperhelper/generated_component_telemetry_test.go +++ b/receiver/scraperhelper/generated_component_telemetry_test.go @@ -18,6 +18,7 @@ import ( "go.opentelemetry.io/collector/receiver/receivertest" ) +// Deprecated: [v0.116.0] use metadatatest.TestTelemetry type componentTestTelemetry struct { reader *sdkmetric.ManualReader meterProvider *sdkmetric.MeterProvider @@ -37,6 +38,7 @@ func (tt *componentTestTelemetry) newTelemetrySettings() component.TelemetrySett return set } +// Deprecated: [v0.116.0] use metadatatest.SetupTestTelemetry func setupTestTelemetry() componentTestTelemetry { reader := sdkmetric.NewManualReader() return componentTestTelemetry{ diff --git a/receiver/scraperhelper/internal/metadata/generated_telemetry.go b/receiver/scraperhelper/internal/metadata/generated_telemetry.go index 8e01bc1d74b..c9f15214367 100644 --- a/receiver/scraperhelper/internal/metadata/generated_telemetry.go +++ b/receiver/scraperhelper/internal/metadata/generated_telemetry.go @@ -6,7 +6,7 @@ import ( "errors" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/noop" + noopmetric "go.opentelemetry.io/otel/metric/noop" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -68,5 +68,5 @@ func getLeveledMeter(meter metric.Meter, cfgLevel, srvLevel configtelemetry.Leve if cfgLevel <= srvLevel { return meter } - return noop.Meter{} + return noopmetric.Meter{} } diff --git a/receiver/scraperhelper/internal/metadatatest/generated_telemetrytest.go b/receiver/scraperhelper/internal/metadatatest/generated_telemetrytest.go new file mode 100644 index 00000000000..cf2a29bcc1c --- /dev/null +++ b/receiver/scraperhelper/internal/metadatatest/generated_telemetrytest.go @@ -0,0 +1,83 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/collector/receiver" + "go.opentelemetry.io/collector/receiver/receivertest" +) + +type TestTelemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTestTelemetry() TestTelemetry { + reader := sdkmetric.NewManualReader() + return TestTelemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *TestTelemetry) NewSettings() receiver.Settings { + set := receivertest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("scraperhelper")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *TestTelemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *TestTelemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { + var md metricdata.ResourceMetrics + require.NoError(t, tt.reader.Collect(context.Background(), &md)) + // ensure all required metrics are present + for _, want := range expected { + got := getMetric(want.Name, md) + metricdatatest.AssertEqual(t, want, got, opts...) + } + + // ensure no additional metrics are emitted + require.Equal(t, len(expected), lenMetrics(md)) +} + +func (tt *TestTelemetry) Shutdown(ctx context.Context) error { + return tt.meterProvider.Shutdown(ctx) +} + +func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { + for _, sm := range got.ScopeMetrics { + for _, m := range sm.Metrics { + if m.Name == name { + return m + } + } + } + + return metricdata.Metrics{} +} + +func lenMetrics(got metricdata.ResourceMetrics) int { + metricsCount := 0 + for _, sm := range got.ScopeMetrics { + metricsCount += len(sm.Metrics) + } + + return metricsCount +} diff --git a/receiver/scraperhelper/internal/metadatatest/generated_telemetrytest_test.go b/receiver/scraperhelper/internal/metadatatest/generated_telemetrytest_test.go new file mode 100644 index 00000000000..ce7120ddf20 --- /dev/null +++ b/receiver/scraperhelper/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,52 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/receiver/scraperhelper/internal/metadata" +) + +func TestSetupTestTelemetry(t *testing.T) { + testTel := SetupTestTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + ) + require.NoError(t, err) + tb.ScraperErroredMetricPoints.Add(context.Background(), 1) + tb.ScraperScrapedMetricPoints.Add(context.Background(), 1) + + testTel.AssertMetrics(t, []metricdata.Metrics{ + { + Name: "otelcol_scraper_errored_metric_points", + Description: "Number of metric points that were unable to be scraped. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_scraper_scraped_metric_points", + Description: "Number of metric points successfully scraped. [alpha]", + Unit: "{datapoints}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + require.NoError(t, testTel.Shutdown(context.Background())) +} diff --git a/service/generated_component_telemetry_test.go b/service/generated_component_telemetry_test.go index 2680da02764..2e37020d2d6 100644 --- a/service/generated_component_telemetry_test.go +++ b/service/generated_component_telemetry_test.go @@ -16,6 +16,7 @@ import ( "go.opentelemetry.io/collector/config/configtelemetry" ) +// Deprecated: [v0.116.0] use metadatatest.TestTelemetry type componentTestTelemetry struct { reader *sdkmetric.ManualReader meterProvider *sdkmetric.MeterProvider @@ -28,6 +29,7 @@ func (tt *componentTestTelemetry) newTelemetrySettings() component.TelemetrySett return set } +// Deprecated: [v0.116.0] use metadatatest.SetupTestTelemetry func setupTestTelemetry() componentTestTelemetry { reader := sdkmetric.NewManualReader() return componentTestTelemetry{ diff --git a/service/internal/metadata/generated_telemetry.go b/service/internal/metadata/generated_telemetry.go index e8d2360a85d..a180db3c3f0 100644 --- a/service/internal/metadata/generated_telemetry.go +++ b/service/internal/metadata/generated_telemetry.go @@ -7,7 +7,7 @@ import ( "errors" "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/noop" + noopmetric "go.opentelemetry.io/otel/metric/noop" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -175,5 +175,5 @@ func getLeveledMeter(meter metric.Meter, cfgLevel, srvLevel configtelemetry.Leve if cfgLevel <= srvLevel { return meter } - return noop.Meter{} + return noopmetric.Meter{} } diff --git a/service/internal/metadatatest/generated_telemetrytest.go b/service/internal/metadatatest/generated_telemetrytest.go new file mode 100644 index 00000000000..84973c116af --- /dev/null +++ b/service/internal/metadatatest/generated_telemetrytest.go @@ -0,0 +1,75 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/config/configtelemetry" +) + +type TestTelemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTestTelemetry() TestTelemetry { + reader := sdkmetric.NewManualReader() + return TestTelemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} + +func (tt *TestTelemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *TestTelemetry) AssertMetrics(t *testing.T, expected []metricdata.Metrics, opts ...metricdatatest.Option) { + var md metricdata.ResourceMetrics + require.NoError(t, tt.reader.Collect(context.Background(), &md)) + // ensure all required metrics are present + for _, want := range expected { + got := getMetric(want.Name, md) + metricdatatest.AssertEqual(t, want, got, opts...) + } + + // ensure no additional metrics are emitted + require.Equal(t, len(expected), lenMetrics(md)) +} + +func (tt *TestTelemetry) Shutdown(ctx context.Context) error { + return tt.meterProvider.Shutdown(ctx) +} + +func getMetric(name string, got metricdata.ResourceMetrics) metricdata.Metrics { + for _, sm := range got.ScopeMetrics { + for _, m := range sm.Metrics { + if m.Name == name { + return m + } + } + } + + return metricdata.Metrics{} +} + +func lenMetrics(got metricdata.ResourceMetrics) int { + metricsCount := 0 + for _, sm := range got.ScopeMetrics { + metricsCount += len(sm.Metrics) + } + + return metricsCount +} diff --git a/service/internal/metadatatest/generated_telemetrytest_test.go b/service/internal/metadatatest/generated_telemetrytest_test.go new file mode 100644 index 00000000000..8b06a86a2c7 --- /dev/null +++ b/service/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,98 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/service/internal/metadata" +) + +func TestSetupTestTelemetry(t *testing.T) { + testTel := SetupTestTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + metadata.WithProcessCPUSecondsCallback(func() float64 { return 1 }), + metadata.WithProcessMemoryRssCallback(func() int64 { return 1 }), + metadata.WithProcessRuntimeHeapAllocBytesCallback(func() int64 { return 1 }), + metadata.WithProcessRuntimeTotalAllocBytesCallback(func() int64 { return 1 }), + metadata.WithProcessRuntimeTotalSysMemoryBytesCallback(func() int64 { return 1 }), + metadata.WithProcessUptimeCallback(func() float64 { return 1 }), + ) + require.NoError(t, err) + + testTel.AssertMetrics(t, []metricdata.Metrics{ + { + Name: "otelcol_process_cpu_seconds", + Description: "Total CPU user and system time in seconds [alpha]", + Unit: "s", + Data: metricdata.Sum[float64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[float64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_memory_rss", + Description: "Total physical memory (resident set size) [alpha]", + Unit: "By", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_runtime_heap_alloc_bytes", + Description: "Bytes of allocated heap objects (see 'go doc runtime.MemStats.HeapAlloc') [alpha]", + Unit: "By", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_runtime_total_alloc_bytes", + Description: "Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc') [alpha]", + Unit: "By", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_runtime_total_sys_memory_bytes", + Description: "Total bytes of memory obtained from the OS (see 'go doc runtime.MemStats.Sys') [alpha]", + Unit: "By", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_uptime", + Description: "Uptime of the process [alpha]", + Unit: "s", + Data: metricdata.Sum[float64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[float64]{ + {}, + }, + }, + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) + require.NoError(t, testTel.Shutdown(context.Background())) +} diff --git a/service/internal/proctelemetry/process_telemetry_linux_test.go b/service/internal/proctelemetry/process_telemetry_linux_test.go index 3bdbc9cd74b..e1c42990e97 100644 --- a/service/internal/proctelemetry/process_telemetry_linux_test.go +++ b/service/internal/proctelemetry/process_telemetry_linux_test.go @@ -6,46 +6,86 @@ package proctelemetry import ( - "fmt" - "strings" "testing" - "time" - io_prometheus_client "github.com/prometheus/client_model/go" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" + + "go.opentelemetry.io/collector/service/internal/metadatatest" ) func TestProcessTelemetryWithHostProc(t *testing.T) { - tel := setupTelemetry(t) // Make the sure the environment variable value is not used. t.Setenv("HOST_PROC", "foo/bar") - - require.NoError(t, RegisterProcessMetrics(tel.TelemetrySettings, WithHostProc("/proc"))) - - // Check that the metrics are actually filled. - time.Sleep(200 * time.Millisecond) - - mp, err := fetchPrometheusMetrics(tel.promHandler) - require.NoError(t, err) - - for _, metricName := range expectedMetrics { - metric, ok := mp[metricName] - require.True(t, ok) - require.Len(t, metric.Metric, 1) - var metricValue float64 - if metric.GetType() == io_prometheus_client.MetricType_COUNTER { - metricValue = metric.Metric[0].GetCounter().GetValue() - } else { - metricValue = metric.Metric[0].GetGauge().GetValue() - } - if strings.HasPrefix(metricName, "otelcol_process_uptime") || strings.HasPrefix(metricName, "otelcol_process_cpu_seconds") { - // This likely will still be zero when running the test. - assert.GreaterOrEqual(t, metricValue, float64(0), metricName) - continue - } - - fmt.Println(metricName) - assert.Greater(t, metricValue, float64(0), metricName) - } + tel := metadatatest.SetupTestTelemetry() + require.NoError(t, RegisterProcessMetrics(tel.NewTelemetrySettings(), WithHostProc("/proc"))) + tel.AssertMetrics(t, []metricdata.Metrics{ + { + Name: "otelcol_process_uptime", + Description: "Uptime of the process [alpha]", + Unit: "s", + Data: metricdata.Sum[float64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[float64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_runtime_heap_alloc_bytes", + Description: "Bytes of allocated heap objects (see 'go doc runtime.MemStats.HeapAlloc') [alpha]", + Unit: "By", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_runtime_total_alloc_bytes", + Description: "Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc') [alpha]", + Unit: "By", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_runtime_total_sys_memory_bytes", + Description: "Total bytes of memory obtained from the OS (see 'go doc runtime.MemStats.Sys') [alpha]", + Unit: "By", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_cpu_seconds", + Description: "Total CPU user and system time in seconds [alpha]", + Unit: "s", + Data: metricdata.Sum[float64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[float64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_memory_rss", + Description: "Total physical memory (resident set size) [alpha]", + Unit: "By", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) } diff --git a/service/internal/proctelemetry/process_telemetry_test.go b/service/internal/proctelemetry/process_telemetry_test.go index f7a6a4ee913..140cbb4828b 100644 --- a/service/internal/proctelemetry/process_telemetry_test.go +++ b/service/internal/proctelemetry/process_telemetry_test.go @@ -4,102 +4,84 @@ package proctelemetry import ( - "context" - "net/http" - "net/http/httptest" - "strings" "testing" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - promclient "github.com/prometheus/client_model/go" - "github.com/prometheus/common/expfmt" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - otelprom "go.opentelemetry.io/otel/exporters/prometheus" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/resource" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" - "go.opentelemetry.io/collector/component" - "go.opentelemetry.io/collector/component/componenttest" - "go.opentelemetry.io/collector/config/configtelemetry" + "go.opentelemetry.io/collector/service/internal/metadatatest" ) -type testTelemetry struct { - TelemetrySettings component.TelemetrySettings - promHandler http.Handler -} - -var expectedMetrics = []string{ - "otelcol_process_uptime", - "otelcol_process_runtime_heap_alloc_bytes", - "otelcol_process_runtime_total_alloc_bytes", - "otelcol_process_runtime_total_sys_memory_bytes", - "otelcol_process_cpu_seconds", - "otelcol_process_memory_rss", -} - -func setupTelemetry(t *testing.T) testTelemetry { - settings := testTelemetry{ - TelemetrySettings: componenttest.NewNopTelemetrySettings(), - } - - promReg := prometheus.NewRegistry() - exporter, err := otelprom.New(otelprom.WithRegisterer(promReg), otelprom.WithoutUnits(), otelprom.WithoutCounterSuffixes()) - require.NoError(t, err) - - meterProvider := sdkmetric.NewMeterProvider( - sdkmetric.WithResource(resource.Empty()), - sdkmetric.WithReader(exporter), - ) - - settings.TelemetrySettings.MetricsLevel = configtelemetry.LevelDetailed - settings.TelemetrySettings.MeterProvider = meterProvider - - settings.promHandler = promhttp.HandlerFor(promReg, promhttp.HandlerOpts{}) - - t.Cleanup(func() { assert.NoError(t, meterProvider.Shutdown(context.Background())) }) - - return settings -} - -func fetchPrometheusMetrics(handler http.Handler) (map[string]*promclient.MetricFamily, error) { - req, err := http.NewRequest(http.MethodGet, "/metrics", nil) - if err != nil { - return nil, err - } - - rr := httptest.NewRecorder() - handler.ServeHTTP(rr, req) - - var parser expfmt.TextParser - return parser.TextToMetricFamilies(rr.Body) -} - func TestProcessTelemetry(t *testing.T) { - tel := setupTelemetry(t) - - require.NoError(t, RegisterProcessMetrics(tel.TelemetrySettings)) - - mp, err := fetchPrometheusMetrics(tel.promHandler) - require.NoError(t, err) - - for _, metricName := range expectedMetrics { - metric, ok := mp[metricName] - require.True(t, ok) - require.Len(t, metric.Metric, 1) - var metricValue float64 - if metric.GetType() == promclient.MetricType_COUNTER { - metricValue = metric.Metric[0].GetCounter().GetValue() - } else { - metricValue = metric.Metric[0].GetGauge().GetValue() - } - if strings.HasPrefix(metricName, "otelcol_process_uptime") || strings.HasPrefix(metricName, "otelcol_process_cpu_seconds") { - // This likely will still be zero when running the test. - assert.GreaterOrEqual(t, metricValue, float64(0), metricName) - continue - } - - assert.Greater(t, metricValue, float64(0), metricName) - } + tel := metadatatest.SetupTestTelemetry() + require.NoError(t, RegisterProcessMetrics(tel.NewTelemetrySettings())) + tel.AssertMetrics(t, []metricdata.Metrics{ + { + Name: "otelcol_process_uptime", + Description: "Uptime of the process [alpha]", + Unit: "s", + Data: metricdata.Sum[float64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[float64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_runtime_heap_alloc_bytes", + Description: "Bytes of allocated heap objects (see 'go doc runtime.MemStats.HeapAlloc') [alpha]", + Unit: "By", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_runtime_total_alloc_bytes", + Description: "Cumulative bytes allocated for heap objects (see 'go doc runtime.MemStats.TotalAlloc') [alpha]", + Unit: "By", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_runtime_total_sys_memory_bytes", + Description: "Total bytes of memory obtained from the OS (see 'go doc runtime.MemStats.Sys') [alpha]", + Unit: "By", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_cpu_seconds", + Description: "Total CPU user and system time in seconds [alpha]", + Unit: "s", + Data: metricdata.Sum[float64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: []metricdata.DataPoint[float64]{ + {}, + }, + }, + }, + { + Name: "otelcol_process_memory_rss", + Description: "Total physical memory (resident set size) [alpha]", + Unit: "By", + Data: metricdata.Gauge[int64]{ + DataPoints: []metricdata.DataPoint[int64]{ + {}, + }, + }, + }, + }, metricdatatest.IgnoreTimestamp(), metricdatatest.IgnoreValue()) }