File Coverage

blib/lib/Sys/Statistics/Linux/NetStats.pm
Criterion Covered Total %
statement 69 85 81.1
branch 15 26 57.6
condition 4 9 44.4
subroutine 10 11 90.9
pod 5 5 100.0
total 103 136 75.7


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Sys::Statistics::Linux::NetStats - Collect linux net statistics.
4              
5             =head1 SYNOPSIS
6              
7             use Sys::Statistics::Linux::NetStats;
8              
9             my $lxs = Sys::Statistics::Linux::NetStats->new;
10             $lxs->init;
11             sleep 1;
12             my $stat = $lxs->get;
13              
14             Or
15              
16             my $lxs = Sys::Statistics::Linux::NetStats->new(initfile => $file);
17             $lxs->init;
18             my $stat = $lxs->get;
19              
20             =head1 DESCRIPTION
21              
22             Sys::Statistics::Linux::NetStats gathers net statistics from the virtual F filesystem (procfs).
23              
24             For more information read the documentation of the front-end module L.
25              
26             =head1 NET STATISTICS
27              
28             Generated by F.
29              
30             rxbyt - Number of bytes received per second.
31             rxpcks - Number of packets received per second.
32             rxerrs - Number of errors that happend while received packets per second.
33             rxdrop - Number of packets that were dropped per second.
34             rxfifo - Number of FIFO overruns that happend on received packets per second.
35             rxframe - Number of carrier errors that happend on received packets per second.
36             rxcompr - Number of compressed packets received per second.
37             rxmulti - Number of multicast packets received per second.
38             txbyt - Number of bytes transmitted per second.
39             txpcks - Number of packets transmitted per second.
40             txerrs - Number of errors that happend while transmitting packets per second.
41             txdrop - Number of packets that were dropped per second.
42             txfifo - Number of FIFO overruns that happend on transmitted packets per second.
43             txcolls - Number of collisions that were detected per second.
44             txcarr - Number of carrier errors that happend on transmitted packets per second.
45             txcompr - Number of compressed packets transmitted per second.
46             ttpcks - Number of total packets (received + transmitted) per second.
47             ttbyt - Number of total bytes (received + transmitted) per second.
48              
49             =head1 METHODS
50              
51             =head2 new()
52              
53             Call C to create a new object.
54              
55             my $lxs = Sys::Statistics::Linux::NetStats->new;
56              
57             Maybe you want to store/load the initial statistics to/from a file:
58              
59             my $lxs = Sys::Statistics::Linux::NetStats->new(initfile => '/tmp/netstats.yml');
60              
61             If you set C it's not necessary to call sleep before C.
62              
63             It's also possible to set the path to the proc filesystem.
64              
65             Sys::Statistics::Linux::NetStats->new(
66             files => {
67             # This is the default
68             path => '/proc',
69             netdev => 'net/dev',
70             }
71             );
72              
73             =head2 init()
74              
75             Call C to initialize the statistics.
76              
77             $lxs->init;
78              
79             =head2 get()
80              
81             Call C to get the statistics. C returns the statistics as a hash reference.
82              
83             my $stat = $lxs->get;
84              
85             =head2 raw()
86              
87             The same as get_raw() but it's not necessary to call init() first.
88              
89             =head2 get_raw()
90              
91             Call C to get the raw data - no deltas.
92              
93             =head1 EXPORTS
94              
95             No exports.
96              
97             =head1 SEE ALSO
98              
99             B
100              
101             =head1 REPORTING BUGS
102              
103             Please report all bugs to .
104              
105             =head1 AUTHOR
106              
107             Jonny Schulz .
108              
109             =head1 COPYRIGHT
110              
111             Copyright (c) 2006, 2007 by Jonny Schulz. All rights reserved.
112              
113             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
114              
115             =cut
116              
117             package Sys::Statistics::Linux::NetStats;
118              
119 1     1   5 use strict;
  1         2  
  1         44  
120 1     1   6 use warnings;
  1         2  
  1         36  
121 1     1   6 use Carp qw(croak);
  1         2  
  1         70  
122 1     1   1173 use Time::HiRes;
  1         2881  
  1         5  
