Projet

Général

Profil

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

root / plugins / network / bandwidth_ @ 9eeaa526

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