Merge branch 'add-ci' into 'master'

Add ci

See merge request sum7/ejabberd-tools!6
This commit is contained in:
genofire 2020-06-29 19:34:48 +02:00
commit 091b6e525a
11 changed files with 205 additions and 106 deletions

38
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,38 @@
image: "python:3.7"
variables:
# force pip cache dir
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
cache:
paths:
- .cache/pip # pip caching directory
# setup environemnt
before_script:
- python --version
- pip install -r requirements.txt
- pip install flake8 black
stages:
- syntax
- code consistency
- flake8
syntax:
stage: syntax
script:
# flake8 check only breaking errors ie syntax errors
- flake8 --select=E9,F63,F7,F82 --show-source
black:
stage: code consistency
script:
# code consistency
- black . --check
pep8:
stage: flake8
script:
# full flake8 test
- flake8 --show-source

View File

@ -48,7 +48,7 @@ listen:
acl: acl:
api: api:
user: user:
- "api_user@magicbroccoli.de" - "api_user@magicbroccoli.de"
loopback: loopback:
ip: ip:
@ -59,7 +59,7 @@ acl:
api_permissions: api_permissions:
"api access": "api access":
from: from:
- mod_http_api - mod_http_api
who: who:
access: access:
allow: allow:
@ -81,7 +81,7 @@ configuration file should be located at `/etc/ejabberd-metrics.yml`.
#### systemd service #### systemd service
To properly operate the metrics exporter tools, we created some systemd service templates, to simplify the whole To properly operate the metrics exporter tools, we created some systemd service templates, to simplify the whole
process. If the `ejabberd-metrics.yml` file is not accessible for the user`nobody:nogroup`, it is required to update the process. If the `ejabberd-metrics.yml` file is not accessible for the user`nobody:nogroup`, it is required to update the
`User` and `Group` definitions inside the service file. `User` and `Group` definitions inside the service file.
If a virtualenv is used, it is required to update the `Environment=PATH` to include the `venv/bin` directory created If a virtualenv is used, it is required to update the `Environment=PATH` to include the `venv/bin` directory created
earlier. earlier.

7
api.py
View File

@ -9,6 +9,7 @@ class EjabberdApi:
""" """
class to interact with the ejabberd rest/ xmlrpc api class to interact with the ejabberd rest/ xmlrpc api
""" """
def __init__(self, url, login=None, api: str = "rpc"): def __init__(self, url, login=None, api: str = "rpc"):
# api variables # api variables
self._login = login self._login = login
@ -25,7 +26,7 @@ class EjabberdApi:
@property @property
def _auth(self) -> (str, None): def _auth(self) -> (str, None):
if self._login is not None: if self._login is not None:
return f"{self._login['user']}@{self._login['server']}", self._login['password'] return f"{self._login['user']}@{self._login['server']}", self._login["password"]
return None return None
def _rest(self, command: str, data) -> dict: def _rest(self, command: str, data) -> dict:
@ -34,7 +35,7 @@ class EjabberdApi:
self.session.auth = self._auth self.session.auth = self._auth
# post # post
r = self.session.post('/'.join([self._url, command]), json=data) r = self.session.post("/".join([self._url, command]), json=data)
# proceed if response is ok # proceed if response is ok
if r.ok: if r.ok:
@ -52,6 +53,6 @@ class EjabberdApi:
return fn(self._login, data) return fn(self._login, data)
return fn(data) return fn(data)
except: except: # noqa: E722
# this needs to be more specific # this needs to be more specific
return {} return {}

View File

