122 lines
3.9 KiB
Python
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
|
|
"""
|