Projet

Général

Profil

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

root / plugins / network / bandwidth_ @ 17f78427

Historique | Voir | Annoter | Télécharger (7,64 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
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
=head1 USAGE
32

    
33
Any device found in /proc/net/dev can be monitored.  Examples include ipsec*,
34
eth*, irda* and lo.
35

    
36
Please note that aliases cannot be monitored with this plugin.
37

    
38
=head1 VERSION
39

    
40
$Id: bandwidth_,v 1.37 2012/01/23 20:04:33 root Exp $
41

    
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

    
64
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
my $monthlyCap = ($ENV{monthlycap} or 268435456000);
84
my $warnRate = $monthlyCap/$count30;
85

    
86
init();
87

    
88
sub autoconf {
89
    $0 =~ /bandwidth_(.+)*$/;
90
    $interface = $1;
91
    $history = "$ENV{MUNIN_PLUGSTATE}/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
graph_title Monthly Bandwidth average ($interface)
177
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
graph_category network
185
graph_args  --base 1024 -l 0
186
graph_info This graph show your current average bandwidth usage and projected 30 day average based on your last 30 day usage.
187
average.warning $warnRate
188
monthly.warning $monthlyCap
189
30dayusage.warning $monthlyCap
190
EOM
191
    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
        my @arr = split;
212
        $uptime = $arr[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
    return unless $period;  #can't estimate anything from a single point, so don't.
274
    my $total30   = $output_30days;
275
    $total30 += $input_30days unless $ENV{uploadonly};
276
    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
    arg();
285
    exit 2 unless defined $interface;
286
    retrieve_history();
287
    read_traffic();
288
    bit32or64();
289
    uptime();
290
    update_stats();
291
    sum_old();
292
    munin_output();
293
    store_history();
294
}