@ -14,8 +14,8 @@ class EjabberdApiCalls(EjabberdApi):
@property @property
def nodename(self): def nodename(self):
if self._login is not None: if self._login is not None:
node_str = re.compile('The node \'(.*)\'') node_str = re.compile("The node '(.*)'")
status = self.cmd('status', {}) status = self.cmd("status", {})
# matches # matches
try: try:
@ -32,8 +32,8 @@ class EjabberdApiCalls(EjabberdApi):
@property @property
def verstring(self): def verstring(self):
if self._login is not None: if self._login is not None:
ver_str = re.compile('([1-9][0-9.]+(?![.a-z]))\\b') ver_str = re.compile("([1-9][0-9.]+(?![.a-z]))\\b")
status = self.cmd('status', {}) status = self.cmd("status", {})
# matches # matches
try: try:
@ -117,7 +117,7 @@ class EjabberdApiCalls(EjabberdApi):
host = "global" host = "global"
if vhost is not None: if vhost is not None:
if self.verstring.major >= 19: if self.verstring.major >= 19:
host = '.'.join([muc_host, vhost]) host = ".".join([muc_host, vhost])
else: else:
host = vhost host = vhost
result = self.cmd("muc_online_rooms", {"host": host}) result = self.cmd("muc_online_rooms", {"host": host})

View File

@ -20,16 +20,16 @@ class EjabberdCleanup(EjabberdApiCalls):
if self.dry: if self.dry:
logging.warning(f"{user}@{host}: dry delete : {reason}") logging.warning(f"{user}@{host}: dry delete : {reason}")
else: else:
self.cmd("unregister", {"host": host, "user": user}) self.cmd("unregister", {"host": host, "user": user})
logging.warning(f"{user}@{host}: deleted - {reason}") logging.warning(f"{user}@{host}: deleted - {reason}")
def run_user(self, host, user): def run_user(self, host, user):
if self.skip_by_roster: if self.skip_by_roster:
roster = self.cmd("get_roster",{"host": host, "user": user}) roster = self.cmd("get_roster", {"host": host, "user": user})
if len(roster) > 0: if len(roster) > 0:
logging.debug(f"{user}@{host}: skipped it has a roster") logging.debug(f"{user}@{host}: skipped it has a roster")
return return
last = self.cmd("get_last",{"host": host, "user": user}) last = self.cmd("get_last", {"host": host, "user": user})
if self.delete_not_login and last["status"] == "Registered but didn't login": if self.delete_not_login and last["status"] == "Registered but didn't login":
self.delete_user(host, user, "not login") self.delete_user(host, user, "not login")
return return
@ -37,14 +37,16 @@ class EjabberdCleanup(EjabberdApiCalls):
last_stamp = last["timestamp"] last_stamp = last["timestamp"]
lastdate = None lastdate = None
try: try:
lastdate = datetime.datetime.strptime(last_stamp,"%Y-%m-%dT%H:%M:%SZ") lastdate = datetime.datetime.strptime(last_stamp, "%Y-%m-%dT%H:%M:%SZ")
except: except: # noqa: E722
try: try:
lastdate = datetime.datetime.strptime(last_stamp,"%Y-%m-%dT%H:%M:%S.%fZ") lastdate = datetime.datetime.strptime(last_stamp, "%Y-%m-%dT%H:%M:%S.%fZ")
except: except: # noqa: E722
logging.error(f"{user}@{host}: not able to parse '{last_stamp}'") logging.error(f"{user}@{host}: not able to parse '{last_stamp}'")
return return
if lastdate != None and lastdate-datetime.datetime.now() > datetime.timedelta(days=self.offline_since_days): if lastdate is not None and lastdate - datetime.datetime.now() > datetime.timedelta(
days=self.offline_since_days
):
self.delete_user(host, user, f"last seen @ {lastdate}") self.delete_user(host, user, f"last seen @ {lastdate}")
return return
@ -53,7 +55,7 @@ class EjabberdCleanup(EjabberdApiCalls):
if host in self.ignore_hosts: if host in self.ignore_hosts:
continue continue
logging.info(f"run cleanup for host: {host}") logging.info(f"run cleanup for host: {host}")
for user in self.cmd("registered_users",{"host": host}): for user in self.cmd("registered_users", {"host": host}):
if user in self.ignore_usernames: if user in self.ignore_usernames:
continue continue
self.run_user(host, user) self.run_user(host, user)
@ -64,20 +66,20 @@ if __name__ == "__main__":
# load config # load config
config = Config() config = Config()
if config.get('debug', default=False): if config.get("debug", default=False):
logging.getLogger().setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG)
# credentials and parameters # credentials and parameters
url = config.get('url', default='http://localhost:5280/api') url = config.get("url", default="http://localhost:5280/api")
login = config.get('login', default=None) login = config.get("login", default=None)
api = config.get('api', default='rest') api = config.get("api", default="rest")
# init handler # init handler
cleaner = EjabberdCleanup(url, login, api) cleaner = EjabberdCleanup(url, login, api)
cleaner.dry = config.get('cleaner_dry',default=False) cleaner.dry = config.get("cleaner_dry", default=False)
cleaner.ignore_hosts = config.get('cleaner_ignore_hosts',default=[]) cleaner.ignore_hosts = config.get("cleaner_ignore_hosts", default=[])
cleaner.ignore_usernames = config.get('cleaner_ignore_usernames',default=[]) cleaner.ignore_usernames = config.get("cleaner_ignore_usernames", default=[])
cleaner.skip_by_roster = config.get('cleaner_skip_by_roster',default=True) cleaner.skip_by_roster = config.get("cleaner_skip_by_roster", default=True)
cleaner.delete_not_login = config.get('cleaner_delete_not_login',default=True) cleaner.delete_not_login = config.get("cleaner_delete_not_login", default=True)
cleaner.offline_since_days = config.get('cleaner_offline_since_days', default=None) cleaner.offline_since_days = config.get("cleaner_offline_since_days", default=None)
cleaner.run() cleaner.run()

