| Server IP : 199.250.200.62 / Your IP : 216.73.216.15 Web Server : Apache System : Linux vps37394.inmotionhosting.com 3.10.0-1160.119.1.vz7.224.4 #1 SMP Mon Sep 30 15:36:27 MSK 2024 x86_64 User : jasonp18 ( 1000) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /proc/2/cwd/proc/self/root/proc/2/cwd/opt/imh-python/lib/python3.9/site-packages/mtrlib/ |
Upload File : |
"""Functions for Retrieving data from graphite"""
from typing import Union, List, Optional, Tuple
from datetime import datetime
import urllib.parse
import requests
from arrow.arrow import Arrow
import arrow
QUERY_FMT = '%H:%M_%Y%m%d'
class GraphiteError(Exception):
"""Raised on error when fetching graphite data"""
class Graphite:
"""Performs Graphite Queries"""
def __init__(
self,
render_url: Optional[str] = 'https://graphite.imhadmin.net/render/',
timeout: Optional[Union[float, Tuple[float]]] = 600,
):
self.render_url = render_url
self.timeout = timeout
@staticmethod
def _params(
target: Union[str, List[str]],
start: Optional[Union[datetime, Arrow, str, int]] = None,
stop: Optional[Union[datetime, Arrow, str, int]] = None,
tzname: Optional[str] = None,
) -> dict:
# int -> arrow
if isinstance(start, int):
start = arrow.get(start)
if isinstance(stop, int):
stop = arrow.get(stop)
# format datetimes
if isinstance(start, (datetime, Arrow)):
if tzname is None: # if tzname was not overridden
tzname = start.tzname()
start = start.strftime(QUERY_FMT)
if isinstance(stop, (datetime, Arrow)):
stop = stop.strftime(QUERY_FMT)
# graphite's pytz may be old
if tzname in ('PDT', 'PST'):
tzname = 'America/Los_Angeles'
if tzname in ('EST', 'EDT'):
tzname = 'America/New_York'
params = {'target': target}
if start is not None:
params['from'] = start
if stop is not None:
params['until'] = stop
if tzname is not None:
params['tz'] = tzname
return params
def query(
self,
target: Union[str, List[str]],
start: Optional[Union[datetime, Arrow, str, int]] = None,
stop: Optional[Union[datetime, Arrow, str, int]] = None,
tzname: Optional[str] = None,
) -> list:
"""Query data from graphite
Args:
target (str or list): graphite bucket(s) to fetch data for
start: start time to fetch data for. If not supplied, it'll
be 24 hours ago **(see note)**
stop: stop time to fetch data for. If not supplied, it'll be now
**(see note)**
tzname: timezone to use. If not supplied, the ``start`` arg's
timezone will be used. If the ``start`` arg is not timezone
aware, it'll use graphite defaults
Raises:
GraphiteError: on any error
Note:
``start`` and ``stop`` will accept ``arrow`` objects, ``datetimes``,
``int`` for unix timestamps, and ``str``. If it's a ``str``, it'll
be sent as a literal and handled per graphite's documentation
https://graphite.readthedocs.io/en/latest/render_api.html
"""
params = self._params(target, start, stop, tzname)
params['format'] = 'json'
try:
req = requests.get(
self.render_url,
timeout=self.timeout,
params=params,
)
except requests.RequestException as exc:
raise GraphiteError(exc) from exc
try:
return req.json()
except ValueError as exc:
if req.status_code != 200:
raise GraphiteError(
f"{req.url}\nHTTP {req.status_code}: {req.reason}"
) from exc
raise GraphiteError(
f"{req.url}\n{type(exc).__name__}: {exc}"
) from exc
def query_dict(
self,
target: Union[str, List[str]],
start: Optional[Union[datetime, Arrow, str, int]] = None,
stop: Optional[Union[datetime, Arrow, str, int]] = None,
tzname: Optional[str] = None,
) -> dict:
"""Just like ``query`` except it converts the data to a dict
Args:
target (str or list): graphite bucket(s) to fetch data for
start: start time to fetch data for. If not supplied, it'll
be 24 hours ago **(see note)**
stop: stop time to fetch data for. If not supplied, it'll be now
**(see note)**
tzname: timezone to use. If not supplied, the ``start`` arg's
timezone will be used. If the ``start`` arg is not timezone
aware, it'll use graphite defaults
Raises:
GraphiteError: on any error
Note:
``start`` and ``stop`` will accept ``arrow`` objects, ``datetimes``,
``int`` for unix timestamps, and ``str``. If it's a ``str``, it'll
be sent as a literal and handled per graphite's documentation
https://graphite.readthedocs.io/en/latest/render_api.html
"""
return {
x['target']: x['datapoints']
for x in self.query(target, start, stop, tzname)
}
def img_url(
self,
target: Union[str, List[str]],
start: Optional[Union[datetime, Arrow, str, int]] = None,
stop: Optional[Union[datetime, Arrow, str, int]] = None,
tzname: Optional[str] = None,
**kwargs,
) -> str:
"""Gets a graphite render URL for an image but does not fetch it
Args:
target (str or list): graphite bucket(s) to fetch data for
start: start time to fetch data for. If not supplied, it'll
be 24 hours ago **(see note)**
stop: stop time to fetch data for. If not supplied, it'll be now
**(see note)**
tzname: timezone to use. If not supplied, the ``start`` arg's
timezone will be used. If the ``start`` arg is not timezone
aware, it'll use graphite defaults
Raises:
GraphiteError: on any error
Note:
``start`` and ``stop`` will accept ``arrow`` objects, ``datetimes``,
``int`` for unix timestamps, and ``str``. If it's a ``str``, it'll
be sent as a literal and handled per graphite's documentation
https://graphite.readthedocs.io/en/latest/render_api.html
"""
params = self._params(target, start, stop, tzname)
params.update(kwargs)
args = urllib.parse.urlencode(query=params, doseq=True)
return f'{self.render_url}?{args}'