Lint
This commit is contained in:
parent
b2105df1ac
commit
a306198c5a
19
setup.py
19
setup.py
|
@ -1,4 +1,5 @@
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
# To use a consistent encoding
|
# To use a consistent encoding
|
||||||
from codecs import open
|
from codecs import open
|
||||||
from os import path
|
from os import path
|
||||||
|
@ -11,35 +12,23 @@ with open(path.join(here, "README.md"), encoding="utf-8") as f:
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="radio_exporter",
|
name="radio_exporter",
|
||||||
|
version="0.1.0",
|
||||||
version='0.1.0',
|
|
||||||
|
|
||||||
description="",
|
description="",
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
|
|
||||||
url="https://git.gammaspectra.live/S.O.N.G/radio_exporter",
|
url="https://git.gammaspectra.live/S.O.N.G/radio_exporter",
|
||||||
|
|
||||||
author="w1kl4s",
|
author="w1kl4s",
|
||||||
author_email="w1kl4s@protonmail.com",
|
author_email="w1kl4s@protonmail.com",
|
||||||
license="BSD 2-Clause",
|
license="BSD 2-Clause",
|
||||||
|
|
||||||
classifiers=[
|
classifiers=[
|
||||||
"Development Status :: 4 - Beta",
|
"Development Status :: 4 - Beta",
|
||||||
|
|
||||||
"Intended Audience :: System Administrators",
|
"Intended Audience :: System Administrators",
|
||||||
|
|
||||||
"Programming Language :: Python :: 3.6",
|
"Programming Language :: Python :: 3.6",
|
||||||
"Programming Language :: Python :: 3.7",
|
"Programming Language :: Python :: 3.7",
|
||||||
"Programming Language :: Python :: 3.8",
|
"Programming Language :: Python :: 3.8",
|
||||||
|
|
||||||
],
|
],
|
||||||
python_requires=">=3.6, <4",
|
python_requires=">=3.6, <4",
|
||||||
keywords="monitoring metrics exporter radio",
|
keywords="monitoring metrics exporter radio",
|
||||||
packages=["src"],
|
packages=["src"],
|
||||||
install_requires=[
|
install_requires=["requests"],
|
||||||
"requests"
|
entry_points={"console_scripts": ["radio_exporter=src.main:start"]},
|
||||||
],
|
|
||||||
entry_points={
|
|
||||||
"console_scripts": ["radio_exporter=src.main:start"]
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,26 +5,32 @@ import requests
|
||||||
from collections.abc import MutableMapping
|
from collections.abc import MutableMapping
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Metric:
|
class Metric:
|
||||||
prefix: str
|
prefix: str
|
||||||
value_name: str
|
value_name: str
|
||||||
labels: dict
|
labels: dict
|
||||||
value: int
|
value: int
|
||||||
|
|
||||||
def format_prom(self) -> str:
|
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}"
|
return f"{self.prefix}_{self.value_name}{{{labels}}} {self.value}"
|
||||||
|
|
||||||
|
|
||||||
class Collector(object):
|
class Collector(object):
|
||||||
def __init__(self):
|
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"]
|
self.fcmm_urls = ["https://radio.animebits.moe/api/fcmm_status"]
|
||||||
|
|
||||||
def _fetch_json(self, url):
|
def _fetch_json(self, url):
|
||||||
try:
|
try:
|
||||||
r = requests.get(url)
|
r = requests.get(url)
|
||||||
data = json.loads(r.text)
|
data = json.loads(r.text)
|
||||||
return data
|
return data
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
raise CollectorException(f"Failed to parse JSON at {url}")
|
raise CollectorException(f"Failed to parse JSON at {url}")
|
||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
|
@ -36,11 +42,11 @@ class Collector(object):
|
||||||
|
|
||||||
def get_fcmm(self, url):
|
def get_fcmm(self, url):
|
||||||
data = self._fetch_json(url)
|
data = self._fetch_json(url)
|
||||||
|
|
||||||
if "public_key" not in data.keys() or "servers" not in data.keys():
|
if "public_key" not in data.keys() or "servers" not in data.keys():
|
||||||
raise CollectorException("FinalCommander JSON seems to be wrong.")
|
raise CollectorException("FinalCommander JSON seems to be wrong.")
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def get_instances(self, fcmm_data):
|
def get_instances(self, fcmm_data):
|
||||||
for server in fcmm_data["servers"]:
|
for server in fcmm_data["servers"]:
|
||||||
|
@ -64,7 +70,9 @@ class Collector(object):
|
||||||
up = 0
|
up = 0
|
||||||
metrics.append(Metric("fcmm", "up", {"url": url}, up))
|
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:
|
for server_data in servers_data:
|
||||||
baselabel = {"server": server_data["fcmm_data"]["Address"]}
|
baselabel = {"server": server_data["fcmm_data"]["Address"]}
|
||||||
|
|
||||||
|
@ -80,21 +88,34 @@ class Collector(object):
|
||||||
|
|
||||||
for name, data in server_data["statistics"].items():
|
for name, data in server_data["statistics"].items():
|
||||||
if name == "http" or name == "tls":
|
if name == "http" or name == "tls":
|
||||||
for k,v in data.items():
|
for k, v in data.items():
|
||||||
for subtype,value in v.items():
|
for subtype, value in v.items():
|
||||||
metrics.append(Metric("orbt_stats", f"{name}_{k}", {**baselabel, **{k: subtype}}, value))
|
metrics.append(
|
||||||
|
Metric(
|
||||||
|
"orbt_stats",
|
||||||
|
f"{name}_{k}",
|
||||||
|
{**baselabel, **{k: subtype}},
|
||||||
|
value,
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
for valuetype, value in data.items():
|
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():
|
for name, value in server_data["database"].items():
|
||||||
metrics.append(Metric("orbt_db", name, {**baselabel}, value))
|
metrics.append(Metric("orbt_db", name, {**baselabel}, value))
|
||||||
|
|
||||||
return metrics
|
return metrics
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CollectorException(Exception):
|
class CollectorException(Exception):
|
||||||
"""
|
"""
|
||||||
Base exception class raised by Collector
|
Base exception class raised by Collector
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import socket
|
import socket
|
||||||
import signal
|
import signal
|
||||||
from ipaddress import ip_address
|
from ipaddress import ip_address
|
||||||
from http.server import HTTPServer,BaseHTTPRequestHandler
|
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||||
from selectors import DefaultSelector, EVENT_READ
|
from selectors import DefaultSelector, EVENT_READ
|
||||||
|
|
||||||
from src import Collector
|
from src import Collector
|
||||||
|
|
||||||
class PromServer(HTTPServer):
|
|
||||||
|
class PromServer(HTTPServer):
|
||||||
def __init__(self, address):
|
def __init__(self, address):
|
||||||
if ip_address(address[0]).version == 6:
|
if ip_address(address[0]).version == 6:
|
||||||
self.address_family = socket.AF_INET6
|
self.address_family = socket.AF_INET6
|
||||||
super().__init__(address, self.RequestHandler)
|
super().__init__(address, self.RequestHandler)
|
||||||
|
|
||||||
|
@ -19,14 +20,14 @@ class PromServer(HTTPServer):
|
||||||
|
|
||||||
metrics = [x.format_prom() for x in self.server.collector.collect()]
|
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.send_response(200)
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(output.encode())
|
self.wfile.write(output.encode())
|
||||||
|
|
||||||
def signal_handler(self, signum, frame):
|
def signal_handler(self, signum, frame):
|
||||||
print('Signal handler called with signal', signum)
|
print("Signal handler called with signal", signum)
|
||||||
self.interrupt_write.send(b'\0')
|
self.interrupt_write.send(b"\0")
|
||||||
|
|
||||||
def serve_forever(self):
|
def serve_forever(self):
|
||||||
sel = DefaultSelector()
|
sel = DefaultSelector()
|
||||||
|
@ -41,7 +42,7 @@ class PromServer(HTTPServer):
|
||||||
self.handle_request()
|
self.handle_request()
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.collector = Collector.Collector()
|
self.collector = Collector.Collector()
|
||||||
self.interrupt_read, self.interrupt_write = socket.socketpair()
|
self.interrupt_read, self.interrupt_write = socket.socketpair()
|
||||||
signal.signal(signal.SIGINT, self.signal_handler)
|
signal.signal(signal.SIGINT, self.signal_handler)
|
||||||
self.serve_forever()
|
self.serve_forever()
|
||||||
|
|
25
src/main.py
25
src/main.py
|
@ -3,14 +3,31 @@ import argparse
|
||||||
|
|
||||||
from src import PrometheusServer
|
from src import PrometheusServer
|
||||||
|
|
||||||
|
|
||||||
def start():
|
def start():
|
||||||
parser = argparse.ArgumentParser(description="Run radio exporter")
|
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(
|
||||||
parser.add_argument("-a", "--address", metavar="address", action='store', default='0.0.0.0', help='Address for http server to listen on')
|
"-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()
|
args = parser.parse_args()
|
||||||
|
|
||||||
server = PrometheusServer.PromServer((args.address, args.port))
|
server = PrometheusServer.PromServer((args.address, args.port))
|
||||||
server.start()
|
server.start()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
if __name__ == "__main__":
|
||||||
start()
|
start()
|
||||||
|
|
Loading…
Reference in a new issue