View File

@ -13,11 +13,11 @@ class Config:
def __init__(self): def __init__(self):
# class variables # class variables
self.content = None self.content = None
self.conf_file = Path('/etc/ejabberd-metrics.yml') self.conf_file = Path("/etc/ejabberd-metrics.yml")
# dev config overwrite # dev config overwrite
if environ.get('ejabberd_metrics_dev'): if environ.get("ejabberd_metrics_dev"):
self.conf_file = Path('config.yml') self.conf_file = Path("config.yml")
# read config file # read config file
self._read() self._read()
@ -27,9 +27,9 @@ class Config:
self._check() self._check()
# open file as an iostream # open file as an iostream
with open(self.conf_file, 'r', encoding='utf-8') as f: with open(self.conf_file, "r", encoding="utf-8") as f:
try: try:
self.content = YAML(typ='safe').load(f) self.content = YAML(typ="safe").load(f)
# catch json decoding errors # catch json decoding errors
except (ParserError, ScannerError) as err: except (ParserError, ScannerError) as err:

View File

@ -21,8 +21,8 @@ class Influx:
@staticmethod @staticmethod
def _rmspace(key: str = None, value: (str, int) = None): def _rmspace(key: str = None, value: (str, int) = None):
try: try:
key = key.replace(' ', '\ ') key = key.replace(" ", "\ ") # noqa: W605
value = value.replace(' ', '\ ') value = value.replace(" ", "\ ") # noqa: W605
except (TypeError, AttributeError): except (TypeError, AttributeError):
pass pass
@ -36,10 +36,10 @@ class Influx:
# create tag_key=tag_value pairs for all elements and append them to name # create tag_key=tag_value pairs for all elements and append them to name
for k, v in tags.items(): for k, v in tags.items():
output += ',{}={}'.format(*self._rmspace(k, v)) output += ",{}={}".format(*self._rmspace(k, v))
# append key=value to name # append key=value to name
output += ' {}={}i {}'.format(*self._rmspace(key, value), ts) output += " {}={}i {}".format(*self._rmspace(key, value), ts)
return output return output
def write_metrics(self): def write_metrics(self):
@ -47,53 +47,60 @@ class Influx:
# global values # global values
cur_ts = self._timestamp() cur_ts = self._timestamp()
data.append(f'ejabberd s2s_in={self._metrics.get_s2s_in()}i {cur_ts}') data.append(f"ejabberd s2s_in={self._metrics.get_s2s_in()}i {cur_ts}")
data.append(f'ejabberd s2s_out={self._metrics.get_s2s_out()}i {cur_ts}') data.append(f"ejabberd s2s_out={self._metrics.get_s2s_out()}i {cur_ts}")
data.append(f'ejabberd uptime={self._metrics.get_uptime()}i {cur_ts}') data.append(f"ejabberd uptime={self._metrics.get_uptime()}i {cur_ts}")
data.append(f'ejabberd processes={self._metrics.get_processes()}i {cur_ts}') data.append(f"ejabberd processes={self._metrics.get_processes()}i {cur_ts}")
# vhost values # vhost values
for vhost in self._metrics.get_vhosts(): for vhost in self._metrics.get_vhosts():
cur_ts = self._timestamp() cur_ts = self._timestamp()
data.append(f'ejabberd,vhost={vhost} registered={self._metrics.get_registered(vhost)}i {cur_ts}') data.append(f"ejabberd,vhost={vhost} registered={self._metrics.get_registered(vhost)}i {cur_ts}")
data.append(f'ejabberd,vhost={vhost} muc={self._metrics.get_muc(vhost)}i {cur_ts}') data.append(f"ejabberd,vhost={vhost} muc={self._metrics.get_muc(vhost)}i {cur_ts}")
# vhost statistics on their respective node # vhost statistics on their respective node
for node in self._metrics.get_nodes(): for node in self._metrics.get_nodes():
cur_ts = self._timestamp() cur_ts = self._timestamp()
for k, v in self._metrics.get_online_by_status(node=node, vhost=vhost).items(): for k, v in self._metrics.get_online_by_status(node=node, vhost=vhost).items():
data.append(self._parse('ejabberd_online_status', k, v, cur_ts, {'node': node, 'vhost': vhost})) data.append(self._parse("ejabberd_online_status", k, v, cur_ts, {"node": node, "vhost": vhost}))
for k, v in self._metrics.get_online_by_client(node=node, vhost=vhost).items(): for k, v in self._metrics.get_online_by_client(node=node, vhost=vhost).items():
data.append(self._parse('ejabberd_online_client', k, v, cur_ts, {'node': node, 'vhost': vhost})) data.append(self._parse("ejabberd_online_client", k, v, cur_ts, {"node": node, "vhost": vhost}))
for k, v in self._metrics.get_online_by_ipversion(node=node, vhost=vhost).items(): for k, v in self._metrics.get_online_by_ipversion(node=node, vhost=vhost).items():
data.append(self._parse('ejabberd_online_ipversion', k, v, cur_ts, {'node': node, 'vhost': vhost})) data.append(self._parse("ejabberd_online_ipversion", k, v, cur_ts, {"node": node, "vhost": vhost}))
for k, v in self._metrics.get_online_by_connection(node=node, vhost=vhost).items(): for k, v in self._metrics.get_online_by_connection(node=node, vhost=vhost).items():
data.append(self._parse('ejabberd_online_connection', k, v, cur_ts, {'node': node, 'vhost': vhost})) data.append(self._parse("ejabberd_online_connection", k, v, cur_ts, {"node": node, "vhost": vhost}))
for cl, ipv in self._metrics.get_online_client_by_ipversion(node=node, vhost=vhost).items(): for cl, ipv in self._metrics.get_online_client_by_ipversion(node=node, vhost=vhost).items():
for k, v in ipv.items(): for k, v in ipv.items():
data.append(self._parse('ejabberd_online_client_ipversion', k, v, cur_ts, data.append(
{'vhost': vhost, 'node': node, 'ipversion': k, 'client': cl})) self._parse(
"ejabberd_online_client_ipversion",
k,
v,
cur_ts,
{"vhost": vhost, "node": node, "ipversion": k, "client": cl},
)
)
# write output to database # write output to database
self.client.write_points(data, time_precision='ms', batch_size=10000, protocol='line') self.client.write_points(data, time_precision="ms", batch_size=10000, protocol="line")
if __name__ == '__main__': if __name__ == "__main__":
# load config # load config
config = Config() config = Config()
if config.get('debug', default=False): if config.get("debug", default=False):
logging.getLogger().setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG)
# credentials and parameters # credentials and parameters
url = config.get('url', default='http://localhost:5280/api') url = config.get("url", default="http://localhost:5280/api")
login = config.get('login', default=None) login = config.get("login", default=None)
api = config.get('api', default='rest') api = config.get("api", default="rest")
# config influxdb # config influxdb
influx_host = config.get('influxdb_host', default='localhost') influx_host = config.get("influxdb_host", default="localhost")
influx_port = config.get('influxdb_port', default=8086) influx_port = config.get("influxdb_port", default=8086)
influx_dbname = config.get('influxdb_db', default='ejabberd') influx_dbname = config.get("influxdb_db", default="ejabberd")
# init handler # init handler
metrics = EjabberdMetrics(url, login, api) metrics = EjabberdMetrics(url, login, api)

