From 306c9394155cf362cca37b28e55648a041a15dca Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 6 Jan 2025 10:06:46 -0800 Subject: [PATCH] Deprecate component_test in favor of metadatatest (#11812) The main idea behind this is that the test helpers were generated in the main package, hard to find and understand and also impossible to use outside the main package, see the [service/internal/proctelemetry/process_telemetry_test.go](https://github.com/open-telemetry/opentelemetry-collector/compare/main...bogdandrutu:opentelemetry-collector:dep-comp-test?expand=1#diff-ed642eb1c968a9308a07e87292f77af1e0830a7af2d87111c5abacde4fc87446). Signed-off-by: Bogdan Drutu --- .chloggen/dep-comp-test.yaml | 25 +++ cmd/mdatagen/internal/command.go | 6 + .../internal/embedded_templates_test.go | 2 + .../generated_component_telemetry_test.go | 2 + .../internal/metadata/generated_telemetry.go | 4 +- .../metadatatest/generated_telemetrytest.go | 83 +++++++++ .../generated_telemetrytest_test.go | 65 +++++++ .../internal/samplereceiver/metrics_test.go | 12 +- .../component_telemetry_test.go.tmpl | 2 + .../internal/templates/telemetry.go.tmpl | 5 +- .../internal/templates/telemetry_test.go.tmpl | 1 - .../internal/templates/telemetrytest.go.tmpl | 89 ++++++++++ .../templates/telemetrytest_test.go.tmpl | 74 ++++++++ .../generated_component_telemetry_test.go | 2 + .../internal/metadata/generated_telemetry.go | 4 +- .../metadatatest/generated_telemetrytest.go | 83 +++++++++ .../generated_telemetrytest_test.go | 144 +++++++++++++++ .../batchprocessor/batch_processor_test.go | 26 +-- .../generated_component_telemetry_test.go | 2 + .../internal/metadata/generated_telemetry.go | 4 +- .../metadatatest/generated_telemetrytest.go | 83 +++++++++ .../generated_telemetrytest_test.go | 90 ++++++++++ .../generated_component_telemetry_test.go | 2 + .../internal/metadata/generated_telemetry.go | 4 +- .../metadatatest/generated_telemetrytest.go | 83 +++++++++ .../generated_telemetrytest_test.go | 105 +++++++++++ .../memorylimiter_test.go | 8 +- .../generated_component_telemetry_test.go | 2 + .../internal/metadata/generated_telemetry.go | 4 +- .../metadatatest/generated_telemetrytest.go | 83 +++++++++ .../generated_telemetrytest_test.go | 53 ++++++ processor/processorhelper/logs_test.go | 14 +- processor/processorhelper/metrics_test.go | 14 +- processor/processorhelper/traces_test.go | 14 +- .../generated_component_telemetry_test.go | 2 + .../internal/metadata/generated_telemetry.go | 4 +- .../metadatatest/generated_telemetrytest.go | 83 +++++++++ .../generated_telemetrytest_test.go | 105 +++++++++++ .../generated_component_telemetry_test.go | 2 + .../internal/metadata/generated_telemetry.go | 4 +- .../metadatatest/generated_telemetrytest.go | 83 +++++++++ .../generated_telemetrytest_test.go | 53 ++++++ service/generated_component_telemetry_test.go | 2 + .../internal/metadata/generated_telemetry.go | 4 +- .../metadatatest/generated_telemetrytest.go | 75 ++++++++ .../generated_telemetrytest_test.go | 99 +++++++++++ .../process_telemetry_linux_test.go | 108 ++++++++---- .../proctelemetry/process_telemetry_test.go | 164 ++++++++---------- 48 files changed, 1801 insertions(+), 181 deletions(-) create mode 100644 .chloggen/dep-comp-test.yaml create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest.go create mode 100644 cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest_test.go create mode 100644 cmd/mdatagen/internal/templates/telemetrytest.go.tmpl create mode 100644 cmd/mdatagen/internal/templates/telemetrytest_test.go.tmpl create mode 100644 exporter/exporterhelper/internal/metadatatest/generated_telemetrytest.go create mode 100644 exporter/exporterhelper/internal/metadatatest/generated_telemetrytest_test.go create mode 100644 processor/batchprocessor/internal/metadatatest/generated_telemetrytest.go create mode 100644 processor/batchprocessor/internal/metadatatest/generated_telemetrytest_test.go create mode 100644 processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest.go create mode 100644 processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest_test.go create mode 100644 processor/processorhelper/internal/metadatatest/generated_telemetrytest.go create mode 100644 processor/processorhelper/internal/metadatatest/generated_telemetrytest_test.go create mode 100644 receiver/receiverhelper/internal/metadatatest/generated_telemetrytest.go create mode 100644 receiver/receiverhelper/internal/metadatatest/generated_telemetrytest_test.go create mode 100644 scraper/scraperhelper/internal/metadatatest/generated_telemetrytest.go create mode 100644 scraper/scraperhelper/internal/metadatatest/generated_telemetrytest_test.go create mode 100644 service/internal/metadatatest/generated_telemetrytest.go create mode 100644 service/internal/metadatatest/generated_telemetrytest_test.go 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 706a2985411..5ad6c74becf 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, 0o700); 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, 0o700); 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..0c3c1f4293b 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.117.0] use metadatatest.Telemetry 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.SetupTelemetry 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 99c7017b575..b44d14a8c70 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..1b9b04ca6b3 --- /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 Telemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTelemetry() Telemetry { + reader := sdkmetric.NewManualReader() + return Telemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *Telemetry) NewSettings() receiver.Settings { + set := receivertest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("sample")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *Telemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *Telemetry) 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 *Telemetry) 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..8783cd7f6d0 --- /dev/null +++ b/cmd/mdatagen/internal/samplereceiver/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,65 @@ +// 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 TestSetupTelemetry(t *testing.T) { + testTel := SetupTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + metadata.WithProcessRuntimeTotalAllocBytesCallback(func() int64 { return 1 }), + ) + require.NoError(t, err) + require.NotNil(t, tb) + 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..95e620f8c77 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.SetupTelemetry() 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..38dc4166eb1 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.117.0] use metadatatest.Telemetry 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.SetupTelemetry 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 3f365e45167..e48ecdf7215 100644 --- a/cmd/mdatagen/internal/templates/telemetry.go.tmpl +++ b/cmd/mdatagen/internal/templates/telemetry.go.tmpl @@ -14,6 +14,9 @@ import ( {{- end }} "go.opentelemetry.io/otel/metric" + {{- if .Telemetry.Metrics }} + noopmetric "go.opentelemetry.io/otel/metric/noop" + {{- end }} "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/collector/component" @@ -128,7 +131,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..d36e655e018 --- /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 Telemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTelemetry() Telemetry { + reader := sdkmetric.NewManualReader() + return Telemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} + +{{- if or isConnector isExporter isExtension isProcessor isReceiver }} +func (tt *Telemetry) 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 *Telemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *Telemetry) 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 *Telemetry) 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..87abd5ceb55 --- /dev/null +++ b/cmd/mdatagen/internal/templates/telemetrytest_test.go.tmpl @@ -0,0 +1,74 @@ +// 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 TestSetupTelemetry(t *testing.T) { + testTel := SetupTelemetry() + 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) + require.NotNil(t, tb) + {{- 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..ff1e7f2ea29 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.117.0] use metadatatest.Telemetry 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.SetupTelemetry 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 41bea2f8ce1..bef767b0a89 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..7ccda226232 --- /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 Telemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTelemetry() Telemetry { + reader := sdkmetric.NewManualReader() + return Telemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *Telemetry) NewSettings() exporter.Settings { + set := exportertest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("exporterhelper")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *Telemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *Telemetry) 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 *Telemetry) 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..ba7584abdf3 --- /dev/null +++ b/exporter/exporterhelper/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,144 @@ +// 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 TestSetupTelemetry(t *testing.T) { + testTel := SetupTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + ) + require.NoError(t, err) + require.NotNil(t, tb) + 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 c4fa2b91476..7ced3bdc138 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.SetupTelemetry() 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", @@ -280,7 +282,7 @@ func TestBatchProcessorSentBySize(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) require.NoError(t, tel.Shutdown(context.Background())) } @@ -293,7 +295,7 @@ func TestBatchProcessorSentBySizeWithMaxSize(t *testing.T) { totalSpans = requestCount * spansPerRequest ) - tel := setupTestTelemetry() + tel := metadatatest.SetupTelemetry() sizer := &ptrace.ProtoMarshaler{} sink := new(consumertest.TracesSink) cfg := createDefaultConfig().(*Config) @@ -334,7 +336,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", @@ -422,7 +424,7 @@ func TestBatchProcessorSentBySizeWithMaxSize(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) require.NoError(t, tel.Shutdown(context.Background())) } @@ -547,7 +549,7 @@ func TestBatchMetricProcessor_ReceivingData(t *testing.T) { } func TestBatchMetricProcessorBatchSize(t *testing.T) { - tel := setupTestTelemetry() + tel := metadatatest.SetupTelemetry() sizer := &pmetric.ProtoMarshaler{} // Instantiate the batch processor with low config values to test data @@ -594,7 +596,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", @@ -667,7 +669,7 @@ func TestBatchMetricProcessorBatchSize(t *testing.T) { }, }, }, - }) + }, metricdatatest.IgnoreTimestamp()) require.NoError(t, tel.Shutdown(context.Background())) } @@ -925,7 +927,7 @@ func TestBatchLogProcessor_ReceivingData(t *testing.T) { } func TestBatchLogProcessor_BatchSize(t *testing.T) { - tel := setupTestTelemetry() + tel := metadatatest.SetupTelemetry() sizer := &plog.ProtoMarshaler{} // Instantiate the batch processor with low config values to test data @@ -970,7 +972,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", @@ -1043,7 +1045,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..c7f48450510 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.117.0] use metadatatest.Telemetry 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.SetupTelemetry 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..e86dfd7f10a --- /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 Telemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTelemetry() Telemetry { + reader := sdkmetric.NewManualReader() + return Telemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *Telemetry) NewSettings() processor.Settings { + set := processortest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("batch")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *Telemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *Telemetry) 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 *Telemetry) 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..9a875038c5a --- /dev/null +++ b/processor/batchprocessor/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,90 @@ +// 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 TestSetupTelemetry(t *testing.T) { + testTel := SetupTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + metadata.WithProcessorBatchMetadataCardinalityCallback(func() int64 { return 1 }), + ) + require.NoError(t, err) + require.NotNil(t, tb) + 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..bd23d9cd600 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.117.0] use metadatatest.Telemetry 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.SetupTelemetry 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..88f39953a15 --- /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 Telemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTelemetry() Telemetry { + reader := sdkmetric.NewManualReader() + return Telemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *Telemetry) NewSettings() processor.Settings { + set := processortest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("memory_limiter")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *Telemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *Telemetry) 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 *Telemetry) 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..8e87e88ac5d --- /dev/null +++ b/processor/memorylimiterprocessor/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,105 @@ +// 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 TestSetupTelemetry(t *testing.T) { + testTel := SetupTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + ) + require.NoError(t, err) + require.NotNil(t, tb) + 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..e6ac7da5819 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.SetupTelemetry() 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..1ce9c014794 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.117.0] use metadatatest.Telemetry 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.SetupTelemetry 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..626e1d4a299 --- /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 Telemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTelemetry() Telemetry { + reader := sdkmetric.NewManualReader() + return Telemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *Telemetry) NewSettings() processor.Settings { + set := processortest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("processorhelper")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *Telemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *Telemetry) 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 *Telemetry) 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..5279286a0e9 --- /dev/null +++ b/processor/processorhelper/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,53 @@ +// 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 TestSetupTelemetry(t *testing.T) { + testTel := SetupTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + ) + require.NoError(t, err) + require.NotNil(t, tb) + 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..58ba972c603 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.SetupTelemetry() 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.SetupTelemetry() 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..537c7c564f8 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.SetupTelemetry() 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.SetupTelemetry() 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..00824aae1d3 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.SetupTelemetry() 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.SetupTelemetry() 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..3c63a2f108b 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.117.0] use metadatatest.Telemetry 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.SetupTelemetry 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..de3d278a236 --- /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 Telemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTelemetry() Telemetry { + reader := sdkmetric.NewManualReader() + return Telemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *Telemetry) NewSettings() receiver.Settings { + set := receivertest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("receiverhelper")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *Telemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *Telemetry) 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 *Telemetry) 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..96eb0b1956a --- /dev/null +++ b/receiver/receiverhelper/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,105 @@ +// 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 TestSetupTelemetry(t *testing.T) { + testTel := SetupTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + ) + require.NoError(t, err) + require.NotNil(t, tb) + 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/scraper/scraperhelper/generated_component_telemetry_test.go b/scraper/scraperhelper/generated_component_telemetry_test.go index a60c59fe220..8672f4e1f6e 100644 --- a/scraper/scraperhelper/generated_component_telemetry_test.go +++ b/scraper/scraperhelper/generated_component_telemetry_test.go @@ -18,6 +18,7 @@ import ( "go.opentelemetry.io/collector/receiver/receivertest" ) +// Deprecated: [v0.117.0] use metadatatest.Telemetry 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.SetupTelemetry func setupTestTelemetry() componentTestTelemetry { reader := sdkmetric.NewManualReader() return componentTestTelemetry{ diff --git a/scraper/scraperhelper/internal/metadata/generated_telemetry.go b/scraper/scraperhelper/internal/metadata/generated_telemetry.go index 2ae72fee03b..7999eab6658 100644 --- a/scraper/scraperhelper/internal/metadata/generated_telemetry.go +++ b/scraper/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/scraper/scraperhelper/internal/metadatatest/generated_telemetrytest.go b/scraper/scraperhelper/internal/metadatatest/generated_telemetrytest.go new file mode 100644 index 00000000000..26236d96633 --- /dev/null +++ b/scraper/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 Telemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTelemetry() Telemetry { + reader := sdkmetric.NewManualReader() + return Telemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} +func (tt *Telemetry) NewSettings() receiver.Settings { + set := receivertest.NewNopSettings() + set.ID = component.NewID(component.MustNewType("scraperhelper")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func (tt *Telemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *Telemetry) 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 *Telemetry) 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/scraper/scraperhelper/internal/metadatatest/generated_telemetrytest_test.go b/scraper/scraperhelper/internal/metadatatest/generated_telemetrytest_test.go new file mode 100644 index 00000000000..54f85342420 --- /dev/null +++ b/scraper/scraperhelper/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,53 @@ +// 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/scraper/scraperhelper/internal/metadata" +) + +func TestSetupTelemetry(t *testing.T) { + testTel := SetupTelemetry() + tb, err := metadata.NewTelemetryBuilder( + testTel.NewTelemetrySettings(), + ) + require.NoError(t, err) + require.NotNil(t, tb) + 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..346198dff22 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.117.0] use metadatatest.Telemetry 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.SetupTelemetry 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..ad22057271b --- /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 Telemetry struct { + reader *sdkmetric.ManualReader + meterProvider *sdkmetric.MeterProvider +} + +func SetupTelemetry() Telemetry { + reader := sdkmetric.NewManualReader() + return Telemetry{ + reader: reader, + meterProvider: sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)), + } +} + +func (tt *Telemetry) NewTelemetrySettings() component.TelemetrySettings { + set := componenttest.NewNopTelemetrySettings() + set.MeterProvider = tt.meterProvider + set.MetricsLevel = configtelemetry.LevelDetailed + return set +} + +func (tt *Telemetry) 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 *Telemetry) 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..70f39cdcd0e --- /dev/null +++ b/service/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,99 @@ +// 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 TestSetupTelemetry(t *testing.T) { + testTel := SetupTelemetry() + 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) + require.NotNil(t, tb) + + 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..30c94ecfd60 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.SetupTelemetry() + 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..f86b233db2e 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.SetupTelemetry() + 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()) }