Skip to content

Commit 69e71f4

Browse files
committed
Improve usability and documentation for changing timeout settings
1 parent ba367cd commit 69e71f4

File tree

5 files changed

+64
-6
lines changed

5 files changed

+64
-6
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* Add missing argument `dashboard_uid` to `get_annotation` method.
66
Thanks, @nikita-b.
77
* Add API method `get_alertrules_all`. Thanks, @harish422.
8+
* Improve usability and documentation for changing timeout settings.
9+
Thanks, @bukem and @dheeg.
810

911

1012
## 3.5.0 (2022-12-07)

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,15 @@ Please note that, on top of the specific examples above, the object obtained by
136136
`credential` can be an arbitrary `requests.auth.AuthBase` instance.
137137

138138

139+
## Timeout settings
140+
141+
The default timeout value is five seconds, used for both connect and read timeout.
142+
143+
The constructors of `GrafanaApi` and `GrafanaClient`, as well as the factory methods
144+
`from_url` and `from_env` accept the `timeout` argument, which can be obtained as a
145+
scalar `float` value, or as a tuple of `(<read timeout>, <connect timeout>)`.
146+
147+
139148
## Proxy
140149

141150
The underlying `requests` library honors the `HTTP_PROXY` and `HTTPS_PROXY`

grafana_client/api.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import requests.auth
1010
from urllib3.exceptions import InsecureRequestWarning
1111

12-
from .client import GrafanaClient
12+
from .client import DEFAULT_TIMEOUT, GrafanaClient
1313
from .elements import (
1414
Admin,
1515
Alerting,
@@ -44,7 +44,7 @@ def __init__(
4444
url_path_prefix="",
4545
protocol="http",
4646
verify=True,
47-
timeout=5.0,
47+
timeout=DEFAULT_TIMEOUT,
4848
user_agent: str = None,
4949
):
5050
self.client = GrafanaClient(
@@ -95,7 +95,12 @@ def version(self):
9595
return version
9696

9797
@classmethod
98-
def from_url(cls, url: str = None, credential: Union[str, Tuple[str, str], requests.auth.AuthBase] = None):
98+
def from_url(
99+
cls,
100+
url: str = None,
101+
credential: Union[str, Tuple[str, str], requests.auth.AuthBase] = None,
102+
timeout: Union[float, Tuple[float, float]] = DEFAULT_TIMEOUT,
103+
):
99104
"""
100105
Factory method to create a `GrafanaApi` instance from a URL.
101106
@@ -129,14 +134,27 @@ def from_url(cls, url: str = None, credential: Union[str, Tuple[str, str], reque
129134
port=url.port,
130135
url_path_prefix=url.path.lstrip("/"),
131136
verify=verify,
137+
timeout=timeout,
132138
)
133139
grafana.url = original_url
134140

135141
return grafana
136142

137143
@classmethod
138-
def from_env(cls):
144+
def from_env(cls, timeout: Union[float, Tuple[float, float]] = None):
139145
"""
140146
Factory method to create a `GrafanaApi` instance from environment variables.
141147
"""
142-
return cls.from_url(url=os.environ.get("GRAFANA_URL"), credential=os.environ.get("GRAFANA_TOKEN"))
148+
if timeout is None:
149+
if "GRAFANA_TIMEOUT" in os.environ:
150+
try:
151+
timeout = float(os.environ["GRAFANA_TIMEOUT"])
152+
except Exception as ex:
153+
raise ValueError(
154+
f"Unable to parse invalid `float` value from " f"`GRAFANA_TIMEOUT` environment variable: {ex}"
155+
)
156+
if timeout is None:
157+
timeout = DEFAULT_TIMEOUT
158+
return cls.from_url(
159+
url=os.environ.get("GRAFANA_URL"), credential=os.environ.get("GRAFANA_TOKEN"), timeout=timeout
160+
)

grafana_client/client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import requests
22
import requests.auth
33

4+
DEFAULT_TIMEOUT: float = 5.0
5+
46

57
class GrafanaException(Exception):
68
def __init__(self, status_code, response, message):
@@ -73,7 +75,7 @@ def __init__(
7375
url_path_prefix="",
7476
protocol="http",
7577
verify=True,
76-
timeout=5.0,
78+
timeout=DEFAULT_TIMEOUT,
7779
user_agent: str = None,
7880
):
7981
self.auth = auth

test/test_grafana_api.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ def test_from_url_full_on(self):
6666
self.assertEqual(grafana.client.verify, False)
6767
self.assertEqual(grafana.client.timeout, 5.0)
6868

69+
def test_from_url_with_timeout_value(self):
70+
grafana = GrafanaApi.from_url(timeout=42.42)
71+
self.assertEqual(grafana.client.timeout, 42.42)
72+
73+
def test_from_url_with_timeout_tuple(self):
74+
grafana = GrafanaApi.from_url(timeout=(3.05, 27))
75+
self.assertEqual(grafana.client.timeout, (3.05, 27))
76+
6977
def test_from_env_default(self):
7078
grafana = GrafanaApi.from_env()
7179
self.assertIsInstance(grafana.client.auth, requests.auth.HTTPBasicAuth)
@@ -114,3 +122,22 @@ def test_from_env_full_on(self):
114122
self.assertEqual(grafana.client.url_protocol, "https")
115123
self.assertEqual(grafana.client.verify, False)
116124
self.assertEqual(grafana.client.timeout, 5.0)
125+
126+
@mock.patch.dict(os.environ, {"GRAFANA_TIMEOUT": "84.84"})
127+
def test_from_env_with_timeout_from_env_valid(self):
128+
grafana = GrafanaApi.from_env()
129+
self.assertEqual(grafana.client.timeout, 84.84)
130+
131+
@mock.patch.dict(os.environ, {"GRAFANA_TIMEOUT": "foobar"})
132+
def test_from_env_with_timeout_from_env_invalid(self):
133+
with self.assertRaises(ValueError) as ctx:
134+
GrafanaApi.from_env()
135+
self.assertEqual(
136+
str(ctx.exception),
137+
"Unable to parse invalid `float` value from `GRAFANA_TIMEOUT` "
138+
"environment variable: could not convert string to float: 'foobar'",
139+
)
140+
141+
def test_from_env_with_timeout_tuple(self):
142+
grafana = GrafanaApi.from_env(timeout=(3.05, 27))
143+
self.assertEqual(grafana.client.timeout, (3.05, 27))

0 commit comments

Comments
 (0)