root / plugins / network / bandwidth_ @ 093708d7
Historique | Voir | Annoter | Télécharger (7,27 ko)
| 1 | 138de37d | Sean Whitney | #!/usr/bin/perl |
|---|---|---|---|
| 2 | # -*- perl -*- |
||
| 3 | ed746fda | Sean Whitney | |
| 4 | 138de37d | Sean Whitney | =head1 NAME |
| 5 | ed746fda | Sean Whitney | |
| 6 | bandwidth_ - Wildcard-plugin to monitor total network traffic and |
||
| 7 | 138de37d | Sean Whitney | predict 30 day bandwidth usage |
| 8 | ed746fda | Sean Whitney | |
| 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 | 138de37d | Sean Whitney | 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 | ed746fda | Sean Whitney | =head1 USAGE |
| 27 | |||
| 28 | Any device found in /proc/net/dev can be monitored. Examples include ipsec*, |
||
| 29 | eth*, irda* and lo. |
||
| 30 | |||
| 31 | 138de37d | Sean Whitney | Please note that aliases cannot be monitored with this plugin. |
| 32 | ed746fda | Sean Whitney | |
| 33 | =head1 VERSION |
||
| 34 | |||
| 35 | 138de37d | Sean Whitney | $Id: bandwidth_,v 1.35 2012/01/23 20:04:33 root Exp $ |
| 36 | ed746fda | Sean Whitney | |
| 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 | d81a0f06 | Sean Whitney | |
| 59 | 138de37d | Sean Whitney | 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 | d81a0f06 | Sean Whitney | graph_title Monthly Bandwidth average |
| 170 | 138de37d | Sean Whitney | 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 | d81a0f06 | Sean Whitney | graph_category network |
| 178 | graph_args --base 1024 -l 0 |
||
| 179 | 138de37d | Sean Whitney | 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 | ed746fda | Sean Whitney | monthly.warning 268435456000 |
| 182 | 138de37d | Sean Whitney | 30dayusage.warning 268435456000 |
| 183 | d81a0f06 | Sean Whitney | EOM |
| 184 | 138de37d | Sean Whitney | 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 | } |
