diff --git a/.gitignore b/.gitignore index 263cfcc..b4c2e09 100644 --- a/.gitignore +++ b/.gitignore @@ -110,6 +110,7 @@ dmypy.json # Pycharm .idea/ .venv/ +venv # config config.json diff --git a/config.py b/config.py new file mode 100644 index 0000000..55b7639 --- /dev/null +++ b/config.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import json +import sys +from pathlib import Path + + +class Config: + def __init__(self): + # global config path + conf_path = '/etc/ejabberd-metrics.conf' + self.file = Path(conf_path) + self.content = None + + # read config file + self._read() + + def _read(self): + """init the config object with this method""" + self._check() + + # open and load json content from config + with open(self.file, 'r', encoding='utf-8') as f: + try: + self.content = json.load(f) + + # catch json decoding errors + except json.JSONDecodeError as err: + print(err, file=sys.stderr) + exit(1) + + def _check(self): + """internal method to check if the config file exists""" + try: + # if file is present try to read it's contents + if self.file.exists(): + return + + # if not create a blank file + else: + Path.touch(self.file) + + # catch permission exceptions as this tries to write to /etc/ + except PermissionError as err: + print(err, file=sys.stderr) + sys.exit(err.errno) + + def get(self, key: str = None, default: (str, int) = None) -> (dict, str, int, None): + """method to retrieve the whole config data, a single value or the optional default value""" + # if a special key is request, return only that value + if key is not None: + + # safety measure + if key in self.content: + return self.content[key] + + # if a default value is given return that + if default is not None: + return default + + # if the key isn't part if self.content return None + else: + return None + + # else return everything + return self.content diff --git a/influx.py b/influx.py index 36d7a47..59728ac 100644 --- a/influx.py +++ b/influx.py @@ -1,12 +1,10 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- - -import json -import os import time from influxdb import InfluxDBClient +from config import Config from ejabberdrpc import EjabberdMetrics @@ -79,19 +77,17 @@ class Influx: if __name__ == '__main__': # load config - path = os.path.dirname(__file__) - with open('/'.join([path, 'config.json']), 'r', encoding='utf-8') as f: - config = json.load(f) + config = Config() - # creds and params - url = config['url'] if 'url' in config else 'http://localhost:5280/api' - login = config['login'] if 'login' in config else None - api = config['api'] if 'api' in config else 'rest' + # credentials and parameters + url = config.get('url', default='http://localhost:5280/api') + login = config.get('login', default=None) + api = config.get('api', default='rest') # config influxdb - influx_host = config['influxdb_host'] if 'influxdb_host' in config else 'localhost' - influx_port = config['influxdb_port'] if 'influxdb_port' in config else 8086 - influx_dbname = config['influxdb_db'] if 'influxdb_db' in config else 'ejabberd' + influx_host = config.get('influxdb_host', default='localhost') + influx_port = config.get('influxdb_port', default=8086) + influx_dbname = config.get('influxdb_db', default='ejabberd') # init handler metrics = EjabberdMetrics(url, login, api) diff --git a/prometheus.py b/prometheus.py index dfca7d4..4aab1b3 100755 --- a/prometheus.py +++ b/prometheus.py @@ -1,14 +1,16 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from ejabberdrpc import EjabberdMetrics - -import time -import threading import socket +import threading +import time from http.server import BaseHTTPRequestHandler, HTTPServer from socketserver import ThreadingMixIn +from config import Config +from ejabberdrpc import EjabberdMetrics + + class _ThreadingSimpleServer(ThreadingMixIn, HTTPServer): """Thread per request HTTP server.""" # Make worker threads "fire and forget". Beginning with Python 3.7 this @@ -65,10 +67,8 @@ class Prometheus(): for k, v in data.items(): output += self._parse_metric("ejabberd_online_client_ipversion", v, {"vhost": host, "node": node, "ipversion": str(k), "client": client}) - return output - def listen(self, port, addr='::'): """Starts an HTTP server for prometheus metrics as a daemon thread""" class myHandler(BaseHTTPRequestHandler): @@ -79,28 +79,24 @@ class Prometheus(): result = self._get_metrics() r.wfile.write(result.encode('utf-8')) - httpd = _ThreadingSimpleServer((addr, port), myHandler) t = threading.Thread(target=httpd.serve_forever) t.daemon = True t.start() + if __name__ == "__main__": - import os - import json - # load config - path = os.path.dirname(__file__) - with open("/".join([path, "config.json"]), "r", encoding="utf-8") as f: - config = json.load(f) + config = Config() + # credentials and parameters + url = config.get('url', default='http://[::1]:5280/api') + login = config.get('login', default=None) + api = config.get('api', default='rest') - url = config['url'] if "url" in config else "http://[::1]:5280/api" - login = config['login'] if "login" in config else None - api = config['api'] if "api" in config else "rest" - - prom_port = config['prometheus_port'] if "prometheus_port" in config else 8080 - prom_refresh = config['prometheus_refresh'] if "prometheus_refresh" in config else 10 + # config prometheus + prom_port = config.get('prometheus_port', default=8080) + prom_refresh = config.get('prometheus_refresh', default=10) metrics = EjabberdMetrics(url, login, api) prom = Prometheus(metrics)