Repository: atlassian/gostatsd
Pull request #252 (2019-08-21 14:19:35)

Allow disabling of retries
Making sure we have the configurability to disable retires.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4eee341..a1b564e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+17.1.x
+------
+- Adding support to disable retries within the gostatsd forwarder
+
 17.1.0
 ------
 - NewRelic event support added by Kav91
diff --git a/README.md b/README.md
index 4c2bf07..e822333 100644
--- a/README.md
+++ b/README.md
@@ -72,6 +72,8 @@ following configuration options:
 - `enable-http2`: boolean to enable the usage of http2 on the request.  There seems to be some incompatibility with the
   golang http2 implementation and AWS ELB/ALBs.  If you experience strange timeouts and hangs, this should be the first
   thing to disable.  Defaults to `false`
+- `enable-retires`: This will tell the forwarder to attempt to send payloads again in case it failed for the first time, 
+   with exponential back off. Defaults to `true`
 - `api-endpoint`: configures the endpoint to submit raw metrics to.  This setting should be just a base URL, for example
   `https://statsd-aggregator.private`, with no path.  Required, no default
 - `max-requests`: maximum number of requests in flight.  Defaults to `1000` (which is probably too high)
diff --git a/pkg/statsd/handler_http_forwarder_v2.go b/pkg/statsd/handler_http_forwarder_v2.go
index 23457eb..a9935b6 100644
--- a/pkg/statsd/handler_http_forwarder_v2.go
+++ b/pkg/statsd/handler_http_forwarder_v2.go
@@ -31,6 +31,7 @@ const (
 	defaultClientTimeout             = 10 * time.Second
 	defaultCompress                  = true
 	defaultEnableHttp2               = false
+	defaultEnableRetires             = true
 	defaultApiEndpoint               = ""
 	defaultMaxRequestElapsedTime     = 30 * time.Second
 	defaultMaxRequests               = 1000
@@ -55,6 +56,7 @@ type HttpForwarderHandlerV2 struct {
 	consolidatedMetrics   <-chan []*gostatsd.MetricMap
 	eventWg               sync.WaitGroup
 	compress              bool
+	retries               bool
 }
 
 // NewHttpForwarderHandlerV2FromViper returns a new http API client.
@@ -63,6 +65,7 @@ func NewHttpForwarderHandlerV2FromViper(logger logrus.FieldLogger, v *viper.Vipe
 	subViper.SetDefault("client-timeout", defaultClientTimeout)
 	subViper.SetDefault("compress", defaultCompress)
 	subViper.SetDefault("enable-http2", defaultEnableHttp2)
+	subViper.SetDefault("enable-retries", defaultEnableRetires)
 	subViper.SetDefault("api-endpoint", defaultApiEndpoint)
 	subViper.SetDefault("max-requests", defaultMaxRequests)
 	subViper.SetDefault("max-request-elapsed-time", defaultMaxRequestElapsedTime)
@@ -77,6 +80,7 @@ func NewHttpForwarderHandlerV2FromViper(logger logrus.FieldLogger, v *viper.Vipe
 		subViper.GetInt("consolidator-slots"),
 		subViper.GetInt("max-requests"),
 		subViper.GetBool("compress"),
+		subViper.GetBool("enable-retries"),
 		subViper.GetBool("enable-http2"),
 		subViper.GetDuration("client-timeout"),
 		subViper.GetDuration("max-request-elapsed-time"),
@@ -85,7 +89,19 @@ func NewHttpForwarderHandlerV2FromViper(logger logrus.FieldLogger, v *viper.Vipe
 }
 
 // NewHttpForwarderHandlerV2 returns a new handler which dispatches metrics over http to another gostatsd server.
-func NewHttpForwarderHandlerV2(logger logrus.FieldLogger, apiEndpoint, network string, consolidatorSlots, maxRequests int, compress, enableHttp2 bool, clientTimeout, maxRequestElapsedTime time.Duration, flushInterval time.Duration) (*HttpForwarderHandlerV2, error) {
+func NewHttpForwarderHandlerV2(
+	logger logrus.FieldLogger,
+	apiEndpoint,
+	network string,
+	consolidatorSlots,
+	maxRequests int,
+	compress,
+	enableRetires,
+	enableHttp2 bool,
+	clientTimeout,
+	maxRequestElapsedTime time.Duration,
+	flushInterval time.Duration,
+) (*HttpForwarderHandlerV2, error) {
 	if apiEndpoint == "" {
 		return nil, fmt.Errorf("api-endpoint is required")
 	}
@@ -110,6 +126,7 @@ func NewHttpForwarderHandlerV2(logger logrus.FieldLogger, apiEndpoint, network s
 		"client-timeout":           clientTimeout,
 		"compress":                 compress,
 		"enable-http2":             enableHttp2,
+		"enable-retries":           enableRetires,
 		"max-request-elapsed-time": maxRequestElapsedTime,
 		"max-requests":             maxRequests,
 		"consolidator-slots":       consolidatorSlots,
@@ -162,6 +179,7 @@ func NewHttpForwarderHandlerV2(logger logrus.FieldLogger, apiEndpoint, network s
 			Transport: transport,
 			Timeout:   clientTimeout,
 		},
+		retries: enableRetires,
 	}, nil
 }
 
@@ -341,7 +359,7 @@ func (hfh *HttpForwarderHandlerV2) post(ctx context.Context, message proto.Messa
 		}
 
 		next := b.NextBackOff()
-		if next == backoff.Stop {
+		if next == backoff.Stop || !hfh.retries {
 			atomic.AddUint64(&hfh.messagesDropped, 1)
 			logger.WithError(err).Info("failed to send, giving up")
 			return


Test patch:
diff --git a/pkg/web/http_receiver_v2_test.go b/pkg/web/http_receiver_v2_test.go
index f5ac86b..71ced27 100644
--- a/pkg/web/http_receiver_v2_test.go
+++ b/pkg/web/http_receiver_v2_test.go
@@ -46,6 +46,7 @@ func TestForwardingEndToEndV2(t *testing.T) {
 		5, // deliberately prime, so the loop below doesn't send the same thing to the same MetricMap every time.
 		10,
 		false,
+		true,
 		false,
 		10*time.Second,
 		10*time.Second,