diff --git a/.chloggen/addretrysetvalidation.yaml b/.chloggen/addretrysetvalidation.yaml new file mode 100755 index 00000000000..db6b49d0309 --- /dev/null +++ b/.chloggen/addretrysetvalidation.yaml @@ -0,0 +1,13 @@ +# 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. otlpreceiver) +component: "exporterhelper" + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: "Add RetrySettings validation function" + +# One or more tracking issues or pull requests related to the change +issues: [9089] diff --git a/exporter/exporterhelper/retry_sender.go b/exporter/exporterhelper/retry_sender.go index 82ffce4389a..e437d50df0b 100644 --- a/exporter/exporterhelper/retry_sender.go +++ b/exporter/exporterhelper/retry_sender.go @@ -39,6 +39,28 @@ type RetrySettings struct { MaxElapsedTime time.Duration `mapstructure:"max_elapsed_time"` } +func (cfg *RetrySettings) Validate() error { + if !cfg.Enabled { + return nil + } + if cfg.InitialInterval < 0 { + return errors.New("'initial_interval' must be non-negative") + } + if cfg.RandomizationFactor < 0 || cfg.RandomizationFactor > 1 { + return errors.New("'randomization_factor' must be within [0, 1]") + } + if cfg.Multiplier <= 0 { + return errors.New("'multiplier' must be positive") + } + if cfg.MaxInterval < 0 { + return errors.New("'max_interval' must be non-negative") + } + if cfg.MaxElapsedTime < 0 { + return errors.New("'max_elapsed' time must be non-negative") + } + return nil +} + // NewDefaultRetrySettings returns the default settings for RetrySettings. func NewDefaultRetrySettings() RetrySettings { return RetrySettings{ diff --git a/exporter/exporterhelper/retry_sender_test.go b/exporter/exporterhelper/retry_sender_test.go index 9ecbb71906b..9169858c091 100644 --- a/exporter/exporterhelper/retry_sender_test.go +++ b/exporter/exporterhelper/retry_sender_test.go @@ -404,3 +404,66 @@ func tagsMatchLabelKeys(tags []tag.Tag, keys []metricdata.LabelKey, labels []met } return true } + +func TestNewDefaultRetrySettings(t *testing.T) { + cfg := NewDefaultRetrySettings() + assert.NoError(t, cfg.Validate()) + assert.Equal(t, + RetrySettings{ + Enabled: true, + InitialInterval: 5 * time.Second, + RandomizationFactor: 0.5, + Multiplier: 1.5, + MaxInterval: 30 * time.Second, + MaxElapsedTime: 5 * time.Minute, + }, cfg) +} + +func TestInvalidInitialInterval(t *testing.T) { + cfg := NewDefaultRetrySettings() + assert.NoError(t, cfg.Validate()) + cfg.InitialInterval = -1 + assert.Error(t, cfg.Validate()) +} + +func TestInvalidRandomizationFactor(t *testing.T) { + cfg := NewDefaultRetrySettings() + assert.NoError(t, cfg.Validate()) + cfg.RandomizationFactor = -1 + assert.Error(t, cfg.Validate()) + cfg.RandomizationFactor = 2 + assert.Error(t, cfg.Validate()) +} + +func TestInvalidMultiplier(t *testing.T) { + cfg := NewDefaultRetrySettings() + assert.NoError(t, cfg.Validate()) + cfg.Multiplier = 0 + assert.Error(t, cfg.Validate()) +} + +func TestInvalidMaxInterval(t *testing.T) { + cfg := NewDefaultRetrySettings() + assert.NoError(t, cfg.Validate()) + cfg.MaxInterval = -1 + assert.Error(t, cfg.Validate()) +} + +func TestInvalidMaxElapsedTime(t *testing.T) { + cfg := NewDefaultRetrySettings() + assert.NoError(t, cfg.Validate()) + cfg.MaxElapsedTime = -1 + assert.Error(t, cfg.Validate()) +} + +func TestDisabledWithInvalidValues(t *testing.T) { + cfg := RetrySettings{ + Enabled: false, + InitialInterval: -1, + RandomizationFactor: -1, + Multiplier: 0, + MaxInterval: -1, + MaxElapsedTime: -1, + } + assert.NoError(t, cfg.Validate()) +}