View File

@ -12,7 +12,8 @@ class EjabberdMetrics(EjabberdApiCalls):
""" """
class to fetch metrics per xmlrpc class to fetch metrics per xmlrpc
""" """
def __init__(self, url, login=None, api="rpc", muc_host: str = 'conference'):
def __init__(self, url, login=None, api="rpc", muc_host: str = "conference"):
# init ejabberd api # init ejabberd api
super().__init__(url, login, api) super().__init__(url, login, api)
@ -32,7 +33,7 @@ class EjabberdMetrics(EjabberdApiCalls):
"profanity": [], "profanity": [],
"Xabber": ["xabber", "xabber-android"], "Xabber": ["xabber", "xabber-android"],
"ChatSecure": ["chatsecure"], "ChatSecure": ["chatsecure"],
"Monal": [] "Monal": [],
} }
for client, names in clientmap.items(): for client, names in clientmap.items():
@ -110,7 +111,7 @@ class EjabberdMetrics(EjabberdApiCalls):
return self.get_online_by("node", vhost=vhost) return self.get_online_by("node", vhost=vhost)
def get_online_by_vhost(self, node=None): 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) return self.get_online_by("jid", parse=lambda jid: jid[jid.find("@") + 1 : jid.find("/")], node=node)
def get_online_by_status(self, vhost=None, node=None): def get_online_by_status(self, vhost=None, node=None):
return self.get_online_by("status", vhost=vhost, node=node) return self.get_online_by("status", vhost=vhost, node=node)
@ -187,11 +188,11 @@ class EjabberdMetrics(EjabberdApiCalls):
return self._uptime return self._uptime
def get_processes(self): def get_processes(self):
if not hasattr(self, '_processes'): if not hasattr(self, "_processes"):
self._processes = self.fetch_processes() self._processes = self.fetch_processes()
return self._processes return self._processes
def get_vhost_metrics(self, vhost): def get_vhost_metrics(self, vhost):
data = { data = {
"registered": self.get_registered(vhost), "registered": self.get_registered(vhost),
"muc": self.get_muc(vhost), "muc": self.get_muc(vhost),
@ -199,7 +200,7 @@ class EjabberdMetrics(EjabberdApiCalls):
"online_by_client": self.get_online_by_client(vhost), "online_by_client": self.get_online_by_client(vhost),
"online_by_ipversion": self.get_online_by_ipversion(vhost), "online_by_ipversion": self.get_online_by_ipversion(vhost),
"online_by_connection": self.get_online_by_connection(vhost), "online_by_connection": self.get_online_by_connection(vhost),
"online_by_node": self.get_online_by_node(vhost) "online_by_node": self.get_online_by_node(vhost),
} }
return data return data
@ -209,13 +210,13 @@ class EjabberdMetrics(EjabberdApiCalls):
self._nodes = self.fetch_nodes() self._nodes = self.fetch_nodes()
return self._nodes return self._nodes
def get_node_metrics(self, node): def get_node_metrics(self, node):
data = { data = {
"online_by_status": self.get_online_by_status(node=node), "online_by_status": self.get_online_by_status(node=node),
"online_by_client": self.get_online_by_client(node=node), "online_by_client": self.get_online_by_client(node=node),
"online_by_ipversion": self.get_online_by_ipversion(node=node), "online_by_ipversion": self.get_online_by_ipversion(node=node),
"online_by_connection": self.get_online_by_connection(node=node), "online_by_connection": self.get_online_by_connection(node=node),
"online_by_vhost": self.get_online_by_vhost(node=node) "online_by_vhost": self.get_online_by_vhost(node=node),
} }
return data return data
@ -225,7 +226,7 @@ class EjabberdMetrics(EjabberdApiCalls):
"registered": self.get_registered(), "registered": self.get_registered(),
"muc": self.get_muc(), "muc": self.get_muc(),
"s2s_in": self.get_s2s_in(), "s2s_in": self.get_s2s_in(),
"s2s_out": self.get_s2s_out(), "s2s_out": self.get_s2s_out(),
"uptime": self.get_uptime(), "uptime": self.get_uptime(),
"processes": self.get_processes(), "processes": self.get_processes(),
"online_by_status": self.get_online_by_status(), "online_by_status": self.get_online_by_status(),
@ -233,14 +234,14 @@ class EjabberdMetrics(EjabberdApiCalls):
"online_by_ipversion": self.get_online_by_ipversion(), "online_by_ipversion": self.get_online_by_ipversion(),
"online_by_connection": self.get_online_by_connection(), "online_by_connection": self.get_online_by_connection(),
"online_by_node": self.get_online_by_node(), "online_by_node": self.get_online_by_node(),
"online_by_vhost": self.get_online_by_vhost() "online_by_vhost": self.get_online_by_vhost(),
} }
vhosts = {} vhosts = {}
for host in self.get_vhosts(): for host in self.get_vhosts():
vhosts[host] = self.get_vhost_metrics(host) vhosts[host] = self.get_vhost_metrics(host)
data["vhosts"] = vhosts data["vhosts"] = vhosts
nodes = {} nodes = {}
for node in self.get_nodes(): for node in self.get_nodes():
nodes[node] = self.get_node_metrics(node) nodes[node] = self.get_node_metrics(node)
@ -259,9 +260,9 @@ if __name__ == "__main__":
config = Config() config = Config()
# credentials and parameters # credentials and parameters
url = config.get('url', default='http://localhost:5280/api') url = config.get("url", default="http://localhost:5280/api")
login = config.get('login', default=None) login = config.get("login", default=None)
api = config.get('api', default='rest') api = config.get("api", default="rest")
# init handler # init handler
metrics = EjabberdMetrics(url, login, api) metrics = EjabberdMetrics(url, login, api)

