diff --git a/receiver/scraperhelper/doc.go b/receiver/scraperhelper/doc.go index f936c187381..a1e5cb26f1d 100644 --- a/receiver/scraperhelper/doc.go +++ b/receiver/scraperhelper/doc.go @@ -1,5 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +//go:generate mdatagen metadata.yaml + // Package scraperhelper provides utilities for scrapers. package scraperhelper // import "go.opentelemetry.io/collector/receiver/scraperhelper" diff --git a/receiver/scraperhelper/package_test.go b/receiver/scraperhelper/generated_package_test.go similarity index 61% rename from receiver/scraperhelper/package_test.go rename to receiver/scraperhelper/generated_package_test.go index a9a536a78d9..d8c3fa42f6d 100644 --- a/receiver/scraperhelper/package_test.go +++ b/receiver/scraperhelper/generated_package_test.go @@ -1,12 +1,10 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 +// Code generated by mdatagen. DO NOT EDIT. package scraperhelper import ( - "testing" - "go.uber.org/goleak" + "testing" ) func TestMain(m *testing.M) { diff --git a/receiver/scraperhelper/internal/metadata/generated_telemetry.go b/receiver/scraperhelper/internal/metadata/generated_telemetry.go new file mode 100644 index 00000000000..01f3d11ad0b --- /dev/null +++ b/receiver/scraperhelper/internal/metadata/generated_telemetry.go @@ -0,0 +1,50 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "errors" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("go.opentelemetry.io/collector/receiver/scraperhelper") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("go.opentelemetry.io/collector/receiver/scraperhelper") +} + +// TelemetryBuilder provides an interface for components to report telemetry +// as defined in metadata and user config. +type TelemetryBuilder struct { + ScraperErroredMetricPoints metric.Int64Counter + ScraperScrapedMetricPoints metric.Int64Counter +} + +// telemetryBuilderOption applies changes to default builder. +type telemetryBuilderOption func(*TelemetryBuilder) + +// NewTelemetryBuilder provides a struct with methods to update all internal telemetry +// for a component +func NewTelemetryBuilder(settings component.TelemetrySettings, options ...telemetryBuilderOption) (*TelemetryBuilder, error) { + builder := TelemetryBuilder{} + var err, errs error + meter := Meter(settings) + builder.ScraperErroredMetricPoints, err = meter.Int64Counter( + "scraper_errored_metric_points", + metric.WithDescription("Number of metric points that were unable to be scraped."), + metric.WithUnit("1"), + ) + errs = errors.Join(errs, err) + builder.ScraperScrapedMetricPoints, err = meter.Int64Counter( + "scraper_scraped_metric_points", + metric.WithDescription("Number of metric points successfully scraped."), + metric.WithUnit("1"), + ) + errs = errors.Join(errs, err) + return &builder, errs +} diff --git a/receiver/scraperhelper/internal/metadata/generated_telemetry_test.go b/receiver/scraperhelper/internal/metadata/generated_telemetry_test.go new file mode 100644 index 00000000000..d182ec9776e --- /dev/null +++ b/receiver/scraperhelper/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,63 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/metric" + embeddedmetric "go.opentelemetry.io/otel/metric/embedded" + noopmetric "go.opentelemetry.io/otel/metric/noop" + "go.opentelemetry.io/otel/trace" + embeddedtrace "go.opentelemetry.io/otel/trace/embedded" + nooptrace "go.opentelemetry.io/otel/trace/noop" + + "go.opentelemetry.io/collector/component" +) + +type mockMeter struct { + noopmetric.Meter + name string +} +type mockMeterProvider struct { + embeddedmetric.MeterProvider +} + +func (m mockMeterProvider) Meter(name string, opts ...metric.MeterOption) metric.Meter { + return mockMeter{name: name} +} + +type mockTracer struct { + nooptrace.Tracer + name string +} + +type mockTracerProvider struct { + embeddedtrace.TracerProvider +} + +func (m mockTracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer { + return mockTracer{name: name} +} + +func TestProviders(t *testing.T) { + set := component.TelemetrySettings{ + MeterProvider: mockMeterProvider{}, + TracerProvider: mockTracerProvider{}, + } + + meter := Meter(set) + if m, ok := meter.(mockMeter); ok { + require.Equal(t, "go.opentelemetry.io/collector/receiver/scraperhelper", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "go.opentelemetry.io/collector/receiver/scraperhelper", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} diff --git a/receiver/scraperhelper/metadata.yaml b/receiver/scraperhelper/metadata.yaml new file mode 100644 index 00000000000..7d084ca2b45 --- /dev/null +++ b/receiver/scraperhelper/metadata.yaml @@ -0,0 +1,25 @@ +type: scraperhelper + +status: + class: pkg + stability: + beta: [traces, metrics, logs] + distributions: [core, contrib] + +telemetry: + metrics: + scraper_scraped_metric_points: + enabled: true + description: Number of metric points successfully scraped. + unit: 1 + sum: + value_type: int + monotonic: true + + scraper_errored_metric_points: + enabled: true + description: Number of metric points that were unable to be scraped. + unit: 1 + sum: + value_type: int + monotonic: true \ No newline at end of file diff --git a/receiver/scraperhelper/obsreport.go b/receiver/scraperhelper/obsreport.go index 89ad80fdc08..bea7d233be8 100644 --- a/receiver/scraperhelper/obsreport.go +++ b/receiver/scraperhelper/obsreport.go @@ -11,7 +11,6 @@ import ( "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/trace" - "go.uber.org/multierr" "go.uber.org/zap" "go.opentelemetry.io/collector/component" @@ -19,6 +18,7 @@ import ( "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" "go.opentelemetry.io/collector/receiver" "go.opentelemetry.io/collector/receiver/scrapererror" + "go.opentelemetry.io/collector/receiver/scraperhelper/internal/metadata" ) var ( @@ -34,9 +34,8 @@ type ObsReport struct { logger *zap.Logger - otelAttrs []attribute.KeyValue - scrapedMetricsPoints metric.Int64Counter - erroredMetricsPoints metric.Int64Counter + otelAttrs []attribute.KeyValue + telemetryBuilder *metadata.TelemetryBuilder } // ObsReportSettings are settings for creating an ObsReport. @@ -52,7 +51,11 @@ func NewObsReport(cfg ObsReportSettings) (*ObsReport, error) { } func newScraper(cfg ObsReportSettings) (*ObsReport, error) { - scraper := &ObsReport{ + telemetryBuilder, err := metadata.NewTelemetryBuilder(cfg.ReceiverCreateSettings.TelemetrySettings) + if err != nil { + return nil, err + } + return &ObsReport{ level: cfg.ReceiverCreateSettings.TelemetrySettings.MetricsLevel, receiverID: cfg.ReceiverID, scraper: cfg.Scraper, @@ -63,35 +66,8 @@ func newScraper(cfg ObsReportSettings) (*ObsReport, error) { attribute.String(obsmetrics.ReceiverKey, cfg.ReceiverID.String()), attribute.String(obsmetrics.ScraperKey, cfg.Scraper.String()), }, - } - - if err := scraper.createOtelMetrics(cfg); err != nil { - return nil, err - } - - return scraper, nil -} - -func (s *ObsReport) createOtelMetrics(cfg ObsReportSettings) error { - meter := cfg.ReceiverCreateSettings.MeterProvider.Meter(scraperScope) - - var errors, err error - - s.scrapedMetricsPoints, err = meter.Int64Counter( - obsmetrics.ScraperPrefix+obsmetrics.ScrapedMetricPointsKey, - metric.WithDescription("Number of metric points successfully scraped."), - metric.WithUnit("1"), - ) - errors = multierr.Append(errors, err) - - s.erroredMetricsPoints, err = meter.Int64Counter( - obsmetrics.ScraperPrefix+obsmetrics.ErroredMetricPointsKey, - metric.WithDescription("Number of metric points that were unable to be scraped."), - metric.WithUnit("1"), - ) - errors = multierr.Append(errors, err) - - return errors + telemetryBuilder: telemetryBuilder, + }, nil } // StartMetricsOp is called when a scrape operation is started. The @@ -144,6 +120,6 @@ func (s *ObsReport) EndMetricsOp( } func (s *ObsReport) recordMetrics(scraperCtx context.Context, numScrapedMetrics, numErroredMetrics int) { - s.scrapedMetricsPoints.Add(scraperCtx, int64(numScrapedMetrics), metric.WithAttributes(s.otelAttrs...)) - s.erroredMetricsPoints.Add(scraperCtx, int64(numErroredMetrics), metric.WithAttributes(s.otelAttrs...)) + s.telemetryBuilder.ScraperScrapedMetricPoints.Add(scraperCtx, int64(numScrapedMetrics), metric.WithAttributes(s.otelAttrs...)) + s.telemetryBuilder.ScraperErroredMetricPoints.Add(scraperCtx, int64(numErroredMetrics), metric.WithAttributes(s.otelAttrs...)) }