From 28c1b154bfbe85cfe2d16cddeb1f43da7c31d5f0 Mon Sep 17 00:00:00 2001 From: kaiyan-sheng Date: Wed, 21 May 2025 09:39:03 -0600 Subject: [PATCH] Use mdatagen to add a telemetry metric --- processor/ratelimitprocessor/documentation.md | 15 ++++ .../generated_component_test.go | 17 ----- .../generated_package_test.go | 17 ----- .../internal/metadata/generated_status.go | 17 ----- .../internal/metadata/generated_telemetry.go | 68 +++++++++++++++++ .../metadata/generated_telemetry_test.go | 74 +++++++++++++++++++ .../metadatatest/generated_telemetrytest.go | 38 ++++++++++ .../generated_telemetrytest_test.go | 27 +++++++ processor/ratelimitprocessor/metadata.yaml | 10 +++ 9 files changed, 232 insertions(+), 51 deletions(-) create mode 100644 processor/ratelimitprocessor/documentation.md create mode 100644 processor/ratelimitprocessor/internal/metadata/generated_telemetry.go create mode 100644 processor/ratelimitprocessor/internal/metadata/generated_telemetry_test.go create mode 100644 processor/ratelimitprocessor/internal/metadatatest/generated_telemetrytest.go create mode 100644 processor/ratelimitprocessor/internal/metadatatest/generated_telemetrytest_test.go diff --git a/processor/ratelimitprocessor/documentation.md b/processor/ratelimitprocessor/documentation.md new file mode 100644 index 000000000..592c042ad --- /dev/null +++ b/processor/ratelimitprocessor/documentation.md @@ -0,0 +1,15 @@ +[comment]: <> (Code generated by mdatagen. DO NOT EDIT.) + +# ratelimit + +## Internal Telemetry + +The following telemetry is emitted by this component. + +### otelcol_ratelimit.requests + +Number of rate-limiting requests + +| Unit | Metric Type | Value Type | Monotonic | +| ---- | ----------- | ---------- | --------- | +| {requests} | Sum | Int | true | diff --git a/processor/ratelimitprocessor/generated_component_test.go b/processor/ratelimitprocessor/generated_component_test.go index f390bedf5..e6cfb74a2 100644 --- a/processor/ratelimitprocessor/generated_component_test.go +++ b/processor/ratelimitprocessor/generated_component_test.go @@ -1,20 +1,3 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you under -// the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - // Code generated by mdatagen. DO NOT EDIT. package ratelimitprocessor diff --git a/processor/ratelimitprocessor/generated_package_test.go b/processor/ratelimitprocessor/generated_package_test.go index 013e35bd8..fda4692d5 100644 --- a/processor/ratelimitprocessor/generated_package_test.go +++ b/processor/ratelimitprocessor/generated_package_test.go @@ -1,20 +1,3 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you under -// the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - // Code generated by mdatagen. DO NOT EDIT. package ratelimitprocessor diff --git a/processor/ratelimitprocessor/internal/metadata/generated_status.go b/processor/ratelimitprocessor/internal/metadata/generated_status.go index 2c4737dae..284c17703 100644 --- a/processor/ratelimitprocessor/internal/metadata/generated_status.go +++ b/processor/ratelimitprocessor/internal/metadata/generated_status.go @@ -1,20 +1,3 @@ -// Licensed to Elasticsearch B.V. under one or more contributor -// license agreements. See the NOTICE file distributed with -// this work for additional information regarding copyright -// ownership. Elasticsearch B.V. licenses this file to you under -// the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - // Code generated by mdatagen. DO NOT EDIT. package metadata diff --git a/processor/ratelimitprocessor/internal/metadata/generated_telemetry.go b/processor/ratelimitprocessor/internal/metadata/generated_telemetry.go new file mode 100644 index 000000000..f1033bcb9 --- /dev/null +++ b/processor/ratelimitprocessor/internal/metadata/generated_telemetry.go @@ -0,0 +1,68 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "errors" + "sync" + + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/trace" + + "go.opentelemetry.io/collector/component" +) + +func Meter(settings component.TelemetrySettings) metric.Meter { + return settings.MeterProvider.Meter("github.com/elastic/opentelemetry-collector-components/processor/ratelimitprocessor") +} + +func Tracer(settings component.TelemetrySettings) trace.Tracer { + return settings.TracerProvider.Tracer("github.com/elastic/opentelemetry-collector-components/processor/ratelimitprocessor") +} + +// TelemetryBuilder provides an interface for components to report telemetry +// as defined in metadata and user config. +type TelemetryBuilder struct { + meter metric.Meter + mu sync.Mutex + registrations []metric.Registration + RatelimitRequests metric.Int64Counter +} + +// TelemetryBuilderOption applies changes to default builder. +type TelemetryBuilderOption interface { + apply(*TelemetryBuilder) +} + +type telemetryBuilderOptionFunc func(mb *TelemetryBuilder) + +func (tbof telemetryBuilderOptionFunc) apply(mb *TelemetryBuilder) { + tbof(mb) +} + +// Shutdown unregister all registered callbacks for async instruments. +func (builder *TelemetryBuilder) Shutdown() { + builder.mu.Lock() + defer builder.mu.Unlock() + for _, reg := range builder.registrations { + reg.Unregister() + } +} + +// 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{} + for _, op := range options { + op.apply(&builder) + } + builder.meter = Meter(settings) + var err, errs error + builder.RatelimitRequests, err = builder.meter.Int64Counter( + "otelcol_ratelimit.requests", + metric.WithDescription("Number of rate-limiting requests"), + metric.WithUnit("{requests}"), + ) + errs = errors.Join(errs, err) + return &builder, errs +} diff --git a/processor/ratelimitprocessor/internal/metadata/generated_telemetry_test.go b/processor/ratelimitprocessor/internal/metadata/generated_telemetry_test.go new file mode 100644 index 000000000..0f49a7b61 --- /dev/null +++ b/processor/ratelimitprocessor/internal/metadata/generated_telemetry_test.go @@ -0,0 +1,74 @@ +// 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" + "go.opentelemetry.io/collector/component/componenttest" +) + +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, "github.com/elastic/opentelemetry-collector-components/processor/ratelimitprocessor", m.name) + } else { + require.Fail(t, "returned Meter not mockMeter") + } + + tracer := Tracer(set) + if m, ok := tracer.(mockTracer); ok { + require.Equal(t, "github.com/elastic/opentelemetry-collector-components/processor/ratelimitprocessor", m.name) + } else { + require.Fail(t, "returned Meter not mockTracer") + } +} + +func TestNewTelemetryBuilder(t *testing.T) { + set := componenttest.NewNopTelemetrySettings() + applied := false + _, err := NewTelemetryBuilder(set, telemetryBuilderOptionFunc(func(b *TelemetryBuilder) { + applied = true + })) + require.NoError(t, err) + require.True(t, applied) +} diff --git a/processor/ratelimitprocessor/internal/metadatatest/generated_telemetrytest.go b/processor/ratelimitprocessor/internal/metadatatest/generated_telemetrytest.go new file mode 100644 index 000000000..8e0f23275 --- /dev/null +++ b/processor/ratelimitprocessor/internal/metadatatest/generated_telemetrytest.go @@ -0,0 +1,38 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadatatest + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/processor" + "go.opentelemetry.io/collector/processor/processortest" + "go.opentelemetry.io/otel/sdk/metric/metricdata" + "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" +) + +func NewSettings(tt *componenttest.Telemetry) processor.Settings { + set := processortest.NewNopSettings(processortest.NopType) + set.ID = component.NewID(component.MustNewType("ratelimit")) + set.TelemetrySettings = tt.NewTelemetrySettings() + return set +} + +func AssertEqualRatelimitRequests(t *testing.T, tt *componenttest.Telemetry, dps []metricdata.DataPoint[int64], opts ...metricdatatest.Option) { + want := metricdata.Metrics{ + Name: "otelcol_ratelimit.requests", + Description: "Number of rate-limiting requests", + Unit: "{requests}", + Data: metricdata.Sum[int64]{ + Temporality: metricdata.CumulativeTemporality, + IsMonotonic: true, + DataPoints: dps, + }, + } + got, err := tt.GetMetric("otelcol_ratelimit.requests") + require.NoError(t, err) + metricdatatest.AssertEqual(t, want, got, opts...) +} diff --git a/processor/ratelimitprocessor/internal/metadatatest/generated_telemetrytest_test.go b/processor/ratelimitprocessor/internal/metadatatest/generated_telemetrytest_test.go new file mode 100644 index 000000000..e67ae16fa --- /dev/null +++ b/processor/ratelimitprocessor/internal/metadatatest/generated_telemetrytest_test.go @@ -0,0 +1,27 @@ +// 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/component/componenttest" +) + +func TestSetupTelemetry(t *testing.T) { + testTel := componenttest.NewTelemetry() + tb, err := metadata.NewTelemetryBuilder(testTel.NewTelemetrySettings()) + require.NoError(t, err) + defer tb.Shutdown() + tb.RatelimitRequests.Add(context.Background(), 1) + AssertEqualRatelimitRequests(t, testTel, + []metricdata.DataPoint[int64]{{Value: 1}}, + metricdatatest.IgnoreTimestamp()) + + require.NoError(t, testTel.Shutdown(context.Background())) +} diff --git a/processor/ratelimitprocessor/metadata.yaml b/processor/ratelimitprocessor/metadata.yaml index 45e4a57f7..65f3b2a02 100644 --- a/processor/ratelimitprocessor/metadata.yaml +++ b/processor/ratelimitprocessor/metadata.yaml @@ -10,3 +10,13 @@ tests: config: rate: 1 burst: 1 + +telemetry: + metrics: + ratelimit.requests: + enabled: true + description: Number of rate-limiting requests + unit: "{requests}" + sum: + value_type: int + monotonic: true