From c6faf3d3b4186f4e19f7d1fddbf5d67048822d97 Mon Sep 17 00:00:00 2001 From: Nico Vinzens Date: Mon, 20 Dec 2021 18:16:23 +0100 Subject: [PATCH] feat: adds optional list of non retryable http statuscodes to http output plugin (#10186) --- plugins/outputs/http/README.md | 3 +++ plugins/outputs/http/http.go | 24 ++++++++++++++++-------- plugins/outputs/http/http_test.go | 16 +++++++++++++++- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/plugins/outputs/http/README.md b/plugins/outputs/http/README.md index 8f902acd9..ef4e12fee 100644 --- a/plugins/outputs/http/README.md +++ b/plugins/outputs/http/README.md @@ -89,6 +89,9 @@ batch format by default. #role_session_name = "" #profile = "" #shared_credential_file = "" + + ## Optional list of statuscodes (<200 or >300) upon which requests should not be retried + # non_retryable_statuscodes = [409, 413] ``` ### Optional Cookie Authentication Settings diff --git a/plugins/outputs/http/http.go b/plugins/outputs/http/http.go index 0ba5257ba..12c6ded9f 100644 --- a/plugins/outputs/http/http.go +++ b/plugins/outputs/http/http.go @@ -116,14 +116,15 @@ const ( ) type HTTP struct { - URL string `toml:"url"` - Method string `toml:"method"` - Username string `toml:"username"` - Password string `toml:"password"` - Headers map[string]string `toml:"headers"` - ContentEncoding string `toml:"content_encoding"` - UseBatchFormat bool `toml:"use_batch_format"` - AwsService string `toml:"aws_service"` + URL string `toml:"url"` + Method string `toml:"method"` + Username string `toml:"username"` + Password string `toml:"password"` + Headers map[string]string `toml:"headers"` + ContentEncoding string `toml:"content_encoding"` + UseBatchFormat bool `toml:"use_batch_format"` + AwsService string `toml:"aws_service"` + NonRetryableStatusCodes []int `toml:"non_retryable_statuscodes"` httpconfig.HTTPClientConfig Log telegraf.Logger `toml:"-"` @@ -277,6 +278,13 @@ func (h *HTTP) writeMetric(reqBody []byte) error { defer resp.Body.Close() if resp.StatusCode < 200 || resp.StatusCode >= 300 { + for _, nonRetryableStatusCode := range h.NonRetryableStatusCodes { + if resp.StatusCode == nonRetryableStatusCode { + h.Log.Errorf("Received non-retryable status %v. Metrics are lost.", resp.StatusCode) + return nil + } + } + errorLine := "" scanner := bufio.NewScanner(io.LimitReader(resp.Body, maxErrMsgLen)) if scanner.Scan() { diff --git a/plugins/outputs/http/http_test.go b/plugins/outputs/http/http_test.go index 3c5d1ca43..9df8dea9f 100644 --- a/plugins/outputs/http/http_test.go +++ b/plugins/outputs/http/http_test.go @@ -21,6 +21,7 @@ import ( "github.com/influxdata/telegraf/plugins/serializers" "github.com/influxdata/telegraf/plugins/serializers/influx" "github.com/influxdata/telegraf/plugins/serializers/json" + "github.com/influxdata/telegraf/testutil" ) func getMetric() telegraf.Metric { @@ -172,11 +173,22 @@ func TestStatusCode(t *testing.T) { plugin: &HTTP{ URL: u.String(), }, - statusCode: http.StatusMultipleChoices, + statusCode: http.StatusBadRequest, errFunc: func(t *testing.T, err error) { require.Error(t, err) }, }, + { + name: "Do not retry on configured non-retryable statuscode", + plugin: &HTTP{ + URL: u.String(), + NonRetryableStatusCodes: []int{409}, + }, + statusCode: http.StatusConflict, + errFunc: func(t *testing.T, err error) { + require.NoError(t, err) + }, + }, } for _, tt := range tests { @@ -190,6 +202,8 @@ func TestStatusCode(t *testing.T) { err = tt.plugin.Connect() require.NoError(t, err) + tt.plugin.Log = testutil.Logger{} + err = tt.plugin.Write([]telegraf.Metric{getMetric()}) tt.errFunc(t, err) })