2019-10-17 07:01:00 +02:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
from ejabberdrpc import EjabberdMetrics
|
|
|
|
|
|
|
|
import time
|
|
|
|
import threading
|
|
|
|
import socket
|
|
|
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
|
|
from socketserver import ThreadingMixIn
|
|
|
|
|
|
|
|
class _ThreadingSimpleServer(ThreadingMixIn, HTTPServer):
|
|
|
|
"""Thread per request HTTP server."""
|
|
|
|
# Make worker threads "fire and forget". Beginning with Python 3.7 this
|
|
|
|
# prevents a memory leak because ``ThreadingMixIn`` starts to gather all
|
|
|
|
# non-daemon threads in a list in order to join on them at server close.
|
|
|
|
# Enabling daemon threads virtually makes ``_ThreadingSimpleServer`` the
|
|
|
|
# same as Python 3.7's ``ThreadingHTTPServer``.
|
|
|
|
daemon_threads = True
|
|
|
|
address_family = socket.AF_INET6
|
|
|
|
|
|
|
|
|
|
|
|
class Prometheus():
|
|
|
|
def __init__(self, metrics):
|
|
|
|
self._metrics = metrics
|
|
|
|
|
|
|
|
def _parse_metric(self, name, value, tags=None):
|
|
|
|
output = name
|
|
|
|
if isinstance(tags, dict):
|
|
|
|
output += "{"
|
|
|
|
first = True
|
|
|
|
for k, v in tags.items():
|
|
|
|
if not first:
|
|
|
|
output += ', '
|
|
|
|
else:
|
|
|
|
first = False
|
|
|
|
output += k+'="'+v+'"'
|
|
|
|
output += '}'
|
|
|
|
return output + ' {}\n'.format(value)
|
|
|
|
|
|
|
|
def _get_metrics(self):
|
|
|
|
output = ""
|
|
|
|
|
2019-10-17 09:13:00 +02:00
|
|
|
output += self._parse_metric("ejabberd_node_s2s_in", self._metrics.get_s2s_in())
|
|
|
|
output += self._parse_metric("ejabberd_node_s2s_out", self._metrics.get_s2s_out())
|
2019-10-17 07:01:00 +02:00
|
|
|
for host in self._metrics.get_vhosts():
|
|
|
|
output += self._parse_metric("ejabberd_registered_vhosts", self._metrics.get_registered(host), {"vhost": host})
|
2019-10-17 09:13:00 +02:00
|
|
|
muc = self._metrics.get_muc(host)
|
|
|
|
if muc is not None:
|
|
|
|
output += self._parse_metric("ejabberd_muc", muc, {"vhost": host})
|
2019-10-17 07:01:00 +02:00
|
|
|
|
|
|
|
for k, v in self._metrics.get_online_by_node(vhost=host).items():
|
|
|
|
output += self._parse_metric("ejabberd_online_vhost_node", v, {"vhost": host, "node": k})
|
|
|
|
|
|
|
|
for node in self._metrics.get_nodes():
|
|
|
|
for k, v in self._metrics.get_online_by_status(node=node, vhost=host).items():
|
|
|
|
output += self._parse_metric("ejabberd_online_status", v, {"vhost": host, "node": node, "status": k})
|
|
|
|
for k, v in self._metrics.get_online_by_connection(node=node, vhost=host).items():
|
|
|
|
output += self._parse_metric("ejabberd_online_connection", v, {"vhost": host, "node": node, "connection": k})
|
|
|
|
for k, v in self._metrics.get_online_by_client(node=node, vhost=host).items():
|
|
|
|
output += self._parse_metric("ejabberd_online_client", v, {"vhost": host, "node": node, "client": k})
|
|
|
|
for k, v in self._metrics.get_online_by_ipversion(node=node, vhost=host).items():
|
|
|
|
output += self._parse_metric("ejabberd_online_ipversion", v, {"vhost": host, "node": node, "ipversion": str(k)})
|
2019-10-17 13:45:55 +02:00
|
|
|
for client, data in self._metrics.get_online_client_by_ipversion(node=node,vhost=host).items():
|
|
|
|
for k, v in data.items():
|
|
|
|
output += self._parse_metric("ejabberd_online_client_ipversion", v, {"vhost": host, "node": node, "ipversion": str(k), "client": client})
|
|
|
|
|
2019-10-17 07:01:00 +02:00
|
|
|
|
|
|
|
return output
|
|
|
|
|
|
|
|
|
|
|
|
def listen(self, port, addr='::'):
|
|
|
|
"""Starts an HTTP server for prometheus metrics as a daemon thread"""
|
|
|
|
class myHandler(BaseHTTPRequestHandler):
|
|
|
|
def do_GET(r):
|
|
|
|
r.send_response(200)
|
|
|
|
r.send_header('Content-type', 'text/html')
|
|
|
|
r.end_headers()
|
|
|
|
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__":
|
2019-12-07 16:01:03 +01:00
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
metrics = EjabberdMetrics(url, login, api)
|
2019-10-17 07:01:00 +02:00
|
|
|
prom = Prometheus(metrics)
|
2019-12-07 16:01:03 +01:00
|
|
|
prom.listen(prom_port)
|
2019-10-17 07:01:00 +02:00
|
|
|
while True:
|
|
|
|
metrics.update()
|
2019-12-07 16:01:03 +01:00
|
|
|
time.sleep(prom_refresh)
|