ejabberd-tools/prometheus.py

122 lines
5.2 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import subprocess
import logging
from time import time
from collections import defaultdict
from http.server import BaseHTTPRequestHandler, HTTPServer
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 >= i(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,str(k),client).set(v)
return registry
def listen(self, addr=("127.0.0.1", 8080)):
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))