Source code for Happyface4.helpers

import json
import requests
import pycurl
from io import BytesIO


[docs] def get_data_from_elasticsearch( base_url, header, query_head, query_body, logger, timeout=600 ): logger.debug("Starting data extraction from elastic API") # next build the http data string from the query_header and the query_body # important: There has to be a newline between header and body # see here for more information: https://www.elastic.co/guide/en/elasticsearch/reference/master/search-multi-search.html request = "\n" + json.dumps(query_head) + "\n" + json.dumps(query_body) + "\n" logger.debug(f"using query:\n{request}") # get the data with pycurl (http://pycurl.io/docs/latest/quickstart.html) # pycurl needs a function to write the http response to, we use BytesIO # the correspondig curl command is: curl -X POST -H 'Content-Type: application/json' -H "Authorization: Bearer $CERN_BEARER_TOKEN" "https://monit-grafana.cern.ch/api/datasources/proxy/9582/_msearch" --data $request response_body = BytesIO() response_header = BytesIO() c = pycurl.Curl() c.setopt(c.URL, base_url) c.setopt(c.POSTFIELDS, request) c.setopt(c.HTTPHEADER, header) c.setopt(c.WRITEDATA, response_body) c.setopt(c.WRITEHEADER, response_header) c.setopt(c.TIMEOUT, timeout) c.perform() c.close() logger.debug(f"recieved haeder:\n{response_header.getvalue()}\n") body_bytes = response_body.getvalue() logger.debug(f"recieved data:\n{body_bytes}\n") # check if the http code is 200 else raise an error if "200" not in response_header.getvalue().decode("utf8").split("\n")[0]: logger.error(f"recieved haeder:\n{response_header.getvalue().decode('utf8')}\n") logger.error(f"recieved data:\n{body_bytes.decode('utf8')}\n") raise Exception( f"Server retourned an error code:\n{response_header.getvalue().decode('utf8')}" ) # try to interpret the resieved data as json try: result = json.loads(body_bytes.decode("utf8")) except Exception as e: logger.error(e) logger.error(f"Response body size: {len(body_bytes)} bytes") logger.error("The HTTP response didn't contain the expected JSON.") raise return result
[docs] def get_data_from_grafana( url, datasource, queries, logger, token=None, time_range={"from": "now-24h", "to": "now"}, ) -> dict: """Simple helper function to get the resource data from a grafana service in JSON format. Args: url (str): Url to the grafana instance. Should look like `https://grafana_instance.com/api/ds/query`. datasource (dict): Datasource to fetch data from. Usually something like `{'uid': 'foobar'}` queries (dict): The queries to run against the datasource. The keys are used as refId, values are the queries. logger (logging.logger): A logger. Usually `self.logger`. token (str, optional): The identification token for the grafana instance if necessary. Defaults to None. time_range (dict): Time range. Defaults to `{"from": "now-24h", "to": "now"}`. Returns: dict: The ``results`` member of the Grafana response JSON. """ headers = { "Accept": "application/json", "Content-Type": "application/json", } if token: headers["Authorization"] = f"Bearer {token}" if "from" not in time_range or "to" not in time_range: logger.error( 'get_data_from_grafana argument "time_range" has to define "from" and "to".' ) data = { "queries": [ { "refId": ref_id, "datasource": datasource, "query": query, "rawQuery": True, "resultFormat": "time_series", } for ref_id, query in queries.items() ], **time_range, } logger.debug(f"Get data from Grafana ({url}) with request") logger.debug(data) req = requests.post(url, headers=headers, json=data) logger.debug(f"Response: {req.text[:150]}{'...' if len(req.text) > 150 else ''}") return req.json()["results"]
[docs] def field_index(name, fields, key="name") -> int | None: return next((i for i, f in enumerate(fields) if f[key] == name), None)