From 8e70d5d1818fa12a3ca442e9af20adf1415a0d2c Mon Sep 17 00:00:00 2001 From: Arseny Smalyuk Date: Wed, 7 Apr 2021 17:46:19 +0300 Subject: [PATCH] Add timeout option to datasource config (#31871) --- docs/sources/administration/provisioning.md | 1 + .../DataSourceHttpSettings.tsx | 41 +++++++++++++------ pkg/models/datasource_cache.go | 15 ++++++- pkg/models/datasource_cache_test.go | 19 +++++++++ 4 files changed, 61 insertions(+), 15 deletions(-) diff --git a/docs/sources/administration/provisioning.md b/docs/sources/administration/provisioning.md index 4654be86781..e0c7d6c556f 100644 --- a/docs/sources/administration/provisioning.md +++ b/docs/sources/administration/provisioning.md @@ -147,6 +147,7 @@ Since not all datasources have the same configuration settings we only have the | tlsAuthWithCACert | boolean | _All_ | Enable TLS authentication using CA cert | | tlsSkipVerify | boolean | _All_ | Controls whether a client verifies the server's certificate chain and host name. | | serverName | string | _All_ | Optional. Controls the server name used for certificate common name/subject alternative name verification. Defaults to using the data source URL. | +| timeout | string | _All_ | Request timeout in seconds. Overrides dataproxy.timeout option | | graphiteVersion | string | Graphite | Graphite version | | timeInterval | string | Prometheus, Elasticsearch, InfluxDB, MySQL, PostgreSQL and MSSQL | Lowest interval/step value that should be used for this data source. | | httpMode | string | Influxdb | HTTP Method. 'GET', 'POST', defaults to GET | diff --git a/packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.tsx b/packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.tsx index bea0bd8fb31..88bbaa2f050 100644 --- a/packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.tsx +++ b/packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.tsx @@ -148,19 +148,34 @@ export const DataSourceHttpSettings: React.FC = (props) => { )} {dataSourceConfig.access === 'proxy' && ( -
- - Whitelisted Cookies - - - onSettingsChange({ jsonData: { ...dataSourceConfig.jsonData, keepCookies: cookies } }) - } - /> +
+
+ + Whitelisted Cookies + + + onSettingsChange({ jsonData: { ...dataSourceConfig.jsonData, keepCookies: cookies } }) + } + /> +
+
+ { + onSettingsChange({ + jsonData: { ...dataSourceConfig.jsonData, timeout: event.currentTarget.value }, + }); + }} + /> +
)}
diff --git a/pkg/models/datasource_cache.go b/pkg/models/datasource_cache.go index 63ce4da2479..76b92308b09 100644 --- a/pkg/models/datasource_cache.go +++ b/pkg/models/datasource_cache.go @@ -124,6 +124,17 @@ var ptc = proxyTransportCache{ cache: make(map[int64]cachedTransport), } +func (ds *DataSource) getTimeout() time.Duration { + timeout := 0 + if ds.JsonData != nil { + timeout = ds.JsonData.Get("timeout").MustInt() + } + if timeout == 0 { + timeout = setting.DataProxyTimeout + } + return time.Duration(timeout) * time.Second +} + func (ds *DataSource) GetHttpClient() (*http.Client, error) { transport, err := ds.GetHttpTransport() if err != nil { @@ -131,7 +142,7 @@ func (ds *DataSource) GetHttpClient() (*http.Client, error) { } return &http.Client{ - Timeout: time.Duration(setting.DataProxyTimeout) * time.Second, + Timeout: ds.getTimeout(), Transport: transport, }, nil } @@ -158,7 +169,7 @@ func (ds *DataSource) GetHttpTransport() (*dataSourceTransport, error) { TLSClientConfig: tlsConfig, Proxy: http.ProxyFromEnvironment, Dial: (&net.Dialer{ - Timeout: time.Duration(setting.DataProxyTimeout) * time.Second, + Timeout: ds.getTimeout(), KeepAlive: time.Duration(setting.DataProxyKeepAlive) * time.Second, }).Dial, TLSHandshakeTimeout: time.Duration(setting.DataProxyTLSHandshakeTimeout) * time.Second, diff --git a/pkg/models/datasource_cache_test.go b/pkg/models/datasource_cache_test.go index f9dfe37ba60..9e4a930e519 100644 --- a/pkg/models/datasource_cache_test.go +++ b/pkg/models/datasource_cache_test.go @@ -214,6 +214,25 @@ func TestDataSource_GetHttpTransport(t *testing.T) { assert.Equal(t, "Ok", bodyStr) }) + t.Run("Should use request timeout if configured in JsonData", func(t *testing.T) { + clearDSProxyCache(t) + + json := simplejson.NewFromAny(map[string]interface{}{ + "timeout": 19, + }) + ds := DataSource{ + Id: 1, + Url: "http://k8s:8001", + Type: "Kubernetes", + JsonData: json, + } + + client, err := ds.GetHttpClient() + require.NoError(t, err) + + assert.Equal(t, 19*time.Second, client.Timeout) + }) + t.Run("Should not include SigV4 middleware if not configured in JsonData", func(t *testing.T) { clearDSProxyCache(t)