ejabberd-tools/metrics.py

273 lines
8.7 KiB
Python
Raw Normal View History

2019-10-17 05:16:28 +02:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import ipaddress
from calls import EjabberdApiCalls
2019-10-17 05:16:28 +02:00
2019-10-17 13:45:55 +02:00
# rfc6052: IPv6 Addressing of IPv4/IPv6 Translators
nat64 = ipaddress.ip_network("64:ff9b::/96")
class EjabberdMetrics(EjabberdApiCalls):
2019-10-17 05:16:28 +02:00
"""
class to fetch metrics per xmlrpc
"""
def __init__(self, url, login=None, api="rpc", muc_host: str = "conference"):
# init ejabberd api
2020-06-10 12:41:38 +02:00
super().__init__(url, login, api)
# variables
self.muc_host = muc_host
2019-10-17 05:16:28 +02:00
2019-10-17 13:45:55 +02:00
def _client(self, resource):
clientmap = {
"blabber.im": [],
"ChatSecure": ["chatsecure"],
2020-06-09 20:17:29 +02:00
"Conv6ations": ["Conversations with IPv6", "Conv6ations for Sum7"],
2019-10-17 13:45:55 +02:00
"Conversations": [],
"Dino": ["dino"],
"Gajim": ["gajim"],
2019-10-17 13:45:55 +02:00
"jitsi": [],
"Monal": [],
"Pix-Art Messenger": [],
2019-10-17 13:45:55 +02:00
"poezio": [],
"profanity": [],
"Psi+": [],
"Xabber": ["xabber", "xabber-android"],
2019-10-17 13:45:55 +02:00
}
for client, names in clientmap.items():
2019-10-17 13:45:55 +02:00
for c in names:
if c in resource:
return client
if client in resource:
return client
return "other"
@staticmethod
def _ipversion(ip):
2019-10-17 13:45:55 +02:00
addr = ipaddress.ip_address(ip)
if addr.version == 6:
if addr.ipv4_mapped:
return 4
if addr in nat64:
return 4
return addr.version
2019-10-17 05:16:28 +02:00
def update(self):
# nodes
2020-06-10 12:41:38 +02:00
self._nodes = self.fetch_nodes()
2019-10-17 05:16:28 +02:00
# vhosts
2020-06-10 12:41:38 +02:00
self._vhosts = self.fetch_vhosts()
2019-10-17 05:16:28 +02:00
# registered
if not hasattr(self, "_registered"):
self._registered = {}
2020-06-10 12:48:18 +02:00
self._registered[None] = self.fetch_registered_count()
2019-10-17 09:13:00 +02:00
# muc
if not hasattr(self, "_muc"):
self._muc = {}
2020-06-10 23:23:34 +02:00
self._muc[None] = self.fetch_muc_count(muc_host=self.muc_host)
2019-10-17 09:13:00 +02:00
# registered + muc
2019-10-17 05:16:28 +02:00
for vhost in self._vhosts:
2020-06-10 12:48:18 +02:00
self._registered[vhost] = self.fetch_registered_count(vhost)
self._muc[vhost] = self.fetch_muc_count(vhost, muc_host=self.muc_host)
2019-10-17 05:16:28 +02:00
# online user
2020-06-10 12:41:38 +02:00
self._onlineuser = self.fetch_onlineuser()
2019-10-17 09:13:00 +02:00
# s2s
2020-06-10 12:41:38 +02:00
self._s2s_in = self.fetch_s2s_in()
self._s2s_out = self.fetch_s2s_out()
2019-10-17 05:16:28 +02:00
# misc
self._uptime = self.fetch_uptime()
self._processes = self.fetch_processes()
2019-10-17 05:16:28 +02:00
def get_online_by(self, by="node", parse=None, vhost=None, node=None):
parser = parse or (lambda a: a)
if not hasattr(self, "_onlineuser"):
2020-06-10 12:41:38 +02:00
self._onlineuser = self.fetch_onlineuser()
2019-10-17 05:16:28 +02:00
data = {}
for conn in self._onlineuser:
if vhost is not None and vhost not in conn["jid"]:
continue
if node is not None and node != conn["node"]:
continue
if by not in conn:
continue
value = parser(conn[by])
if value not in data:
data[value] = 1
else:
data[value] += 1
return data
def get_online_by_node(self, vhost=None):
return self.get_online_by("node", vhost=vhost)
def get_online_by_vhost(self, node=None):
return self.get_online_by("jid", parse=lambda jid: jid[jid.find("@") + 1 : jid.find("/")], node=node)
2019-10-17 05:16:28 +02:00
def get_online_by_status(self, vhost=None, node=None):
return self.get_online_by("status", vhost=vhost, node=node)
def get_online_by_connection(self, vhost=None, node=None):
return self.get_online_by("connection", vhost=vhost, node=node)
def get_online_by_client(self, vhost=None, node=None):
2019-10-17 13:45:55 +02:00
return self.get_online_by("resource", parse=self._client, vhost=vhost, node=node)
2019-10-17 05:16:28 +02:00
def get_online_by_ipversion(self, vhost=None, node=None):
2019-10-17 13:45:55 +02:00
return self.get_online_by("ip", parse=self._ipversion, vhost=vhost, node=node)
def get_online_client_by(self, by="ip", parse=None, vhost=None, node=None):
parser = parse or self._ipversion
if not hasattr(self, "_onlineuser"):
2020-06-10 12:41:38 +02:00
self._onlineuser = self.fetch_onlineuser()
2019-10-17 13:45:55 +02:00
data = {}
for conn in self._onlineuser:
client = "other"
if "resource" in conn:
client = self._client(conn["resource"])
if client not in data:
data[client] = {}
if vhost is not None and vhost not in conn["jid"]:
continue
if node is not None and node != conn["node"]:
continue
if by not in conn:
continue
value = parser(conn[by])
if value not in data[client]:
data[client][value] = 1
else:
data[client][value] += 1
return data
def get_online_client_by_ipversion(self, vhost=None, node=None):
return self.get_online_client_by("ip", parse=self._ipversion, vhost=vhost, node=node)
2019-10-17 05:16:28 +02:00
def get_registered(self, vhost=None):
if not hasattr(self, "_registered"):
self._registered = {}
if vhost not in self._registered:
2020-06-10 12:48:18 +02:00
self._registered[vhost] = self.fetch_registered_count(vhost)
2019-10-17 05:16:28 +02:00
return self._registered[vhost]
2019-10-17 09:13:00 +02:00
def get_muc(self, vhost=None):
if not hasattr(self, "_muc"):
self._muc = {}
if vhost not in self._muc:
2020-06-10 23:23:34 +02:00
self._muc[vhost] = self.fetch_muc_count(vhost, muc_host=self.muc_host)
2019-10-17 09:13:00 +02:00
return self._muc[vhost]
2019-10-17 05:16:28 +02:00
def get_vhosts(self):
if not hasattr(self, "_vhosts"):
2020-06-10 12:41:38 +02:00
self._vhosts = self.fetch_vhosts()
2019-10-17 05:16:28 +02:00
return self._vhosts
2019-10-17 09:13:00 +02:00
def get_s2s_in(self):
if not hasattr(self, "_s2s_in"):
2020-06-10 12:41:38 +02:00
self._s2s_in = self.fetch_s2s_in()
2019-10-17 09:13:00 +02:00
return self._s2s_in
def get_s2s_out(self):
if not hasattr(self, "_s2s_out"):
2020-06-10 12:41:38 +02:00
self._s2s_out = self.fetch_s2s_out()
2019-10-17 09:13:00 +02:00
return self._s2s_out
def get_uptime(self):
if not hasattr(self, "_uptime"):
self._uptime = self.fetch_uptime()
return self._uptime
def get_processes(self):
if not hasattr(self, "_processes"):
self._processes = self.fetch_processes()
return self._processes
def get_vhost_metrics(self, vhost):
data = {
"registered": self.get_registered(vhost),
"muc": self.get_muc(vhost),
"online_by_status": self.get_online_by_status(vhost),
"online_by_client": self.get_online_by_client(vhost),
"online_by_ipversion": self.get_online_by_ipversion(vhost),
"online_by_connection": self.get_online_by_connection(vhost),
"online_by_node": self.get_online_by_node(vhost),
}
2019-10-17 05:16:28 +02:00
return data
def get_nodes(self):
2019-10-17 05:16:28 +02:00
if not hasattr(self, "_nodes"):
2020-06-10 12:41:38 +02:00
self._nodes = self.fetch_nodes()
2019-10-17 05:16:28 +02:00
return self._nodes
def get_node_metrics(self, node):
data = {
"online_by_status": self.get_online_by_status(node=node),
"online_by_client": self.get_online_by_client(node=node),
"online_by_ipversion": self.get_online_by_ipversion(node=node),
"online_by_connection": self.get_online_by_connection(node=node),
"online_by_vhost": self.get_online_by_vhost(node=node),
}
2019-10-17 05:16:28 +02:00
return data
def get_all(self):
data = {
"registered": self.get_registered(),
"muc": self.get_muc(),
"s2s_in": self.get_s2s_in(),
"s2s_out": self.get_s2s_out(),
"uptime": self.get_uptime(),
"processes": self.get_processes(),
"online_by_status": self.get_online_by_status(),
"online_by_client": self.get_online_by_client(),
"online_by_ipversion": self.get_online_by_ipversion(),
"online_by_connection": self.get_online_by_connection(),
"online_by_node": self.get_online_by_node(),
"online_by_vhost": self.get_online_by_vhost(),
}
2019-10-17 05:16:28 +02:00
vhosts = {}
for host in self.get_vhosts():
vhosts[host] = self.get_vhost_metrics(host)
data["vhosts"] = vhosts
2019-10-17 05:16:28 +02:00
nodes = {}
for node in self.get_nodes():
2019-10-17 05:16:28 +02:00
nodes[node] = self.get_node_metrics(node)
2019-10-17 13:45:55 +02:00
data["online_client_by_ipversion"] = self.get_online_client_by_ipversion()
2019-10-17 05:16:28 +02:00
data["nodes"] = nodes
2019-10-17 05:16:28 +02:00
return data
if __name__ == "__main__":
import json
from config import Config
# load config
config = Config()
# credentials and parameters
url = config.get("url", default="http://localhost:5280/api")
login = config.get("login", default=None)
api = config.get("api", default="rest")
# init handler
metrics = EjabberdMetrics(url, login, api)
data = metrics.get_all()
print(json.dumps(data, indent=True))