From 326bea2549fd4d9b009a801abad0260689aba6f3 Mon Sep 17 00:00:00 2001 From: Vishal Kumar Singh Date: Sat, 16 May 2026 13:40:09 +0530 Subject: [PATCH] [connector/routing] Add feature gate to change default error_mode to ignore Add connector.routing.defaultErrorModeIgnore feature gate that when enabled changes the default error_mode from propagate to ignore. This improves resiliency by logging OTTL condition errors and continuing processing rather than dropping valid data. Fixes #48418 --- .../routing-default-error-mode-ignore.yaml | 30 ++++++++++++++++ connector/routingconnector/config.go | 3 +- connector/routingconnector/factory.go | 9 ++++- connector/routingconnector/factory_test.go | 36 +++++++++++++++++++ .../metadata/generated_feature_gates.go | 14 ++++++++ connector/routingconnector/metadata.yaml | 6 ++++ 6 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 .chloggen/routing-default-error-mode-ignore.yaml create mode 100644 connector/routingconnector/internal/metadata/generated_feature_gates.go diff --git a/.chloggen/routing-default-error-mode-ignore.yaml b/.chloggen/routing-default-error-mode-ignore.yaml new file mode 100644 index 0000000000000..889ea202052c1 --- /dev/null +++ b/.chloggen/routing-default-error-mode-ignore.yaml @@ -0,0 +1,30 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. receiver/filelog) +component: connector/routing + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add `connector.routing.defaultErrorModeIgnore` feature gate to change default `error_mode` to `ignore` + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [48418] + +# (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: | + When the feature gate is enabled, the connector defaults to `ignore` mode which preserves + valid data when an OTTL condition error occurs, improving resiliency. This is a breaking + change rolled out via feature gate to allow gradual adoption. + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# 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: [user] diff --git a/connector/routingconnector/config.go b/connector/routingconnector/config.go index ca0e7c39aafe9..47e606cbfeee7 100644 --- a/connector/routingconnector/config.go +++ b/connector/routingconnector/config.go @@ -38,7 +38,8 @@ type Config struct { // condition has an error then the payload will be routed to the default exporter. `propagate` // means the processor returns the error up the pipeline. This will result in the payload being // dropped from the collector. - // The default value is `propagate`. + // The default value is `propagate`, but when the `connector.routing.defaultErrorModeIgnore` + // feature gate is enabled, the default changes to `ignore`. ErrorMode ottl.ErrorMode `mapstructure:"error_mode"` // DefaultPipelines contains the list of pipelines to use when a more specific record can't be // found in the routing table. diff --git a/connector/routingconnector/factory.go b/connector/routingconnector/factory.go index 14356d9a52202..eac533b792afd 100644 --- a/connector/routingconnector/factory.go +++ b/connector/routingconnector/factory.go @@ -16,6 +16,13 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl" ) +func defaultErrorMode() ottl.ErrorMode { + if metadata.ConnectorRoutingDefaultErrorModeIgnoreFeatureGate.IsEnabled() { + return ottl.IgnoreError + } + return ottl.PropagateError +} + // NewFactory returns a ConnectorFactory. func NewFactory() connector.Factory { return connector.NewFactory( @@ -30,7 +37,7 @@ func NewFactory() connector.Factory { // createDefaultConfig creates the default configuration. func createDefaultConfig() component.Config { return &Config{ - ErrorMode: ottl.PropagateError, + ErrorMode: defaultErrorMode(), } } diff --git a/connector/routingconnector/factory_test.go b/connector/routingconnector/factory_test.go index 48c6333bf0bdd..5979812c714cc 100644 --- a/connector/routingconnector/factory_test.go +++ b/connector/routingconnector/factory_test.go @@ -7,13 +7,16 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "go.opentelemetry.io/collector/connector" "go.opentelemetry.io/collector/connector/connectortest" "go.opentelemetry.io/collector/consumer" "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/featuregate" "go.opentelemetry.io/collector/pipeline" "github.com/open-telemetry/opentelemetry-collector-contrib/connector/routingconnector/internal/metadata" + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl" ) func TestConnectorCreatedWithValidConfiguration(t *testing.T) { @@ -60,3 +63,36 @@ func TestCreationFailsWithIncorrectConsumer(t *testing.T) { assert.ErrorIs(t, err, errUnexpectedConsumer) assert.Nil(t, conn) } + +func TestDefaultErrorModeWithFeatureGate(t *testing.T) { + tests := []struct { + name string + featureGateEnabled bool + expectedErrorMode ottl.ErrorMode + }{ + { + name: "feature gate disabled", + featureGateEnabled: false, + expectedErrorMode: ottl.PropagateError, + }, + { + name: "feature gate enabled", + featureGateEnabled: true, + expectedErrorMode: ottl.IgnoreError, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + previousValue := metadata.ConnectorRoutingDefaultErrorModeIgnoreFeatureGate.IsEnabled() + require.NoError(t, featuregate.GlobalRegistry().Set(metadata.ConnectorRoutingDefaultErrorModeIgnoreFeatureGate.ID(), tt.featureGateEnabled)) + defer func() { + require.NoError(t, featuregate.GlobalRegistry().Set(metadata.ConnectorRoutingDefaultErrorModeIgnoreFeatureGate.ID(), previousValue)) + }() + + factory := NewFactory() + cfg := factory.CreateDefaultConfig().(*Config) + assert.Equal(t, tt.expectedErrorMode, cfg.ErrorMode) + }) + } +} diff --git a/connector/routingconnector/internal/metadata/generated_feature_gates.go b/connector/routingconnector/internal/metadata/generated_feature_gates.go new file mode 100644 index 0000000000000..4514559afbd59 --- /dev/null +++ b/connector/routingconnector/internal/metadata/generated_feature_gates.go @@ -0,0 +1,14 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/featuregate" +) + +var ConnectorRoutingDefaultErrorModeIgnoreFeatureGate = featuregate.GlobalRegistry().MustRegister( + "connector.routing.defaultErrorModeIgnore", + featuregate.StageAlpha, + featuregate.WithRegisterDescription("When enabled, the default error_mode is `ignore` instead of `propagate`."), + featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/48418"), +) diff --git a/connector/routingconnector/metadata.yaml b/connector/routingconnector/metadata.yaml index 970ba3ee58fac..0cd28bae99b11 100644 --- a/connector/routingconnector/metadata.yaml +++ b/connector/routingconnector/metadata.yaml @@ -11,6 +11,12 @@ status: emeritus: [jpkrohling, mwear] seeking_new: true +feature_gates: + - id: connector.routing.defaultErrorModeIgnore + description: When enabled, the default error_mode is `ignore` instead of `propagate`. + stage: alpha + reference_url: https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/48418 + tests: skip_lifecycle: true skip_shutdown: true