Skip to content

Commit

Permalink
Improve usability and documentation for changing timeout settings
Browse files Browse the repository at this point in the history
  • Loading branch information
amotl committed Jul 30, 2023
1 parent ba367cd commit ea44043
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* Add missing argument `dashboard_uid` to `get_annotation` method.
Thanks, @nikita-b.
* Add API method `get_alertrules_all`. Thanks, @harish422.
* Improve usability and documentation for changing timeout settings.
Thanks, @bukem and @dheeg.


## 3.5.0 (2022-12-07)
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ Please note that, on top of the specific examples above, the object obtained by
`credential` can be an arbitrary `requests.auth.AuthBase` instance.


## Timeout settings

The default timeout value is five seconds, used for both connect and read timeout.

The constructors of `GrafanaApi` and `GrafanaClient`, as well as the factory methods
`from_url` and `from_env` accept the `timeout` argument, which can be obtained as a
scalar `float` value, or as a tuple of `(<read timeout>, <connect timeout>)`.


## Proxy

The underlying `requests` library honors the `HTTP_PROXY` and `HTTPS_PROXY`
Expand Down
28 changes: 23 additions & 5 deletions grafana_client/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import requests.auth
from urllib3.exceptions import InsecureRequestWarning

from .client import GrafanaClient
from .client import DEFAULT_TIMEOUT, GrafanaClient
from .elements import (
Admin,
Alerting,
Expand Down Expand Up @@ -44,7 +44,7 @@ def __init__(
url_path_prefix="",
protocol="http",
verify=True,
timeout=5.0,
timeout=DEFAULT_TIMEOUT,
user_agent: str = None,
):
self.client = GrafanaClient(
Expand Down Expand Up @@ -95,7 +95,12 @@ def version(self):
return version

@classmethod
def from_url(cls, url: str = None, credential: Union[str, Tuple[str, str], requests.auth.AuthBase] = None):
def from_url(
cls,
url: str = None,
credential: Union[str, Tuple[str, str], requests.auth.AuthBase] = None,
timeout: Union[float, Tuple[float, float]] = DEFAULT_TIMEOUT,
):
"""
Factory method to create a `GrafanaApi` instance from a URL.
Expand Down Expand Up @@ -129,14 +134,27 @@ def from_url(cls, url: str = None, credential: Union[str, Tuple[str, str], reque
port=url.port,
url_path_prefix=url.path.lstrip("/"),
verify=verify,
timeout=timeout,
)
grafana.url = original_url

return grafana

@classmethod
def from_env(cls):
def from_env(cls, timeout: Union[float, Tuple[float, float]] = None):
"""
Factory method to create a `GrafanaApi` instance from environment variables.
"""
return cls.from_url(url=os.environ.get("GRAFANA_URL"), credential=os.environ.get("GRAFANA_TOKEN"))
if timeout is None:
if "GRAFANA_TIMEOUT" in os.environ:
try:
timeout = float(os.environ["GRAFANA_TIMEOUT"])
except Exception as ex:
raise ValueError(
f"Unable to parse invalid `float` value from " f"`GRAFANA_TIMEOUT` environment variable: {ex}"
)
if timeout is None:
timeout = DEFAULT_TIMEOUT
return cls.from_url(
url=os.environ.get("GRAFANA_URL"), credential=os.environ.get("GRAFANA_TOKEN"), timeout=timeout
)
4 changes: 3 additions & 1 deletion grafana_client/client.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import requests
import requests.auth

DEFAULT_TIMEOUT: float = 5.0


class GrafanaException(Exception):
def __init__(self, status_code, response, message):
Expand Down Expand Up @@ -73,7 +75,7 @@ def __init__(
url_path_prefix="",
protocol="http",
verify=True,
timeout=5.0,
timeout=DEFAULT_TIMEOUT,
user_agent: str = None,
):
self.auth = auth
Expand Down
27 changes: 27 additions & 0 deletions test/test_grafana_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ def test_from_url_full_on(self):
self.assertEqual(grafana.client.verify, False)
self.assertEqual(grafana.client.timeout, 5.0)

def test_from_url_with_timeout_value(self):
grafana = GrafanaApi.from_url(timeout=42.42)
self.assertEqual(grafana.client.timeout, 42.42)

def test_from_url_with_timeout_tuple(self):
grafana = GrafanaApi.from_url(timeout=(3.05, 27))
self.assertEqual(grafana.client.timeout, (3.05, 27))

def test_from_env_default(self):
grafana = GrafanaApi.from_env()
self.assertIsInstance(grafana.client.auth, requests.auth.HTTPBasicAuth)
Expand Down Expand Up @@ -114,3 +122,22 @@ def test_from_env_full_on(self):
self.assertEqual(grafana.client.url_protocol, "https")
self.assertEqual(grafana.client.verify, False)
self.assertEqual(grafana.client.timeout, 5.0)

@mock.patch.dict(os.environ, {"GRAFANA_TIMEOUT": "84.84"})
def test_from_env_with_timeout_from_env_valid(self):
grafana = GrafanaApi.from_env()
self.assertEqual(grafana.client.timeout, 84.84)

@mock.patch.dict(os.environ, {"GRAFANA_TIMEOUT": "foobar"})
def test_from_env_with_timeout_from_env_invalid(self):
with self.assertRaises(ValueError) as ctx:
GrafanaApi.from_env()
self.assertEqual(
str(ctx.exception),
"Unable to parse invalid `float` value from `GRAFANA_TIMEOUT` "
"environment variable: could not convert string to float: 'foobar'",
)

def test_from_env_with_timeout_tuple(self):
grafana = GrafanaApi.from_env(timeout=(3.05, 27))
self.assertEqual(grafana.client.timeout, (3.05, 27))

0 comments on commit ea44043

Please sign in to comment.