root / plugins / network / bandwidth_ @ dd4afac8
Historique | Voir | Annoter | Télécharger (7,27 ko)
| 1 |
#!/usr/bin/perl |
|---|---|
| 2 |
# -*- perl -*- |
| 3 |
|
| 4 |
=head1 NAME |
| 5 |
|
| 6 |
bandwidth_ - Wildcard-plugin to monitor total network traffic and |
| 7 |
predict 30 day bandwidth usage |
| 8 |
|
| 9 |
=head1 CONFIGURATION |
| 10 |
|
| 11 |
This is a wildcard plugin. To monitor an interface, link |
| 12 |
bandwidth_<interface> to this file. E.g. |
| 13 |
|
| 14 |
ln -s /usr/share/munin/node/plugins-auto/bandwidth_ \ |
| 15 |
/etc/munin/node.d/bandwidth_eth0 |
| 16 |
|
| 17 |
...will monitor eth0 |
| 18 |
|
| 19 |
Most likely usage is to monitor an interface connected to your ISP. |
| 20 |
|
| 21 |
The suggest option will try and determine if you have any interfaces with a |
| 22 |
public IP and if so it will suggest monitoring those interfaces. If all |
| 23 |
IP addresses are private the setup will have to be done manually. Suggest |
| 24 |
does not handle IPv6 addresses. |
| 25 |
|
| 26 |
=head1 USAGE |
| 27 |
|
| 28 |
Any device found in /proc/net/dev can be monitored. Examples include ipsec*, |
| 29 |
eth*, irda* and lo. |
| 30 |
|
| 31 |
Please note that aliases cannot be monitored with this plugin. |
| 32 |
|
| 33 |
=head1 VERSION |
| 34 |
|
| 35 |
$Id: bandwidth_,v 1.35 2012/01/23 20:04:33 root Exp $ |
| 36 |
|
| 37 |
=head1 AUTHOR |
| 38 |
|
| 39 |
Sean Whitney |
| 40 |
|
| 41 |
=head1 LICENSE |
| 42 |
|
| 43 |
GPLv2 |
| 44 |
|
| 45 |
=head1 MAGIC MARKERS |
| 46 |
|
| 47 |
#%# family=contrib |
| 48 |
#%# capabilities=autoconf suggest |
| 49 |
|
| 50 |
=head1 BUGS |
| 51 |
|
| 52 |
I know that bandwidth is bits and base10 as opposed to bytes and base2. |
| 53 |
However the purpose of this plugin it to monitor your monthly bandwidth |
| 54 |
consumption to make sure you don't go over your ISP's peak. ISP's seem |
| 55 |
to be interested in expressing peaks in bytes.... |
| 56 |
|
| 57 |
=cut |
| 58 |
|
| 59 |
use strict; |
| 60 |
use Storable qw(store retrieve); |
| 61 |
use Switch; |
| 62 |
|
| 63 |
my $interface; |
| 64 |
my $history; |
| 65 |
my $counter_input; |
| 66 |
my $counter_output; |
| 67 |
my $input; |
| 68 |
my $output; |
| 69 |
my $uptime; |
| 70 |
my $oldest_ts; |
| 71 |
my $input_30days; |
| 72 |
my $output_30days; |
| 73 |
my $perf_ref = {};
|
| 74 |
my $count30 = 2592000; # The number of seconds in 30 days |
| 75 |
my $unix_ts = time; |
| 76 |
my $rollover = 4294967295; |
| 77 |
|
| 78 |
eval { init(); };
|
| 79 |
|
| 80 |
sub autoconf {
|
| 81 |
$0 =~ /bandwidth_(.+)*$/; |
| 82 |
$interface = $1; |
| 83 |
exit 2 unless defined $interface; |
| 84 |
$history = "/var/lib/munin/plugin-state/bandwidth_$interface.state"; |
| 85 |
} |
| 86 |
|
| 87 |
sub bit32or64 {
|
| 88 |
if ( $input > $rollover || $output > $rollover ) {
|
| 89 |
$rollover = 18446744073709551615; |
| 90 |
} |
| 91 |
} |
| 92 |
|
| 93 |
sub retrieve_history {
|
| 94 |
return (undef) unless ( -r $history ); |
| 95 |
my $store = retrieve($history); |
| 96 |
while ( my ( $key, $value ) = each(%$store) ) {
|
| 97 |
if ( $unix_ts - $key < $count30 ) {
|
| 98 |
$perf_ref->{$key} = $value;
|
| 99 |
} |
| 100 |
if ( $key =~ /last/ ) {
|
| 101 |
$perf_ref->{$key} = $value;
|
| 102 |
} |
| 103 |
|
| 104 |
} |
| 105 |
} |
| 106 |
|
| 107 |
sub suggest {
|
| 108 |
|
| 109 |
# This only works if one of your interfaces has a public IP, |
| 110 |
# Otherwise it will fail and you will have to set it manually |
| 111 |
# Multiple public IP addresses can be detected. It won't |
| 112 |
# Detect IPv6 addresses. |
| 113 |
my $locate = readpipe("locate -b '\\ifconfig'");
|
| 114 |
my @ifconfig = readpipe($locate); |
| 115 |
my @old; |
| 116 |
my $net = "/proc/net/dev"; |
| 117 |
my @interfaces; |
| 118 |
-f $net || die "Unable to read $net: $!"; |
| 119 |
open( DEV, "<", $net ) || die "Unable to read $net: $!"; |
| 120 |
|
| 121 |
while (<DEV>) {
|
| 122 |
chomp; |
| 123 |
split; |
| 124 |
/Inter|face/ and next; |
| 125 |
split /:/; |
| 126 |
push( @interfaces, $_[0] ); |
| 127 |
} |
| 128 |
close(DEV); |
| 129 |
|
| 130 |
foreach (@ifconfig) {
|
| 131 |
if (/inet addr:([\d.]+)/) {
|
| 132 |
$1 |
| 133 |
=~ /^(127\.\d+|10\.\d+|172\.(1[6-9]|2\d|3[0-1])|192\.168)(\.\d+){2}$/
|
| 134 |
and next; |
| 135 |
exists $interfaces[ $old[0] ] and print "$old[0]\n"; |
| 136 |
} |
| 137 |
@old = split; |
| 138 |
chomp @old; |
| 139 |
} |
| 140 |
exit 0; |
| 141 |
} |
| 142 |
|
| 143 |
sub store_history {
|
| 144 |
|
| 145 |
# Store the current values to the new old times |
| 146 |
$perf_ref->{$unix_ts} = {
|
| 147 |
input => $input, |
| 148 |
output => $output, |
| 149 |
}; |
| 150 |
$perf_ref->{last} = {
|
| 151 |
counter_input => $counter_input, |
| 152 |
counter_output => $counter_output, |
| 153 |
uptime => $uptime, |
| 154 |
}; |
| 155 |
store( $perf_ref, $history ) || die "Unable to store $history: $!"; |
| 156 |
} |
| 157 |
|
| 158 |
sub arg {
|
| 159 |
defined( $ARGV[0] ) or return; |
| 160 |
switch ( $ARGV[0] ) {
|
| 161 |
case 'autoconf' { print "yes\n"; exit 0; }
|
| 162 |
case 'config' { print_config(); }
|
| 163 |
case 'suggest' { suggest(); }
|
| 164 |
} |
| 165 |
} |
| 166 |
|
| 167 |
sub print_config {
|
| 168 |
print <<EOM; |
| 169 |
graph_title Monthly Bandwidth average |
| 170 |
graph_vlabel Bytes (per sec) |
| 171 |
average.label current 30 day average bytes/sec |
| 172 |
monthly.label monthly project based on 30 day average |
| 173 |
30dayusage.label monthly usage |
| 174 |
average.info Your average network rate based (up to) the last 30 days of data |
| 175 |
monthly.info Your projected monthly network rate based on your average network rate |
| 176 |
30dayusage.info Your usage for the last 30 days. |
| 177 |
graph_category network |
| 178 |
graph_args --base 1024 -l 0 |
| 179 |
graph_info This graph show your current average bandwidth usage and projected 30 day average based on your last 30 day usage. |
| 180 |
average.warning 103563 |
| 181 |
monthly.warning 268435456000 |
| 182 |
30dayusage.warning 268435456000 |
| 183 |
EOM |
| 184 |
exit 0; |
| 185 |
} |
| 186 |
|
| 187 |
sub read_traffic {
|
| 188 |
open( my $rx, "<", "/sys/class/net/$interface/statistics/rx_bytes" ) |
| 189 |
|| die "Unable to read: $!"; |
| 190 |
$counter_input = <$rx>; |
| 191 |
chomp $counter_input; |
| 192 |
close($rx); |
| 193 |
open(my $tx , "<", "/sys/class/net/$interface/statistics/tx_bytes" ) |
| 194 |
|| die "Unable to read: $!"; |
| 195 |
$counter_output = <$tx>; |
| 196 |
chomp $counter_output; |
| 197 |
close(DEV); |
| 198 |
} |
| 199 |
|
| 200 |
sub uptime {
|
| 201 |
my $puptime = "/proc/uptime"; |
| 202 |
open( TIME, "<", $puptime ) || die "Unable to read $puptime: $!"; |
| 203 |
while (<TIME>) {
|
| 204 |
split; |
| 205 |
$uptime = @_[0]; |
| 206 |
} |
| 207 |
close(TIME); |
| 208 |
chomp $uptime; |
| 209 |
} |
| 210 |
|
| 211 |
sub update_stats {
|
| 212 |
|
| 213 |
# First determine if this has ever run before. If not set initial values |
| 214 |
# to 0. |
| 215 |
if ( defined $perf_ref->{last}->{uptime} ) {
|
| 216 |
|
| 217 |
# Compute the new totals, caused by reboot. As uptime is measures in |
| 218 |
# 64-bit jiffies, the chance of a counter rollover is remote |
| 219 |
if ( $perf_ref->{last}->{uptime} > $uptime ) {
|
| 220 |
$input = $counter_input; |
| 221 |
$output = $counter_output; |
| 222 |
|
| 223 |
} |
| 224 |
else {
|
| 225 |
if ( $perf_ref->{last}->{counter_input} > $counter_input ) {
|
| 226 |
$input = |
| 227 |
$counter_input |
| 228 |
+ $rollover |
| 229 |
- $perf_ref->{last}->{counter_input};
|
| 230 |
} |
| 231 |
else {
|
| 232 |
$input = $counter_input - $perf_ref->{last}->{counter_input};
|
| 233 |
} |
| 234 |
if ( $perf_ref->{last}->{counter_output} > $counter_output ) {
|
| 235 |
$output = |
| 236 |
$counter_output |
| 237 |
+ $rollover |
| 238 |
- $perf_ref->{last}->{counter_output};
|
| 239 |
} |
| 240 |
else {
|
| 241 |
$output = |
| 242 |
$counter_output - $perf_ref->{last}->{counter_output};
|
| 243 |
} |
| 244 |
} |
| 245 |
} |
| 246 |
else {
|
| 247 |
$input = 0; |
| 248 |
$output = 0; |
| 249 |
} |
| 250 |
} |
| 251 |
|
| 252 |
sub sum_old {
|
| 253 |
$oldest_ts = $unix_ts; |
| 254 |
while ( my ( $key, $value ) = each(%$perf_ref) ) {
|
| 255 |
$key =~ /last/ and next; |
| 256 |
$input_30days += $perf_ref->{$key}->{'input'};
|
| 257 |
$output_30days += $perf_ref->{$key}->{'output'};
|
| 258 |
$key < $oldest_ts and $oldest_ts = $key |
| 259 |
} |
| 260 |
$input_30days += $input; |
| 261 |
$output_30days += $output; |
| 262 |
} |
| 263 |
|
| 264 |
sub munin_output {
|
| 265 |
my $period = $unix_ts - $oldest_ts; |
| 266 |
my $total30 = $input_30days + $output_30days; |
| 267 |
my $average30 = $total30 / $period; |
| 268 |
print "average.value $average30\n"; |
| 269 |
print "monthly.value " . $average30 * $count30 . "\n"; |
| 270 |
print "30dayusage.value $total30\n"; |
| 271 |
} |
| 272 |
|
| 273 |
sub init {
|
| 274 |
arg(); |
| 275 |
autoconf(); |
| 276 |
retrieve_history(); |
| 277 |
read_traffic(); |
| 278 |
bit32or64(); |
| 279 |
uptime(); |
| 280 |
update_stats(); |
| 281 |
sum_old(); |
| 282 |
munin_output(); |
| 283 |
store_history(); |
| 284 |
} |
