Repository
Munin (contrib)
Last change
2020-08-25
Graph Categories
Capabilities
Keywords
Language
Python (3.x)
Authors

prosody_

Name

prosody_ - Munin wildcard-plugin to monitor a Prosody xmpp server.

This wildcard plugin provides at the moment only the suffixes c2s, s2s, presence, uptime and users suffixes.

Installation

It is very simple to install the plugin.

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

After the installation you need to restart your munin-node:

service munin-node restart

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:

[prosody_*]
env.host example.com
env.port 5582

If you want to get the number of registered users, add the following lines to /etc/munin/plugin-conf.d/prosody:

[prosody_users]
user prosody
group prosody

Version

Version 2.2

Bugs

None known

Author

(C) 2010 Christoph Heer Christoph.Heer@googlemail.com

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.

#!/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('ascii'))
            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('ascii'))
            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('ascii'))
            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('ascii'))
            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('ascii'))
            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<Prosody|http://prosody.im> xmpp server.

This wildcard plugin provides at the moment only the suffixes C<c2s>, C<s2s>, C<presence>,
C<uptime> and C<users> 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 <Christoph.Heer@googlemail.com>

=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


"""