Projet

Général

Profil

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

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
}