Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

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
}