I have not found a way to edit the wiki page for munin plugins so I thought for anyone outthere who created their own munin plugins to monitor mikrotik routers. I couldn’t find a topic for this already, if there is one I appologize.
Below are my plugins that I hope some will find usefull. They build on telnet connection as api in my experience timed out way too much and snmp was too high on the cpu. I’m pretty sure they can be rewritten for ssh, but that may be pricy on the cpu side.
I assume that you are familiar with the munin plugin architecture so will not waste time on it. I have based my plguins on this wiki page http://wiki.mikrotik.com/wiki/Munin_Monitoring which details how you can monitor any mikrotik device with munin. I made some changes and some additional plugins to those on the wiki page. The main difference is that my plugins take the creds from a standalone file in the munins plugin directory which looks like this:
#!/usr/bin/perl
use strict;
use warnings;
our $TelnetPort;
our $TelnetUser;
our $TelnetPass;
$TelnetPort = "23";
$TelnetUser = "munin";
$TelnetPass = "some very secure password goes here";
and should be named mikrotikcreds_. All my plguins will assume the existence of this file and if they don’t exists will throw some hopefully meaningful error message should the require some troubleshooting. I have a single rb751g-2Hnd so my assumptions are based around that. I use telnet for the read-only mgmt user i created for munin for now as I was mainly lazy but I rationalize it with being expensive on the CPU.
and my first somewhat usefull plugin is the CPU grapher which graphs the 3 types of CPU load munin tells you about:
This file should be called mikrotikcpu_
#!/usr/bin/perl
###############################################################################
#use diagnostics;
use Net::Telnet::Cisco;
use strict;
use warnings;
###############################################################################
my @Output = undef;
our $TelnetPort;
our $TelnetUser;
our $TelnetPass;
my $munin_plugins_dir="/etc/munin/plugins/";
###############################################################################
## Determine Hostname
my $Host = undef;
$0 =~ /mikrotikcpu_(.+)*$/;
unless ($Host = $1) {
exit 2;
}
my $creds_file="$munin_plugins_dir/mikrotikcreds_$Host";
if (-e $creds_file){
require "$creds_file";
} else {
die "$creds_file doesn't exist, it needs to exist to store the credentials for all devices. It should look like below:
#######################################
#!/usr/bin/perl
use strict;
use warnings;
our \$TelnetPort;
our \$TelnetUser;
our \$TelnetPass;
\$TelnetPort = \"23\";
\$TelnetUser = \"munin\";
\$TelnetPass = \"someverysecurepassword\";
#######################################
\n";
}
###############################################################################
## Initiate SNMP Session
## Initiate Telnet Session
my $MT = Net::Telnet::Cisco->new(Host => $Host,
Port => $TelnetPort,
Prompt => '/[\>\#] $/',
Timeout => 30);
if (!defined($MT->login($TelnetUser . "+ct", $TelnetPass))) {
die "Croaking: $MT->error";
}
###############################################################################
## Configuration
if ($ARGV[0] && $ARGV[0] eq "config") {
@Output = $MT->cmd("/system resource cpu print");
print "host_name " . $Host . "\n";
print "graph_args -l 0 -r --vertical-label percent --lower-limit 0 --upper-limit 100\n";
print "graph_title CPU usage\n";
print "graph_category system\n";
print "graph_info This graph shows the router's CPU usage.\n";
print "graph_order Total\n";
print "graph_vlabel %\n";
print "graph_scale no\n";
foreach my $Line (@Output) {
my ($junk, $cpu_num, $cpu_name,$load,$irq,$disk)=split(/\s+/,$Line);
if ($cpu_num=~ /^[0-9]$/){
print "Load_".$cpu_name.".label ".$cpu_name." Load %\n";
print "Load_".$cpu_name.".draw LINE2\n";
print "Load_".$cpu_name.".warning 60\n";
print "Load_".$cpu_name.".critical 90\n";
print "IRQ_".$cpu_name.".label ".$cpu_name." IRQ %\n";
print "IRQ_".$cpu_name.".draw LINE2\n";
print "IRQ_".$cpu_name.".warning 60\n";
print "IRQ_".$cpu_name.".critical 90\n";
print "Disk_".$cpu_name.".label ".$cpu_name." Disk %\n";
print "Disk_".$cpu_name.".draw LINE2\n";
print "Disk_".$cpu_name.".warning 60\n";
print "Disk_".$cpu_name.".critical 90\n";
}
}
exit;
}
###############################################################################
## Execution
@Output = $MT->cmd("/system resource cpu print");
foreach my $Line (@Output) {
my ($junk, $cpu_num, $cpu_name,$load,$irq,$disk)=split(/\s+/,$Line);
if ($cpu_num=~ /^[0-9]$/){
$load=~ s/%//g;
$irq=~ s/%//g;
$disk=~ s/%//g;
print "Load_".$cpu_name.".value ".$load."\n";
print "IRQ_".$cpu_name.".value ".$irq."\n";
print "Disk_".$cpu_name.".value ".$disk."\n";
}
}
This one should be called mikrotikifrate__
Thise one uses the /interface print stats-detail where name=“” command and parses the data from it, so that’s what the filename should look like:
For some reason munin doesn’t like spaces in the filenames of the plugins so if you have interface names with spaces you need to replace each space with a . (dot). For example if you have an interface named “my nice readable interface name” on the “my.nice.little.hostname” the symlink to the plugin in the munin plugins directory should look like
. This unfortunately means you can’t really have . (dot) in the interface name as it will be replaced with space.
#!/usr/bin/perl
###############################################################################
use diagnostics;
use Net::Telnet::Cisco;
use strict;
use warnings;
###############################################################################
my @Output = undef;
our $TelnetPort;
our $TelnetUser;
our $TelnetPass;
my $munin_plugins_dir="/etc/munin/plugins/";
###############################################################################
## Determine Hostname
my $Host = undef;
my $Interface = undef;
my $temp = undef;
($temp, $Host, $Interface)=split ("_", $0);
if (!defined($Host) or !defined($Interface)){
die("Hostname or Interface name isn't specified! Filnemae should be like: mikrotikifrate_example.changeip.net_ether1 ");
}
###############################
# This line doees the replacement of .s with spaces. If you don't like comment it out
$Interface=~ s/\./ /g;
###############################
my $creds_file="$munin_plugins_dir/mikrotikcreds_$Host";
if (-e $creds_file){
require "$creds_file";
} else {
die "$creds_file doesn't exist, it needs to exist to store the credentials for all devices. It should look like below:
#######################################
#!/usr/bin/perl
use strict;
use warnings;
our \$TelnetPort;
our \$TelnetUser;
our \$TelnetPass;
\$TelnetPort = \"23\";
\$TelnetUser = \"munin\";
\$TelnetPass = \"someverysecurepassword\";
#######################################
\n";
}
###############################################################################
## Initiate Telnet Session
my $MT = Net::Telnet::Cisco->new(Host => $Host,
Port => $TelnetPort,
Prompt => '/[\>\#] $/',
Timeout => 30);
if (!defined($MT->login($TelnetUser . "+ct", $TelnetPass))) {
die "Croaking: $MT->error";
}
###############################################################################
if ($ARGV[0] and ($ARGV[0] eq "config")) {
print "host_name $Host\n";
print "graph_args --base 1000\n";
print "graph_title \"$Interface\" traffic\n";
print "graph_vlabel bits per second\n";
print "graph_category interfaces\n";
print "graph_info This graph shows the incoming and outgoing traffic rate of an interface\n";
print "in.label received\n";
print "in.type DERIVE\n";
print "in.draw AREA\n";
print "in.min 0\n";
print "in.cdef in,8,*\n";
print "out.label sent\n";
print "out.type DERIVE\n";
print "out.draw LINE1\n";
print "out.min 0\n";
print "out.cdef out,8,*\n";
exit;
}
@Output = $MT->cmd("/interface print stats-detail where name=\"$Interface\"");
foreach my $Line (@Output) {
chomp($Line);
next if ($Line=~/Flags:/ or $Line=~/$Host/);
if ($Line =~ /rx-byte=([0-9 ]+)/){
my $rx_byte=$1;
$rx_byte=~s/ //g;
print "in.value $rx_byte\n";
}
if ($Line =~ /tx-byte=([0-9 ]+)/){
my $tx_byte=$1;
$tx_byte=~s/ //g;
print "out.value $tx_byte\n";
}
}
exit;
this one graphs the wireless clients ccq, names the graphs based on the dhcp-servers hostname if that doesn’t exists based on the MAC address.
should be called mikrotikwirelessccq_
#!/usr/bin/perl
###############################################################################
use diagnostics;
use Net::Telnet::Cisco;
use strict;
use warnings;
##############################################################################
my @Output = undef;
our $TelnetPort;
our $TelnetUser;
our $TelnetPass;
my $munin_plugins_dir="/etc/munin/plugins/";
###############################################################################
## Determine Hostname
my $Host = undef;
$0 =~ /mikrotikwirelessccq_(.+)*$/;
unless ($Host = $1) {
exit 2;
}
my $creds_file="$munin_plugins_dir/mikrotikcreds_$Host";
if (-e $creds_file){
require "$creds_file";
} else {
die "$creds_file doesn't exist, it needs to exist to store the credentials for all devices. It should look like below:
#######################################
#!/usr/bin/perl
use strict;
use warnings;
our \$TelnetPort;
our \$TelnetUser;
our \$TelnetPass;
\$TelnetPort = \"23\";
\$TelnetUser = \"munin\";
\$TelnetPass = \"someverysecurepassword\";
#######################################
\n";
}
###############################################################################
## Initiate Telnet Session
my $MT = Net::Telnet::Cisco->new(Host => $Host,
Port => $TelnetPort,
Prompt => '/[\>\#] $/',
Timeout => 30);
if (!defined($MT->login($TelnetUser . "+ct", $TelnetPass))) {
die "Croaking: $MT->error";
}
###############################################################################
## Configuration
if ($ARGV[0] && $ARGV[0] eq "config") {
print "host_name " . $Host . "\n";
print "graph_args -l 50 --lower-limit 0 --upper-limit 100\n";
print "graph_title Wireless Interface ccq per MAC\n";
print "graph_vlabel ccq %\n";
print "graph_category wireless\n";
print "graph_info This graph shows the wireless ccq\n";
print "graph_scale no\n";
@Output = $MT->cmd("interface wireless registration-table print stats without-paging");
my $current_mac=undef;
my $current_name=undef;
foreach my $Line (@Output) {
if ($Line=~/mac-address=([[0-9A-F:]*) /){
if (defined($current_mac)){
my @dhcp_lease=$MT->cmd("ip dhcp-server lease print value-list where active-mac-address=$current_mac");
foreach my $hostline (@dhcp_lease){
if ($hostline=~/host-name\:/){
$hostline=~s/\s+//g;
my ($item,$value)=split(":",$hostline);
if ($value){
$current_name=$value;
}else{
$current_name=$current_mac;
}
}
}
print "$current_mac.label $current_name ccq\n";
print "$current_mac.type GAUGE\n";
print "$current_mac.draw LINE1 \n";
print "$current_mac.min 0\n";
print "$current_mac.max 100\n";
}
$current_mac=$1;
}
}
my @dhcp_lease=$MT->cmd("ip dhcp-server lease print value-list where active-mac-address=$current_mac");
foreach my $hostline (@dhcp_lease){
if ($hostline=~/host-name\:/){
$hostline=~s/\s+//g;
my ($item,$value)=split(":",$hostline);
if ($value){
$current_name=$value;
}else{
$current_name=$current_mac;
}
}
}
print "$current_mac.label $current_name ccq\n";
print "$current_mac.type GAUGE\n";
print "$current_mac.draw LINE1 \n";
print "$current_mac.min 0\n";
print "$current_mac.max 100\n";
exit;
}
###############################################################################
## Execution
@Output = $MT->cmd("interface wireless registration-table print stats without-paging");
my $current_mac=undef;
my $current_ccq=undef;
foreach my $Line (@Output) {
if ($Line=~/tx-ccq=([0-9]*)% /){
$current_ccq=$1;
}
if ($Line=~/mac-address=([[0-9A-F:]*) /){
if (defined($current_mac)){
print "$current_mac.value $current_ccq\n";
}
$current_mac=$1;
}
}
print "$current_mac.value $current_ccq\n";
exit;