Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: retryable http client for datadog metric provider #2580

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ require (
github.com/golang/protobuf v1.5.2
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/hashicorp/go-plugin v1.4.8
github.com/hashicorp/go-retryablehttp v0.7.1
github.com/influxdata/influxdb-client-go/v2 v2.12.2
github.com/juju/ansiterm v1.0.0
github.com/mitchellh/mapstructure v1.5.0
Expand Down Expand Up @@ -122,7 +123,6 @@ require (
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v0.14.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.13 // indirect
Expand Down
43 changes: 32 additions & 11 deletions metricproviders/datadog/datadog.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/argoproj/argo-rollouts/utils/evaluate"
metricutil "github.com/argoproj/argo-rollouts/utils/metric"
timeutil "github.com/argoproj/argo-rollouts/utils/time"
retryablehttp "github.com/hashicorp/go-retryablehttp"

log "github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -27,12 +28,19 @@ import (
var unixNow = func() int64 { return timeutil.Now().Unix() }

const (
// ProviderType indicates the provider is datadog
ProviderType = "Datadog"
DatadogTokensSecretName = "datadog"
DatadogApiKey = "api-key"
DatadogAppKey = "app-key"
DatadogAddress = "address"
//ProviderType indicates the provider is datadog
ProviderType = "Datadog"
DatadogTokensSecretName = "datadog"
DatadogApiKey = "api-key"
DatadogAppKey = "app-key"
DatadogAddress = "address"
DefaultRetryMaxWaitSeconds time.Duration = 120
DefaultRetryMax int = 10
)

var (
retryMaxWaitSeconds = DefaultRetryMaxWaitSeconds
retryMax = DefaultRetryMax
)

// Provider contains all the required components to run a Datadog query
Expand All @@ -54,7 +62,7 @@ type datadogConfig struct {
AppKey string `yaml:"app-key,omitempty"`
}

// Type incidates provider is a Datadog provider
// Type indicates provider is a Datadog provider
func (p *Provider) Type() string {
return ProviderType
}
Expand Down Expand Up @@ -106,10 +114,15 @@ func (p *Provider) Run(run *v1alpha1.AnalysisRun, metric v1alpha1.Metric) v1alph
request.Header.Set("DD-API-KEY", p.config.ApiKey)
request.Header.Set("DD-APPLICATION-KEY", p.config.AppKey)

// Send Request
httpClient := &http.Client{
Timeout: time.Duration(10) * time.Second,
}
// Configure retryable HTTP Client that automatically retries on 429 status codes
// with exponential backoff.
retryClient := retryablehttp.NewClient()
retryClient.RetryMax = retryMax
retryClient.RetryWaitMax = time.Second * retryMaxWaitSeconds
retryClient.HTTPClient.Timeout = time.Duration(10) * time.Second
httpClient := retryClient.StandardClient()

// Send request
response, err := httpClient.Do(request)

if err != nil {
Expand Down Expand Up @@ -202,6 +215,14 @@ func lookupKeysInEnv(keys []string) map[string]string {
return valuesByKey
}

func SetRetryMax(max int) {
retryMax = max
}

func SetRetryMaxWait(seconds time.Duration) {
retryMaxWaitSeconds = seconds
}

func NewDatadogProvider(logCtx log.Entry, kubeclientset kubernetes.Interface) (*Provider, error) {
ns := defaults.Namespace()

Expand Down
17 changes: 17 additions & 0 deletions metricproviders/datadog/datadog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,21 @@ func TestRunSuite(t *testing.T) {
useEnvVarForKeys: false,
},

// Error if ratelimit response
{
webServerStatus: 429,
webServerResponse: `{"errors":["Bad Request"]}`,
metric: v1alpha1.Metric{
Name: "foo",
SuccessCondition: "default(result, 1) < 0.05",
Provider: ddProviderIntervalDefault,
},
expectedIntervalSeconds: 300,
expectedPhase: v1alpha1.AnalysisPhaseError,
expectedErrorMessage: "giving up after 3 attempt(s)",
useEnvVarForKeys: false,
},

// Expect success with default() and data
{
webServerStatus: 200,
Expand Down Expand Up @@ -231,6 +246,8 @@ func TestRunSuite(t *testing.T) {

for _, test := range tests {
serverURL := test.serverURL
SetRetryMaxWait(5)
SetRetryMax(2)

if serverURL == "" {
// Server setup with response
Expand Down