...
 
Commits (2)
#!/usr/bin/perl #!/usr/bin/perl
# Copyright 2013 CentralNic Ltd. This program is free software; you can # Copyright 2013 CentralNic Ltd. This program is free software; you can
# redistribute it and/or modify it under the same terms as Perl itself. # redistribute it and/or modify it under the same terms as Perl itself.
use Net::DNS;
use Config::Simple; use Config::Simple;
use File::Basename qw(basename);
use Net::DNS;
use strict; use strict;
# to use this plugin, symlink it to /etc/munin/plugins/rdnds_(rate|time)_(udp|tcp) #
# you'll need to multiple symlinks if you want to monitor rate and time or UDP # to use this plugin, symlink it to /etc/munin/plugins/rdnsd_(rate|time)_(udp|tcp)[_(ipv4|ipv6)]
# and TCP #
# you'll need to multiple symlinks if you want to monitor multiple metrics, for example:
#
# /etc/munin/plugins/rdnsd_rate_udp
# /etc/munin/plugins/rdnsd_rate_tcp
# /etc/munin/plugins/rdnsd_time_udp
# /etc/munin/plugins/rdnsd_time_udp_ipv4 (etc)
#
my (undef, $mode, $proto, $family) = split(/_/, basename($0), 4);
my (undef, $mode, $proto) = split(/_/, $0, 4); die("invalid mode '$mode'") if ($mode !~ /^(rate|time)$/);
#
# construct a list of possible config files based on protocol/family
#
my @files;
if ($family) {
#
# explicit IP version specified
#
if ($family !~ /^ipv(4|6)$/) {
die("invalid family '$family'");
} else {
@files = (
sprintf('/etc/rdnsd/rdnsd_%s_%s.conf', $proto, $family),
sprintf('/etc/rdnsd/rdnsd_%s.conf', $family),
);
}
} else {
@files = (
sprintf('/etc/rdnsd/rdnsd_%s.conf', $proto),
'/etc/rdnsd/rdnsd.conf',
);
}
# this plugin assumes that you have a config file here: #
my @files = ( # look for a config file:
"/etc/rdnsd/rdnsd_$proto.conf", #
"/etc/rdnsd/rdnsd.conf",
);
my $config; my $config;
foreach my $file (@files) { foreach my $file (@files) {
if (-e $file) { if (-e $file) {
...@@ -24,13 +57,15 @@ foreach my $file (@files) { ...@@ -24,13 +57,15 @@ foreach my $file (@files) {
} }
} }
die("unhandled mode '$mode'") if ($mode ne 'rate' && $mode ne 'time'); die("Cannot find configuration file") unless ($config);
my $pidfile = $config->param('PidFile'); my $pidfile = $config->param('PidFile');
my $statsfile = $config->param('StatsFile'); my $statsfile = $config->param('StatsFile');
my $servers = $config->param('Servers'); my $servers = $config->param('Servers');
my $domains = $config->param('Domains'); my $domains = $config->param('Domains');
my $family = $config->param('AddressFamily');
my $update = $config->param('UpdateInterval');
my $timeout = $config->param('Timeout') || 1;
my ($warning, $critical); my ($warning, $critical);
if ('rate' eq $mode) { if ('rate' eq $mode) {
...@@ -45,13 +80,15 @@ if ('rate' eq $mode) { ...@@ -45,13 +80,15 @@ if ('rate' eq $mode) {
my @servers; my @servers;
if ($servers && $domains) { if ($servers && $domains) {
die("Both Servers and Domains are present in config (or were provided as arguments): please choose one or the other"); die("Both 'Servers' and 'Domains' are present in the config file: please choose one or the other");
} elsif ($servers) { } elsif ($servers) {
if (ref($servers) eq 'ARRAY') { if (ref($servers) eq 'ARRAY') {
@servers = @{$servers}; @servers = @{$servers};
} else { } else {
@servers = split(/\s*,\s*/, $servers); @servers = split(/\s*,\s*/, $servers);
} }
} else { } else {
...@@ -72,14 +109,19 @@ die("no servers found") if (scalar(@servers) < 1); ...@@ -72,14 +109,19 @@ die("no servers found") if (scalar(@servers) < 1);
if ($ARGV[0] eq 'config') { if ($ARGV[0] eq 'config') {
print "graph_category DNS\n"; print "graph_category DNS\n";
if ($mode eq 'time') { my $fmt;
printf("graph_title Query Response Time %s\ngraph_vlabel Milliseconds\n", uc($proto)); if ('time' eq $mode) {
$fmt = "graph_title Query Response Time (%s)\n".
"graph_vlabel Response Time (ms)\n";
} elsif ($mode eq 'rate') { } elsif ('rate' eq $mode) {
printf("graph_title Query Response Rate (%s)\ngraph_vlabel Response Rate\ngraph_args --upper-limit 1 -l 0\n", uc($proto)); $fmt = "graph_title Query Response Rate (%s)\n".
"graph_vlabel Response Rate\ngraph_args --upper-limit 1 -l 0\n";
} }
printf($fmt, ($family ? sprintf('IPv%d', substr($family, 3), uc($proto)) : uc($proto)));
foreach my $server (@servers) { foreach my $server (@servers) {
my $name = $server; my $name = $server;
$name =~ s/\./_/g; $name =~ s/\./_/g;
...@@ -92,22 +134,31 @@ if ($ARGV[0] eq 'config') { ...@@ -92,22 +134,31 @@ if ($ARGV[0] eq 'config') {
exit; exit;
} }
# if (!$update) {
# to ensure good statistics, we calculate the maximum acceptable age of the #
# log file, based on the number of servers, the timeout, and a reasonable # no UpdateInterval is defined in the configuration, so we need to send
# number of data points: # the USR1 signal to rdnsd.
# #
my $timeout = $config->param('Timeout') || 1; # to ensure good statistics, we calculate the maximum acceptable age of the
my $maxage = scalar(@servers) * $timeout * 3; # log file, based on the number of servers, the timeout, and a reasonable
# number of data points.
if (time() - (stat($statsfile))[9] > $maxage) { #
die("Error opening '$pidfile': $!") if (!open(PIDFILE, $pidfile)); # if you have a lot of servers, you probably want to configure
chomp(my $pid = <PIDFILE>); # UpdateInterval to ensure reliable stats.
close(PIDFILE); #
my $maxage = scalar(@servers) * $timeout * 3;
die("No processes signalled") if (kill('USR1', $pid) < 1);
if (time() - (stat($statsfile))[9] > $maxage) {
sleep(1); die("Error opening '$pidfile': $!") if (!open(PIDFILE, $pidfile));
chomp(my $pid = <PIDFILE>);
close(PIDFILE);
die("No processes signalled") if (kill('USR1', $pid) < 1);
# now we need to sleep to allow rdnsd to complete its current
# loop and update the stats file:
sleep(1 + $maxage);
}
} }
die("Error opening '$statsfile': $!") if (!open(FILE, $statsfile)); die("Error opening '$statsfile': $!") if (!open(FILE, $statsfile));
......
...@@ -496,7 +496,7 @@ given percentile. See L<STATISTICS FILE FORMAT> for further information. ...@@ -496,7 +496,7 @@ given percentile. See L<STATISTICS FILE FORMAT> for further information.
Specifies whether to prefer IPv4 or IPv6 when talking to nameservers, if Specifies whether to prefer IPv4 or IPv6 when talking to nameservers, if
the servers are identified by name rather than address (or when loaded the servers are identified by name rather than address (or when loaded
from SRC records). If not defined, the default behaviour is to prefer from SRV records). If not defined, the default behaviour is to prefer
IPv6. IPv6.
=item * C<Protocol (udp|tcp)> =item * C<Protocol (udp|tcp)>
......