123 lines
5.2 KiB
Python
Executable File
123 lines
5.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import logging
|
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
from socket import AF_INET6
|
|
from time import time
|
|
from urllib.parse import parse_qs, urlparse
|
|
|
|
from prometheus_client import (
|
|
CollectorRegistry, Gauge, generate_latest, CONTENT_TYPE_LATEST
|
|
)
|
|
|
|
from config import Config
|
|
from metrics import EjabberdMetrics
|
|
|
|
|
|
class DynamicMetricsHandler(BaseHTTPRequestHandler):
|
|
"""HTTP handler that gives metrics from ``core.REGISTRY``."""
|
|
def do_GET(self):
|
|
params = parse_qs(urlparse(self.path).query)
|
|
registry = self.generator(params)
|
|
if 'name[]' in params:
|
|
registry = registry.restricted_registry(params['name[]'])
|
|
try:
|
|
output = generate_latest(registry)
|
|
except:
|
|
self.send_error(500, 'error generating metric output')
|
|
raise
|
|
self.send_response(200)
|
|
self.send_header('Content-Type', CONTENT_TYPE_LATEST)
|
|
self.end_headers()
|
|
self.wfile.write(output)
|
|
|
|
@staticmethod
|
|
def factory(registry_generator):
|
|
DynMetricsHandler = type('MetricsHandler',
|
|
(DynamicMetricsHandler, object),
|
|
{"generator": registry_generator})
|
|
return DynMetricsHandler
|
|
|
|
|
|
class Prometheus:
|
|
def __init__(self, metrics):
|
|
self.ttl = 10
|
|
self._last_update = 0
|
|
self._metrics = metrics
|
|
|
|
def handler(self, metrics_handler):
|
|
now = time()
|
|
if now >= (self._last_update + self.ttl):
|
|
self._metrics.update()
|
|
self._last_update = now
|
|
|
|
registry = CollectorRegistry(auto_describe=True)
|
|
|
|
Gauge('ejabberd_node_s2s_in', 'count of incoming server-to-server connection', registry=registry).set(self._metrics.get_s2s_in())
|
|
Gauge('ejabberd_node_s2s_out', 'count of outgoing server-to-server connection', registry=registry).set(self._metrics.get_s2s_out())
|
|
|
|
labelnames_vhost = ["vhost"]
|
|
|
|
registered_vhosts = Gauge('ejabberd_registered_vhosts', 'count of user per vhost', labelnames_vhost, registry=registry)
|
|
muc = Gauge('ejabberd_muc', 'count of muc\'s per vhost', labelnames_vhost, registry=registry)
|
|
|
|
online_vhost_node = Gauge('ejabberd_online_vhost_node', 'count of client connections', ["vhost", "node"], registry=registry)
|
|
|
|
online_status = Gauge('ejabberd_online_status', 'count of client connections', ["vhost", "node", "status"], registry=registry)
|
|
online_connection = Gauge('ejabberd_online_connection', 'count of client connections', ["vhost", "node", "connection"], registry=registry)
|
|
online_client = Gauge('ejabberd_online_client', 'count of client software', ["vhost", "node", "client"], registry=registry)
|
|
online_ipversion = Gauge('ejabberd_online_ipversion', 'count of client software', ["vhost", "node", "ipversion"], registry=registry)
|
|
online_client_ipversion = Gauge('ejabberd_online_client_ipversion', 'count of client software', ["vhost", "node", "client", "ipversion"], registry=registry)
|
|
|
|
for host in self._metrics.get_vhosts():
|
|
labels_vhost = host
|
|
|
|
registered_vhosts.labels(labels_vhost).set(self._metrics.get_registered(host))
|
|
muc.labels(labels_vhost).set(self._metrics.get_muc(host))
|
|
|
|
for k, v in self._metrics.get_online_by_node(vhost=host).items():
|
|
online_vhost_node.labels(host, k).set(v)
|
|
|
|
for node in self._metrics.get_nodes():
|
|
for k, v in self._metrics.get_online_by_status(node=node, vhost=host).items():
|
|
online_status.labels(host, node, k).set(v)
|
|
for k, v in self._metrics.get_online_by_connection(node=node, vhost=host).items():
|
|
online_connection.labels(host, node, k).set(v)
|
|
for k, v in self._metrics.get_online_by_client(node=node, vhost=host).items():
|
|
online_client.labels(host, node, k).set(v)
|
|
for k, v in self._metrics.get_online_by_ipversion(node=node, vhost=host).items():
|
|
online_ipversion.labels(host, node, k).set(v)
|
|
for client, data in self._metrics.get_online_client_by_ipversion(node=node, vhost=host).items():
|
|
for k, v in data.items():
|
|
online_client_ipversion.labels(host, node, client, str(k)).set(v)
|
|
|
|
return registry
|
|
|
|
def listen(self, addr=("127.0.0.1", 8080)):
|
|
if "::" in addr[0]:
|
|
HTTPServer.address_family = AF_INET6
|
|
server = HTTPServer(addr, DynamicMetricsHandler.factory(self.handler))
|
|
server.serve_forever()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# load config
|
|
config = Config()
|
|
if config.get('debug', default=False):
|
|
logging.getLogger().setLevel(logging.DEBUG)
|
|
|
|
# credentials and parameters
|
|
url = config.get('url', default='http://[::1]:5280/api')
|
|
login = config.get('login', default=None)
|
|
api = config.get('api', default='rest')
|
|
|
|
# config prometheus
|
|
prom_addr = config.get('prometheus_address', default='127.0.0.1')
|
|
prom_port = config.get('prometheus_port', default=8080)
|
|
|
|
metrics = EjabberdMetrics(url, login, api)
|
|
prom = Prometheus(metrics)
|
|
prom.ttl = config.get('prometheus_cache_ttl', default=10)
|
|
prom.listen((prom_addr, prom_port))
|