SIP latency munin plugin

I wrote a plugin to track sip latency on trunks, I just thought I’d share to save people time if they needed the same thing. I based it off of Paul McCormack’s asterisk_sippeers plugin.

#!/usr/bin/perl -w
#
# Copyright (C) 2009 Paul McCormack <[email protected]>
# Modified by Jason Balicki to monitor sip latency of remote devices.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; version 2 dated June,
# 1991.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# If you improve this script please send your version to my email address
# with the copyright notice upgrade with your name.
#
# Plugin to monitor latency of sip peers
#
# needs to run as asterisk or root, put a file in your munin plugins-conf.d
# directory as needed.
#
#%# family=asterisk

use strict;
my $debug=0;
my @users;
my $subnet="192.168.0";

# This sub gets the stats from asterisk and shoves them in a
# hash called %peers.  It will ignore anything that doesn't have
# a OK in the line (getting rid of the header) and ignores
# anything with the subnet in the line (getting rid of local
# devices.)  If you want local devices too, modify the if statement.

sub getstats () {
        open(PEERS, 'asterisk -rx "sip show peers"|');
        my %peers;
        while (<PEERS>)
        {
                chomp($_);
                if (($_ =~ /OK/) && ($_ !~ /$subnet/)){
                        my $latency = 0;
                        my @words = split($_);
                        my @usernames = split(/\//,$_,0);
                        my $username = $usernames[0];
                        my @latencies = split(/ /,$_);
                        my $count=0;
                        $latency = $latencies[27];
                        $latency =~ s/\(//;
                        #print "username is $username latency is $latency \n";
                        $peers{$username}=$latency;
                }
        }
        return(%peers);
}

# get the stats
my %peers=getstats();

# yes, we can autoconf, sort of
if ($ARGV[0] and $ARGV[0] eq "autoconf") {
        print "yes\n";
        exit 0;
}

# spit out the config
if ($ARGV[0] and $ARGV[0] eq "config") {
        print "graph_title Asterisk sip latency\n";
        print "graph_args --base 1000 -l 0\n";
        print "graph_vlabel latency\n";
        print "graph_category asterisk\n";
        my $count=1;
        while ((my $key, my $value) = each (%peers)){
                print "trunk$count.label $key\n";
                $count++;
        }
        print "sip_trunk1.warning 85\n";
        print "sip_trunk1.critical 100\n";
        exit 0;
}


close(PEERS);

# print the actual data.

my $count=1;
while ((my $key, my $value) = each (%peers)) {
        print "trunk$count.value $value\n";
        $count++;
}

HTH someone.

This sounds interesting. Do you run it by the command line?

You use this in conjunction with munin. If you’re not already running munin it won’t be much help to you, but by using it as a munin plugin it will graph your sip trunk latency.

Just drop it in your munin plugins directory (make sure it’s executable,) restart munin-node and wait for results to start showing up in your graphs.

Edit: you’ll probably want to change the “subnet” variable to match your actual internal subnet. If you change subnet to “” then it will graph all SIP endpoints.

The inside scanning of the lines returned from the command could be reduced to:

                chop;
		my $line = $_;
                if (($line =~ /OK/) && ($line !~ /$subnet/)){
                        my $latency = 0;
                        if ($_ =~ /\((\d+) ms\)/) {
			    $latency = $1;
			}
                        my $username = (split(/\//,$line))[0];
                        print "username is $username latency is $latency \n" if ($debug);
                        $peers{$username}=$latency;
                }

Perl coders are fickle… Thanks for this!

Thanks. I’m nowhere near the world’s best perl coder. :slight_smile:

I just type random characters until things work.