Skip to content

Commit

Permalink
Improve error reporting on invalid Grafana URLs, or invalid endpoints
Browse files Browse the repository at this point in the history
- Rework "health" method (now a property) to raise exception on errors
- Report Grafana version on startup
- Improve error messages
- Add software tests evaluating connectivity error handling
  • Loading branch information
amotl committed Mar 31, 2024
1 parent 6dc0015 commit 33b3a96
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 17 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ in progress
- Removed support for Python 3.7
- SQLite cache: Use ``requests_cache.CachedSession`` for better concurrency
behaviour. Thanks, @JensRichnow and @JWCook.
- Improve error reporting and exit behavior when connecting to Grafana
instance fails. Thanks, @interfan7.

2024-03-07 0.18.0
=================
Expand Down
5 changes: 4 additions & 1 deletion grafana_wtf/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,13 +228,16 @@ def run():
'No Grafana URL given. Please use "--grafana-url" option or environment variable "GRAFANA_URL".'
)

log.info(f"Using Grafana at {grafana_url}")
log.info(f"Grafana location: {grafana_url}")

engine = GrafanaWtf(grafana_url, grafana_token)

engine.enable_cache(expire_after=cache_ttl, drop_cache=options["drop-cache"])
engine.enable_concurrency(int(options["concurrency"]))
engine.setup()

log.info(f"Grafana version: {engine.version}")

if options.replace:
engine.clear_cache()

Expand Down
35 changes: 22 additions & 13 deletions grafana_wtf/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
class GrafanaEngine:
session = niquests.Session()

def __init__(self, grafana_url, grafana_token):
def __init__(self, grafana_url, grafana_token=None):
self.grafana_url = grafana_url
self.grafana_token = grafana_token

Expand Down Expand Up @@ -263,15 +263,10 @@ async def execute_parallel(self):

class GrafanaWtf(GrafanaEngine):
def info(self):
try:
health = self.grafana.client.GET("/health")
except Exception as ex:
log.error(f"Request to /health endpoint failed: {ex}")
health = {}

response = OrderedDict(
grafana=OrderedDict(
version=health.get("version"),
version=self.version,
url=self.grafana_url,
),
statistics=OrderedDict(),
Expand Down Expand Up @@ -315,15 +310,29 @@ def info(self):

return response

def version(self):
@property
def health(self):
response = None
error = None
error_template = f"The request to {self.grafana_url.rstrip('/')}/api/health failed"
try:
health = self.grafana.client.GET("/health")
response = self.grafana.client.GET("/health")
if not isinstance(response, dict):
error = f"{error_template}: Invalid response, content was: {response}"

except Exception as ex:
log.error(f"Request to /health endpoint failed: {ex}")
health = {}
error = f"{error_template}: {ex}"

version = health.get("version")
return version
if error:
log.critical(error)
raise ConnectionError(error)

if response:
return Munch(response)

@property
def version(self):
return self.health.get("version")

def dashboard_details(self):
for dashboard in self.data.dashboards:
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ def grafana_version(docker_grafana):
"""
engine = GrafanaWtf(grafana_url=docker_grafana, grafana_token=None)
engine.setup()
grafana_version = engine.version()
grafana_version = engine.version
return grafana_version


Expand Down
39 changes: 37 additions & 2 deletions tests/test_core.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from unittest.mock import Mock
from unittest.mock import Mock, patch

import pytest
from munch import Munch

from grafana_wtf.core import Indexer
from grafana_wtf.core import Indexer, GrafanaWtf


def test_collect_datasource_items_variable_all():
Expand Down Expand Up @@ -35,3 +36,37 @@ def test_collect_datasource_items_variable_all():
indexer = Indexer(engine=engine_mock)
result = indexer.collect_datasource_items([node])
assert result == []


def test_connect_success():
wtf = GrafanaWtf("https://play.grafana.org")
wtf.setup()
health = wtf.health
assert "commit" in health
assert "version" in health
assert health.database == "ok"


def test_connect_failure():
wtf = GrafanaWtf("http://localhost:1234")
wtf.setup()
with pytest.raises(ConnectionError) as ex:
_ = wtf.health
assert ex.match("The request to http://localhost:1234/api/health failed")


@patch("grafana_client.client.GrafanaClient.__getattr__")
def test_connect_version(mock_get):
mock_get.return_value = Mock()
mock_get.return_value.return_value = {"commit": "14e988bd22", "database": "ok", "version": "9.0.1"}
wtf = GrafanaWtf("http://localhost:1234")
wtf.setup()
assert wtf.version == "9.0.1"


def test_connect_non_json_response():
wtf = GrafanaWtf("https://example.org/")
wtf.setup()
with pytest.raises(ConnectionError) as ex:
_ = wtf.health
assert ex.match("The request to https://example.org/api/health failed: Client Error 404")

0 comments on commit 33b3a96

Please sign in to comment.