#!/usr/bin/env python3 # Copyright (c) 2010 Christoph Heer (Christoph.Heer@googlemail.com) # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the \"Software\"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. import sys import os import telnetlib import re def main(): try: mode = sys.argv[1] except IndexError: mode = "" wildcard = sys.argv[0].split("prosody_")[1].split("_")[0] host = os.environ.get('host', 'localhost') port = int(os.environ.get('port', 5582)) if mode == "suggest": print("c2s") print("s2s") print("presence") print("uptime") print("users") sys.exit(0) if wildcard == "c2s": if mode == "config": print("graph_title Prosody C2S Connections") print("graph_vlabel users") print("graph_category chat") print("all_client_connections.label client connections") print("secure_client_connections.label secure client connections") print("insecure_client_connections.label insecure client connections") sys.exit(0) else: connection_count_re = re.compile(r"Total:\s(\d+)\s") telnet = telnetlib.Telnet(host, port) telnet.write(b"c2s:show_secure()\n") telnet_response = telnet.read_until(b"secure client connections", 5) parsed_info = connection_count_re.findall(telnet_response.decode()) secure_client_connections = int(parsed_info[0]) print("secure_client_connections.value %s" % secure_client_connections) telnet.write(b"c2s:show_insecure()\n") telnet_response = telnet.read_until(b"insecure client connections", 5) parsed_info = connection_count_re.findall(telnet_response.decode()) insecure_client_connections = int(parsed_info[0]) print("insecure_client_connections.value %s" % insecure_client_connections) all_client_connections = secure_client_connections + insecure_client_connections print("all_client_connections.value %s" % (all_client_connections)) telnet.write(b"quit\n") elif wildcard == "s2s": if mode == "config": print("graph_title Prosody S2S Connections") print("graph_vlabel servers") print("graph_category chat") print("outgoing_connections.label outgoing connections") print("incoming_connections.label incoming connections") sys.exit(0) else: server_connections_re = re.compile(r"(\d+) outgoing, (\d+)") telnet = telnetlib.Telnet(host, port) telnet.write(b"s2s:show()\n") telnet_response = telnet.read_until(b"connections", 5) parsed_info = server_connections_re.findall(telnet_response.decode()) print("outgoing_connections.value %s" % (parsed_info[0][0])) print("incoming_connections.value %s" % (parsed_info[0][1])) telnet.write(b"quit\n") elif wildcard == "presence": if mode == "config": print("graph_title Prosody Client Presence") print("graph_vlabel clients") print("graph_category chat") print("available.label Available Clients") print("chat.label Ready for Chat Clients") print("away.label Away Clients") print("xa.label Extended Away Clients") print("dnd.label Do Not Disturb Clients") sys.exit(0) else: client_presence_re = re.compile(r"[\]] (.*?)\(\d+\)") telnet = telnetlib.Telnet(host, port) telnet.write(b"c2s:show()\n") telnet_response = telnet.read_until(b"clients", 5) parsed_info = client_presence_re.findall(telnet_response.decode()) print("available.value %s" % parsed_info.count("available")) print("chat.value %s" % (parsed_info.count("chat"))) print("away.value %s" % (parsed_info.count("away"))) print("xa.value %s" % (parsed_info.count("xa"))) print("dnd.value %s" % (parsed_info.count("dnd"))) telnet.write(b"quit\n") elif wildcard == "uptime": if mode == "config": print("graph_title Prosody Uptime") print("graph_args --base 1000 -l 0") print("graph_scale no") print("graph_vlabel uptime in days") print("graph_category chat") print("graph_order uptime") print("uptime.draw AREA") print("uptime.min U") print("uptime.max U") print("uptime.label uptime") print("uptime.type GAUGE") sys.exit(0) else: uptime_re = re.compile(r"\d+") telnet = telnetlib.Telnet(host, port) telnet.write(b"server:uptime()\n") telnet_response = telnet.read_until(b"minutes (", 5) parsed_info = uptime_re.findall(telnet_response.decode()) uptime_value = (float(parsed_info[0]) + float(parsed_info[1]) / 24 + float(parsed_info[2]) / 60 / 24) print("uptime.value %s" % (uptime_value)) telnet.write(b"quit\n") elif wildcard == "users": if mode == "config": print("graph_title Prosody Registered Users") print("graph_vlabel users") print("graph_category chat") base_dir = os.environ.get('internal_storage_path', "/var/lib/prosody") if os.path.isdir(base_dir): vhosts = listdirs(base_dir) for vhost in vhosts: account_dir = os.path.join(base_dir, vhost, "accounts") if os.path.isdir(account_dir): vhost = vhost.replace("%2e", ".") munin_var = vhost.replace(".", "_") if mode == "config": print("%s.label %s" % (munin_var, vhost)) else: accounts = len(list(listfiles(account_dir))) print("%s.value %s" % (munin_var, accounts)) def listdirs(folder): for x in os.listdir(folder): if os.path.isdir(os.path.join(folder, x)): yield x def listfiles(folder): for x in os.listdir(folder): if os.path.isfile(os.path.join(folder, x)): yield x if __name__ == '__main__': main() # Here starts the prosody_ plugin documentation, intended to be used with munindoc and in # plugin gallery. """ =head1 NAME prosody_ - Munin wildcard-plugin to monitor a L xmpp server. This wildcard plugin provides at the moment only the suffixes C, C, C, C and C suffixes. =head1 INSTALLATION It is very simple to install the plugin. =over 2 cd /usr/share/munin/plugins (or your munin plugins directory) wget https://github.com/jarus/munin-prosody/raw/master/prosody_ chmod 755 prosody_ ln -s /usr/share/munin/plugins/prosody_ /etc/munin/plugins/prosody_c2s ln -s /usr/share/munin/plugins/prosody_ /etc/munin/plugins/prosody_s2s ln -s /usr/share/munin/plugins/prosody_ /etc/munin/plugins/prosody_presence ln -s /usr/share/munin/plugins/prosody_ /etc/munin/plugins/prosody_uptime ln -s /usr/share/munin/plugins/prosody_ /etc/munin/plugins/prosody_users =back After the installation you need to restart your munin-node: =over 2 service munin-node restart =back =head1 CONFIGURATION When you want to change the default host (localhost) and port (5582) do it in a file named prosody placed in the directory /etc/munin/plugin-conf.d/ with a config like this: =over 2 [prosody_*] env.host example.com env.port 5582 =back If you want to get the number of registered users, add the following lines to /etc/munin/plugin-conf.d/prosody: =over 2 [prosody_users] user prosody group prosody =back =head1 VERSION Version 2.2 =head1 BUGS None known =head1 AUTHOR (C) 2010 Christoph Heer =head1 LICENSE Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =cut """