File Coverage

blib/lib/Linux/Info/CpuStats.pm
Criterion Covered Total %
statement 69 80 86.2
branch 18 32 56.2
condition 2 6 33.3
subroutine 9 10 90.0
pod 4 4 100.0
total 102 132 77.2


line stmt bran cond sub pod time code
1             package Linux::Info::CpuStats;
2 2     2   14 use strict;
  2         4  
  2         81  
3 2     2   11 use warnings;
  2         4  
  2         64  
4 2     2   10 use Carp qw(croak);
  2         4  
  2         120  
5 2     2   457 use YAML::XS 0.41;
  2         2973  
  2         2019  
6             our $VERSION = '1.5'; # VERSION
7              
8             =head1 NAME
9              
10             Linux::Info::CpuStats - Collect linux cpu statistics.
11              
12             =head1 SYNOPSIS
13              
14             use Linux::Info::CpuStats;
15              
16             my $lxs = Linux::Info::CpuStats->new;
17             $lxs->init;
18             sleep 1;
19             my $stats = $lxs->get;
20              
21             Or
22              
23             my $lxs = Linux::Info::CpuStats->new(initfile => $file);
24             $lxs->init;
25             my $stats = $lxs->get;
26              
27             =head1 DESCRIPTION
28              
29             Linux::Info::CpuStats gathers cpu statistics from the virtual
30             F filesystem (procfs).
31              
32             For more information read the documentation of the front-end module
33             L.
34              
35             =head1 CPU STATISTICS
36              
37             Generated by F for each cpu (cpu0, cpu1 ...). F without
38             a number is the summary.
39              
40             user - Percentage of CPU utilization at the user level.
41             nice - Percentage of CPU utilization at the user level with nice priority.
42             system - Percentage of CPU utilization at the system level.
43             idle - Percentage of time the CPU is in idle state.
44             total - Total percentage of CPU utilization.
45              
46             Statistics with kernels >= 2.6.
47              
48             iowait - Percentage of time the CPU is in idle state because an I/O operation
49             is waiting to complete.
50             irq - Percentage of time the CPU is servicing interrupts.
51             softirq - Percentage of time the CPU is servicing softirqs.
52             steal - Percentage of stolen CPU time, which is the time spent in other
53             operating systems when running in a virtualized environment (>=2.6.11).
54              
55             =head1 METHODS
56              
57             =head2 new()
58              
59             Call C to create a new object.
60              
61             my $lxs = Linux::Info::CpuStats->new;
62              
63             Maybe you want to store/load the initial statistics to/from a file:
64              
65             my $lxs = Linux::Info::CpuStats->new(initfile => '/tmp/cpustats.yml');
66              
67             If you set C it's not necessary to call sleep before C.
68              
69             It's also possible to set the path to the proc filesystem.
70              
71             Linux::Info::CpuStats->new(
72             files => {
73             # This is the default
74             path => '/proc'
75             stat => 'stat',
76             }
77             );
78              
79             =head2 init()
80              
81             Call C to initialize the statistics.
82              
83             $lxs->init;
84              
85             =head2 get()
86              
87             Call C to get the statistics. C returns the statistics as a hash reference.
88              
89             my $stats = $lxs->get;
90              
91             =head2 raw()
92              
93             Get raw values.
94              
95             =head1 EXPORTS
96              
97             Nothing.
98              
99             =head1 SEE ALSO
100              
101             =over
102              
103             =item *
104              
105             B
106              
107             =item *
108              
109             L
110              
111             =back
112              
113             =head1 AUTHOR
114              
115             Alceu Rodrigues de Freitas Junior, Earfreitas@cpan.orgE
116              
117             =head1 COPYRIGHT AND LICENSE
118              
119             This software is copyright (c) 2015 of Alceu Rodrigues de Freitas Junior, Earfreitas@cpan.orgE
120              
121             This file is part of Linux Info project.
122              
123             Linux-Info is free software: you can redistribute it and/or modify
124             it under the terms of the GNU General Public License as published by
125             the Free Software Foundation, either version 3 of the License, or
126             (at your option) any later version.
127              
128             Linux-Info is distributed in the hope that it will be useful,
129             but WITHOUT ANY WARRANTY; without even the implied warranty of
130             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
131             GNU General Public License for more details.
132              
133             You should have received a copy of the GNU General Public License
134             along with Linux Info. If not, see .
135              
136             =cut
137              
138             sub new {
139 2     2 1 27 my $class = shift;
140 2 50       9 my $opts = ref( $_[0] ) ? shift : {@_};
141              
142 2         9 my %self = (
143             files => {
144             path => '/proc',
145             stat => 'stat',
146             }
147             );
148              
149 2 50       7 if ( defined $opts->{initfile} ) {
150 0         0 $self{initfile} = $opts->{initfile};
151             }
152              
153 2         4 foreach my $file ( keys %{ $opts->{files} } ) {
  2         10  
154 0         0 $self{files}{$file} = $opts->{files}->{$file};
155             }
156              
157 2         10 return bless \%self, $class;
158             }
159              
160             sub raw {
161 0     0 1 0 my $self = shift;
162 0         0 my $stat = $self->_load;
163 0         0 return $stat;
164             }
165              
166             sub init {
167 2     2 1 4 my $self = shift;
168              
169 2 50 33     18 if ( $self->{initfile} && -r $self->{initfile} ) {
170 0         0 $self->{init} = YAML::XS::LoadFile( $self->{initfile} );
171             }
172             else {
173 2         7 $self->{init} = $self->_load;
174             }
175             }
176              
177             sub get {
178 2     2 1 11 my $self = shift;
179 2         13 my $class = ref $self;
180              
181 2 50       12 if ( !exists $self->{init} ) {
182 0         0 croak "$class: there are no initial statistics defined";
183             }
184              
185 2         13 $self->{stats} = $self->_load;
186 2         17 $self->_deltas;
187              
188 2 50       20 if ( $self->{initfile} ) {
189 0         0 YAML::XS::DumpFile( $self->{initfile}, $self->{init} );
190             }
191              
192 2         12 return $self->{stats};
193             }
194              
195             #
196             # private stuff
197             #
198              
199             sub _load {
200 4     4   12 my $self = shift;
201 4         11 my $class = ref $self;
202 4         13 my $file = $self->{files};
203 4         9 my ( %stats, $iowait, $irq, $softirq, $steal );
204              
205             my $filename =
206 4 50       28 $file->{path} ? "$file->{path}/$file->{stat}" : $file->{stat};
207 4 50       367 open my $fh, '<', $filename
208             or croak "$class: unable to open $filename ($!)";
209              
210 4         403 while ( my $line = <$fh> ) {
211 96 100       392 if ( $line =~ /^(cpu.*?)\s+(.*)$/ ) {
212 68         95 my $cpu = \%{ $stats{$1} };
  68         230  
213             (
214 68         482 @{$cpu}{qw(user nice system idle)},
  68         237  
215             $iowait, $irq, $softirq, $steal
216             ) = split /\s+/, $2;
217              
218             # iowait, irq and softirq are only set
219             # by kernel versions higher than 2.4.
220             # steal is available since 2.6.11.
221 68 50       288 $cpu->{iowait} = $iowait if defined $iowait;
222 68 50       142 $cpu->{irq} = $irq if defined $irq;
223 68 50       139 $cpu->{softirq} = $softirq if defined $softirq;
224 68 50       307 $cpu->{steal} = $steal if defined $steal;
225             }
226             }
227              
228 4         80 close($fh);
229 4         44 return \%stats;
230             }
231              
232             sub _deltas {
233 2     2   6 my $self = shift;
234 2         8 my $class = ref $self;
235 2         6 my $istat = $self->{init};
236 2         7 my $lstat = $self->{stats};
237              
238 2         4 foreach my $cpu ( keys %{$lstat} ) {
  2         19  
239 34         66 my $icpu = $istat->{$cpu};
240 34         53 my $dcpu = $lstat->{$cpu};
241 34         46 my $uptime;
242              
243 34         45 while ( my ( $k, $v ) = each %{$dcpu} ) {
  306         775  
244 272 50       499 if ( !defined $icpu->{$k} ) {
245 0         0 croak "$class: not defined key found '$k'";
246             }
247              
248 272 50 33     1159 if ( $v !~ /^\d+\z/ || $dcpu->{$k} !~ /^\d+\z/ ) {
249 0         0 croak "$class: invalid value for key '$k'";
250             }
251              
252 272         669 $dcpu->{$k} -= $icpu->{$k};
253 272         393 $icpu->{$k} = $v;
254 272         431 $uptime += $dcpu->{$k};
255             }
256              
257 34         53 foreach my $k ( keys %{$dcpu} ) {
  34         95  
258 272 100       548 if ( $dcpu->{$k} > 0 ) {
    50          
259 49         217 $dcpu->{$k} = sprintf( '%.2f', 100 * $dcpu->{$k} / $uptime );
260             }
261             elsif ( $dcpu->{$k} < 0 ) {
262 0         0 $dcpu->{$k} = sprintf( '%.2f', 0 );
263             }
264             else {
265 223         679 $dcpu->{$k} = sprintf( '%.2f', $dcpu->{$k} );
266             }
267             }
268              
269 34         174 $dcpu->{total} = sprintf( '%.2f', 100 - $dcpu->{idle} );
270             }
271             }
272              
273             1;