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

Add WithIdleConnTimeout HTTP client option #308

Merged
merged 1 commit into from Jun 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 18 additions & 9 deletions config/http_config.go
Expand Up @@ -47,6 +47,9 @@ var DefaultHTTPClientConfig = HTTPClientConfig{
var defaultHTTPClientOptions = httpClientOptions{
keepAlivesEnabled: true,
http2Enabled: true,
// 5 minutes is typically above the maximum sane scrape interval. So we can
// use keepalive for all configurations.
idleConnTimeout: 5 * time.Minute,
}

type closeIdler interface {
Expand Down Expand Up @@ -283,6 +286,7 @@ type httpClientOptions struct {
dialContextFunc DialContextFunc
keepAlivesEnabled bool
http2Enabled bool
idleConnTimeout time.Duration
}

// HTTPClientOption defines an option that can be applied to the HTTP client.
Expand All @@ -309,6 +313,13 @@ func WithHTTP2Disabled() HTTPClientOption {
}
}

// WithIdleConnTimeout allows setting the idle connection timeout.
func WithIdleConnTimeout(timeout time.Duration) HTTPClientOption {
return func(opts *httpClientOptions) {
opts.idleConnTimeout = timeout
}
}

// NewClient returns a http.Client using the specified http.RoundTripper.
func newClient(rt http.RoundTripper) *http.Client {
return &http.Client{Transport: rt}
Expand Down Expand Up @@ -357,15 +368,13 @@ func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string, optFuncs ...HT
// The only timeout we care about is the configured scrape timeout.
// It is applied on request. So we leave out any timings here.
var rt http.RoundTripper = &http.Transport{
Proxy: http.ProxyURL(cfg.ProxyURL.URL),
MaxIdleConns: 20000,
MaxIdleConnsPerHost: 1000, // see https://github.com/golang/go/issues/13801
DisableKeepAlives: !opts.keepAlivesEnabled,
TLSClientConfig: tlsConfig,
DisableCompression: true,
// 5 minutes is typically above the maximum sane scrape interval. So we can
// use keepalive for all configurations.
IdleConnTimeout: 5 * time.Minute,
Proxy: http.ProxyURL(cfg.ProxyURL.URL),
MaxIdleConns: 20000,
MaxIdleConnsPerHost: 1000, // see https://github.com/golang/go/issues/13801
DisableKeepAlives: !opts.keepAlivesEnabled,
TLSClientConfig: tlsConfig,
DisableCompression: true,
IdleConnTimeout: opts.idleConnTimeout,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
DialContext: dialContext,
Expand Down
19 changes: 19 additions & 0 deletions config/http_config_test.go
Expand Up @@ -456,6 +456,25 @@ func TestCustomDialContextFunc(t *testing.T) {
}
}

func TestCustomIdleConnTimeout(t *testing.T) {
timeout := time.Second * 5

cfg := HTTPClientConfig{}
rt, err := NewRoundTripperFromConfig(cfg, "test", WithIdleConnTimeout(timeout))
if err != nil {
t.Fatalf("Can't create a round-tripper from this config: %+v", cfg)
}

transport, ok := rt.(*http.Transport)
if !ok {
t.Fatalf("Unexpected transport: %+v", transport)
}

if transport.IdleConnTimeout != timeout {
t.Fatalf("Unexpected idle connection timeout: %+v", timeout)
}
}

func TestMissingBearerAuthFile(t *testing.T) {
cfg := HTTPClientConfig{
BearerTokenFile: MissingBearerTokenFile,
Expand Down