radio_exporter/src/Collector.py
2022-06-30 23:06:30 +02:00

96 lines
3.3 KiB
Python

import time
import json
import random
import requests
from collections.abc import MutableMapping
from dataclasses import dataclass
@dataclass
class Metric:
prefix: str
value_name: str
labels: dict
value: int
def format_prom(self) -> str:
labels = ','.join(x + '=' + '"' + str(self.labels[x]) + '"' for x in self.labels.keys())
return f"{self.prefix}_{self.value_name}{{{labels}}} {self.value}"
class Collector(object):
def __init__(self):
#self.finalcommander_url = "radio.animebits.moe/api/fcmm_status"
self.fcmm_urls = ["https://radio.animebits.moe/api/fcmm_status"]
def _fetch_json(self, url):
try:
r = requests.get(url)
data = json.loads(r.text)
return data
except json.JSONDecodeError:
raise CollectorException(f"Failed to parse JSON at {url}")
except requests.exceptions.ConnectionError:
raise CollectorException(f"Failed to reach {url}")
except requests.exceptions.ReadTimeout:
raise CollectorException(f"Connection timeout to {url}")
except:
raise CollectorException("Request failed.")
def get_fcmm(self, url):
data = self._fetch_json(url)
if "public_key" not in data.keys() or "servers" not in data.keys():
raise CollectorException("FinalCommander JSON seems to be wrong.")
return data
def get_instances(self, fcmm_data):
for server in fcmm_data["servers"]:
try:
data = self._fetch_json(f"https://{server['Address']}/stats")
except CollectorException:
data = {}
data["fcmm_data"] = server
yield data
def collect(self):
metrics = []
fcmm_data = []
for url in self.fcmm_urls:
try:
fcmm_data.append(self.get_fcmm(url))
up = 1
except CollectorException:
# TODO: log here, unreachable FCMM
up = 0
metrics.append(Metric("fcmm", "up", {"url": url}, up))
servers_data = [x for y in [self.get_instances(fcmm) for fcmm in fcmm_data] for x in y]
for server_data in servers_data:
baselabel = {"server": server_data["fcmm_data"]["Address"]}
if server_data["fcmm_data"]["LastCheckResult"]:
metrics.append(Metric("orbt", "up", {**baselabel}, 1))
else:
metrics.append(Metric("orbt", "up", {**baselabel}, 0))
continue
for name, data in server_data["statistics"].items():
if name == "http" or name == "tls":
for k,v in data.items():
for subtype,value in v.items():
metrics.append(Metric("orbt_stats", f"{name}_{k}", {**baselabel, **{k: subtype}}, value))
else:
for valuetype, value in data.items():
metrics.append(Metric("orbt_stats", name, {**baselabel, **{"type": valuetype}}, value))
for name, value in server_data["database"].items():
metrics.append(Metric("orbt_db", name, {**baselabel}, value))
return metrics
class CollectorException(Exception):
"""
Base exception class raised by Collector
"""