Skip to content

Commit 7aebebd

Browse files
peekjef72amotl
authored andcommitted
dsquery: new smartquery function in conjonction with query_factory
1 parent 3b8ce9a commit 7aebebd

File tree

1 file changed

+81
-1
lines changed

1 file changed

+81
-1
lines changed

grafana_client/elements/datasource.py

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import warnings
55
from distutils.version import LooseVersion
66
from typing import Dict, Optional, Tuple, Union
7+
from urllib.parse import urlencode
78

89
from requests import ReadTimeout
910

@@ -306,7 +307,7 @@ def series(self, datasource_id, match, start, end, access="proxy"):
306307
r = self.client.POST(post_series_path, data={"match[]": match, "start": start, "end": end})
307308
return r
308309

309-
def smartquery(self, datasource: Union[DatasourceIdentifier, Dict], expression: str, store: Optional[str] = None):
310+
def smartquery_old(self, datasource: Union[DatasourceIdentifier, Dict], expression: str, store: Optional[str] = None):
310311
"""
311312
Send a query to the designated data source and return its response.
312313
@@ -378,6 +379,85 @@ def smartquery(self, datasource: Union[DatasourceIdentifier, Dict], expression:
378379
f"Reason: {ex}. Response: {ex.response or '<empty>'}"
379380
)
380381
raise
382+
#**********************************************************************************
383+
def smartquery(self, datasource: Union[DatasourceIdentifier, Dict], expression: str, attrs: Optional[dict] = None, request: Optional[dict] = None):
384+
"""
385+
Send a query to the designated data source and return its response.
386+
387+
TODO: This is by far not complete. The `query_factory` function has to
388+
be made more elaborate in order to query different data source
389+
types.
390+
"""
391+
392+
if isinstance(datasource, DatasourceIdentifier):
393+
datasource = self.get(datasource)
394+
395+
datasource_id = datasource["id"]
396+
datasource_type = datasource["type"]
397+
datasource_dialect = datasource.get("jsonData", {}).get("version", "InfluxQL")
398+
access_type = datasource["access"]
399+
400+
# Sanity checks.
401+
if not request and not expression:
402+
raise ValueError("request or expression must be given")
403+
elif not request:
404+
model = {
405+
"refId": "test",
406+
}
407+
if expression is not None and 'query' not in attrs:
408+
model['query'] = expression
409+
model.update(attrs)
410+
request = query_factory(datasource, model)
411+
412+
# Compute request method, body, and endpoint.
413+
if "method" in request and isinstance(request["method"], str):
414+
if request['method'] == 'POST':
415+
send_request = self.client.POST
416+
else:
417+
send_request = self.client.GET
418+
419+
logger.info(f"Submitting request: {request}")
420+
421+
# Certain data sources like InfluxDB 1.x, still use the `/datasources/proxy` route.
422+
if datasource_type == "influxdb" and datasource_dialect == "InfluxQL":
423+
url = f"/datasources/proxy/{datasource_id}/query"
424+
url += '?' + urlencode(request['params'])
425+
request_kwargs = {"data": request["data"]}
426+
427+
elif datasource_type == "graphite":
428+
url = f"/datasources/proxy/{datasource_id}/render"
429+
request_kwargs = {"data": request["data"]}
430+
431+
# This case is very special. It is used for Elasticsearch and Testdata.
432+
# elif expression.startswith("url://"):
433+
# url = expression.replace("url://", "")
434+
# url = url.format(
435+
# datasource_id=datasource.get("id"),
436+
# datasource_uid=datasource.get("uid"),
437+
# database_name=datasource.get("database"),
438+
# )
439+
# request_kwargs = {}
440+
# send_request = self.client.GET
441+
442+
# For all others, use the generic data source communication endpoint.
443+
elif access_type in ["server", "proxy"]:
444+
url = "/ds/query"
445+
request_kwargs = {"json": request["data"]}
446+
447+
else:
448+
raise NotImplementedError(f"Unable to submit query to data source with access type '{access_type}'")
449+
450+
# Submit query.
451+
try:
452+
r = send_request(url, **request_kwargs)
453+
# logger.debug(f"Response from generic data source query: {r}")
454+
return r
455+
except (GrafanaClientError, GrafanaServerError) as ex:
456+
logger.error(
457+
f"Querying data source failed. id={datasource_id}, type={datasource_type}. "
458+
f"Reason: {ex}. Response: {ex.response or '<empty>'}"
459+
)
460+
raise
381461

382462
def health_check(self, datasource: Union[DatasourceIdentifier, Dict]) -> DatasourceHealthResponse:
383463
"""

0 commit comments

Comments
 (0)