123              
124             our $VERSION = '0.21';
125              
126             sub new {
127 1     1 1 4 my $class = shift;
128 1 50       4 my $opts = ref($_[0]) ? shift : {@_};
129              
130 1         8 my %self = (
131             files => {
132             path => '/proc',
133             netdev => 'net/dev',
134             }
135             );
136              
137 1 50       5 if (defined $opts->{initfile}) {
138 0         0 require YAML::Syck;
139 0         0 $self{initfile} = $opts->{initfile};
140             }
141              
142 1         2 foreach my $file (keys %{ $opts->{files} }) {
  1         5  
143 0         0 $self{files}{$file} = $opts->{files}->{$file};
144             }
145              
146 1         8 return bless \%self, $class;
147             }
148              
149             sub init {
150 1     1 1 2 my $self = shift;
151              
152 1 50 33     12 if ($self->{initfile} && -r $self->{initfile}) {
153 0         0 $self->{init} = YAML::Syck::LoadFile($self->{initfile});
154 0         0 $self->{time} = delete $self->{init}->{time};
155             } else {
156 1         8 $self->{time} = Time::HiRes::gettimeofday();
157 1         4 $self->{init} = $self->_load;
158             }
159             }
160              
161             sub get {
162 1     1 1 4 my $self = shift;
163 1         2 my $class = ref $self;
164              
165 1 50       5 if (!exists $self->{init}) {
166 0         0 croak "$class: there are no initial statistics defined";
167             }
168              
169 1         5 $self->{stats} = $self->_load;
170 1         5 $self->_deltas;
171              
172 1 50       5 if ($self->{initfile}) {
173 0         0 $self->{init}->{time} = $self->{time};
174 0         0 YAML::Syck::DumpFile($self->{initfile}, $self->{init});
175             }
176              
177 1         5 return $self->{stats};
178             }
179              
180             sub raw {
181 0     0 1 0 my $self = shift;
182 0         0 my $stat = $self->_load;
183              
184 0         0 return $stat;
185             }
186              
187             sub get_raw {
188 1     1 1 2 my $self = shift;
189 1         2 my %raw = %{$self->{init}};
  1         5  
190 1         3 delete $raw{time};
191 1         5 return \%raw;
192             }
193              
194             #
195             # private stuff
196             #
197              
198             sub _load {
199 2     2   5 my $self = shift;
200 2         5 my $class = ref $self;
201 2         5 my $file = $self->{files};
202 2         3 my %stats = ();
203              
204 2 50       11 my $filename = $file->{path} ? "$file->{path}/$file->{netdev}" : $file->{netdev};
205 2 50       317 open my $fh, '<', $filename or croak "$class: unable to open $filename ($!)";
206              
207 2         88 while (my $line = <$fh>) {
208 8 100       51 next unless $line =~ /^\s*(.+?):\s*(.*)/;
209 4         57 @{$stats{$1}}{qw(
  4         52  
210             rxbyt rxpcks rxerrs rxdrop rxfifo rxframe rxcompr rxmulti
211             txbyt txpcks txerrs txdrop txfifo txcolls txcarr txcompr
212             )} = split /\s+/, $2;
213 4         28 $stats{$1}{ttbyt} = $stats{$1}{rxbyt} + $stats{$1}{txbyt};
214 4         39 $stats{$1}{ttpcks} = $stats{$1}{rxpcks} + $stats{$1}{txpcks};
215             }
216              
217 2         25 close($fh);
218 2         19 return \%stats;
219             }
220              
221             sub _deltas {
222 1     1   4 my $self = shift;
223 1         3 my $class = ref $self;
224 1         2 my $istat = $self->{init};
225 1         3 my $lstat = $self->{stats};
226 1         5 my $time = Time::HiRes::gettimeofday();
227 1         15 my $delta = sprintf('%.2f', $time - $self->{time});
228 1         2 $self->{time} = $time;
229              
230 1         2 foreach my $dev (keys %{$lstat}) {
  1         4  
231 2 50       7 if (!exists $istat->{$dev}) {
232 0         0 delete $lstat->{$dev};
233 0         0 next;
234             }
235              
236 2         3 my $idev = $istat->{$dev};
237 2         3 my $ldev = $lstat->{$dev};
238              
239 2         3 while (my ($k, $v) = each %{$ldev}) {
  38         111  
240 36 50       74 if (!defined $idev->{$k}) {
241 0         0 croak "$class: not defined key found '$k'";
242             }
243              
244 36 50 33     185 if ($v !~ /^\d+\z/ || $ldev->{$k} !~ /^\d+\z/) {
245 0         0 croak "$class: invalid value for key '$k'";
246             }
247              
248 36 100 66     130 if ($ldev->{$k} == $idev->{$k} || $idev->{$k} > $ldev->{$k}) {
    50          
249 32         51 $ldev->{$k} = sprintf('%.2f', 0);
250             } elsif ($delta > 0) {
251 4         21 $ldev->{$k} = sprintf('%.2f', ($ldev->{$k} - $idev->{$k}) / $delta);
252             } else {
253 0         0 $ldev->{$k} = sprintf('%.2f', $ldev->{$k} - $idev->{$k});
254             }
255              
256 36         63 $idev->{$k} = $v;
257             }
258             }
259             }
260              
261             1;