View File

@ -7,9 +7,7 @@ from socket import AF_INET6
from time import time from time import time
from urllib.parse import parse_qs, urlparse from urllib.parse import parse_qs, urlparse
from prometheus_client import ( from prometheus_client import CollectorRegistry, Gauge, generate_latest, CONTENT_TYPE_LATEST
CollectorRegistry, Gauge, generate_latest, CONTENT_TYPE_LATEST
)
from config import Config from config import Config
from metrics import EjabberdMetrics from metrics import EjabberdMetrics
@ -17,26 +15,25 @@ from metrics import EjabberdMetrics
class DynamicMetricsHandler(BaseHTTPRequestHandler): class DynamicMetricsHandler(BaseHTTPRequestHandler):
"""HTTP handler that gives metrics from ``core.REGISTRY``.""" """HTTP handler that gives metrics from ``core.REGISTRY``."""
def do_GET(self): def do_GET(self):
params = parse_qs(urlparse(self.path).query) params = parse_qs(urlparse(self.path).query)
registry = self.generator(params) registry = self.generator(params)
if 'name[]' in params: if "name[]" in params:
registry = registry.restricted_registry(params['name[]']) registry = registry.restricted_registry(params["name[]"])
try: try:
output = generate_latest(registry) output = generate_latest(registry)
except: except: # noqa: E722
self.send_error(500, 'error generating metric output') self.send_error(500, "error generating metric output")
raise raise
self.send_response(200) self.send_response(200)
self.send_header('Content-Type', CONTENT_TYPE_LATEST) self.send_header("Content-Type", CONTENT_TYPE_LATEST)
self.end_headers() self.end_headers()
self.wfile.write(output) self.wfile.write(output)
@staticmethod @staticmethod
def factory(registry_generator): def factory(registry_generator):
DynMetricsHandler = type('MetricsHandler', DynMetricsHandler = type("MetricsHandler", (DynamicMetricsHandler, object), {"generator": registry_generator})
(DynamicMetricsHandler, object),
{"generator": registry_generator})
return DynMetricsHandler return DynMetricsHandler
@ -45,7 +42,7 @@ class Prometheus:
self.ttl = 10 self.ttl = 10
self._last_update = 0 self._last_update = 0
self._metrics = metrics self._metrics = metrics
def handler(self, metrics_handler): def handler(self, metrics_handler):
now = time() now = time()
if now >= (self._last_update + self.ttl): if now >= (self._last_update + self.ttl):
@ -54,25 +51,53 @@ class Prometheus:
registry = CollectorRegistry(auto_describe=True) 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_in", "count of incoming server-to-server connection", registry=registry).set(
Gauge('ejabberd_node_s2s_out', 'count of outgoing server-to-server connection', registry=registry).set(self._metrics.get_s2s_out()) 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()
)
nodename = self._metrics.nodename nodename = self._metrics.nodename
Gauge('ejabberd_node_uptime', 'uptime of ejabberd service', ["node"], registry=registry).labels(nodename).set(self._metrics.get_uptime()) Gauge("ejabberd_node_uptime", "uptime of ejabberd service", ["node"], registry=registry).labels(nodename).set(
Gauge('ejabberd_node_proccess', 'count of pejabber proccess', ["node"], registry=registry).labels(nodename).set(self._metrics.get_processes()) self._metrics.get_uptime()
)
Gauge("ejabberd_node_proccess", "count of pejabber proccess", ["node"], registry=registry).labels(nodename).set(
self._metrics.get_processes()
)
labelnames_vhost = ["vhost"] labelnames_vhost = ["vhost"]
registered_vhosts = Gauge('ejabberd_registered_vhosts', 'count of user per vhost', labelnames_vhost, registry=registry) registered_vhosts = Gauge(
muc = Gauge('ejabberd_muc', 'count of muc\'s per vhost', labelnames_vhost, registry=registry) "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_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_status = Gauge(
online_ipversion = Gauge('ejabberd_online_ipversion', 'count of client software', ["vhost", "node", "ipversion"], registry=registry) "ejabberd_online_status", "count of client connections", ["vhost", "node", "status"], registry=registry
online_client_ipversion = Gauge('ejabberd_online_client_ipversion', 'count of client software', ["vhost", "node", "client", "ipversion"], 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(): for host in self._metrics.get_vhosts():
labels_vhost = host labels_vhost = host
@ -108,19 +133,19 @@ class Prometheus:
if __name__ == "__main__": if __name__ == "__main__":
# load config # load config
config = Config() config = Config()
if config.get('debug', default=False): if config.get("debug", default=False):
logging.getLogger().setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG)
# credentials and parameters # credentials and parameters
url = config.get('url', default='http://[::1]:5280/api') url = config.get("url", default="http://[::1]:5280/api")
login = config.get('login', default=None) login = config.get("login", default=None)
api = config.get('api', default='rest') api = config.get("api", default="rest")
# config prometheus # config prometheus
prom_addr = config.get('prometheus_address', default='127.0.0.1') prom_addr = config.get("prometheus_address", default="127.0.0.1")
prom_port = config.get('prometheus_port', default=8080) prom_port = config.get("prometheus_port", default=8080)
metrics = EjabberdMetrics(url, login, api) metrics = EjabberdMetrics(url, login, api)
prom = Prometheus(metrics) prom = Prometheus(metrics)
prom.ttl = config.get('prometheus_cache_ttl', default=10) prom.ttl = config.get("prometheus_cache_ttl", default=10)
prom.listen((prom_addr, prom_port)) prom.listen((prom_addr, prom_port))

20
pyproject.toml Normal file
View File

@ -0,0 +1,20 @@
[tool.black]
line-length = 120
target-version = ['py37', 'py38']
include = '\.pyi?$'
exclude = '''
(
/(
\.eggs # exclude a few common directories in the
| \.git # root of the project
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
| dist
)/ # the root of the project
)
'''

5
setup.cfg Normal file
View File

@ -0,0 +1,5 @@
[flake8]
ignore = E501,E203
exclude = .git,__pycache__,.gitlab
max-complexity = 15
max-line-length = 120