radio_exporter/src/Collector.py
2022-07-16 18:27:05 +02:00

122 lines
3.9 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"]
and "statistics" in server_data.keys()
and "database" in servers_data.keys()
):
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
"""