diff --git a/setup.cfg b/setup.cfg index aa76bae..526aeb2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,2 @@ [bdist_wheel] -universal=0 +universal = 0 diff --git a/setup.py b/setup.py index 5287067..b5f4ad3 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,5 @@ from setuptools import setup, find_packages + # To use a consistent encoding from codecs import open from os import path @@ -11,35 +12,23 @@ with open(path.join(here, "README.md"), encoding="utf-8") as f: setup( name="radio_exporter", - - version='0.1.0', - + version="0.1.0", description="", long_description=long_description, - url="https://git.gammaspectra.live/S.O.N.G/radio_exporter", - author="w1kl4s", author_email="w1kl4s@protonmail.com", license="BSD 2-Clause", - classifiers=[ "Development Status :: 4 - Beta", - "Intended Audience :: System Administrators", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", - ], python_requires=">=3.6, <4", keywords="monitoring metrics exporter radio", packages=["src"], - install_requires=[ - "requests" - ], - entry_points={ - "console_scripts": ["radio_exporter=src.main:start"] - } + install_requires=["requests"], + entry_points={"console_scripts": ["radio_exporter=src.main:start"]}, ) diff --git a/src/Collector.py b/src/Collector.py index b22af2f..55db72f 100644 --- a/src/Collector.py +++ b/src/Collector.py @@ -5,26 +5,32 @@ import requests from collections.abc import MutableMapping from dataclasses import dataclass + + @dataclass class Metric: prefix: str value_name: str labels: dict - value: int + value: int + def format_prom(self) -> str: - labels = ','.join(x + '=' + '"' + str(self.labels[x]) + '"' for x in self.labels.keys()) + 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.finalcommander_url = "radio.animebits.moe/api/fcmm_status" self.fcmm_urls = ["https://radio.animebits.moe/api/fcmm_status"] def _fetch_json(self, url): - try: + try: r = requests.get(url) data = json.loads(r.text) - return data + return data except json.JSONDecodeError: raise CollectorException(f"Failed to parse JSON at {url}") except requests.exceptions.ConnectionError: @@ -36,11 +42,11 @@ class Collector(object): 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 + return data def get_instances(self, fcmm_data): for server in fcmm_data["servers"]: @@ -64,7 +70,9 @@ class Collector(object): 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] + 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"]} @@ -80,21 +88,34 @@ class Collector(object): 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)) + 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)) + 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 - """ \ No newline at end of file + """ + Base exception class raised by Collector + """ diff --git a/src/PrometheusServer.py b/src/PrometheusServer.py index c5bc9b4..10a950e 100644 --- a/src/PrometheusServer.py +++ b/src/PrometheusServer.py @@ -1,14 +1,15 @@ import socket import signal from ipaddress import ip_address -from http.server import HTTPServer,BaseHTTPRequestHandler +from http.server import HTTPServer, BaseHTTPRequestHandler from selectors import DefaultSelector, EVENT_READ -from src import Collector +from src import Collector -class PromServer(HTTPServer): + +class PromServer(HTTPServer): def __init__(self, address): - if ip_address(address[0]).version == 6: + if ip_address(address[0]).version == 6: self.address_family = socket.AF_INET6 super().__init__(address, self.RequestHandler) @@ -19,14 +20,14 @@ class PromServer(HTTPServer): metrics = [x.format_prom() for x in self.server.collector.collect()] - output = '\n'.join(metrics) + '\n' + output = "\n".join(metrics) + "\n" self.send_response(200) self.end_headers() self.wfile.write(output.encode()) def signal_handler(self, signum, frame): - print('Signal handler called with signal', signum) - self.interrupt_write.send(b'\0') + print("Signal handler called with signal", signum) + self.interrupt_write.send(b"\0") def serve_forever(self): sel = DefaultSelector() @@ -41,7 +42,7 @@ class PromServer(HTTPServer): self.handle_request() def start(self): - self.collector = Collector.Collector() + self.collector = Collector.Collector() self.interrupt_read, self.interrupt_write = socket.socketpair() signal.signal(signal.SIGINT, self.signal_handler) self.serve_forever() diff --git a/src/main.py b/src/main.py index 70d5ce6..5250799 100644 --- a/src/main.py +++ b/src/main.py @@ -3,14 +3,31 @@ import argparse from src import PrometheusServer + def start(): parser = argparse.ArgumentParser(description="Run radio exporter") - parser.add_argument("-p", "--port", metavar="port", action='store', type=int, default=8888, help='Port for http server to listen on') - parser.add_argument("-a", "--address", metavar="address", action='store', default='0.0.0.0', help='Address for http server to listen on') + parser.add_argument( + "-p", + "--port", + metavar="port", + action="store", + type=int, + default=8888, + help="Port for http server to listen on", + ) + parser.add_argument( + "-a", + "--address", + metavar="address", + action="store", + default="0.0.0.0", + help="Address for http server to listen on", + ) args = parser.parse_args() - server = PrometheusServer.PromServer((args.address, args.port)) + server = PrometheusServer.PromServer((args.address, args.port)) server.start() -if __name__ == '__main__': + +if __name__ == "__main__": start()