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   12 use strict;
  2         3  
  2         55  
3 2     2   8 use warnings;
  2         3  
  2         53  
4 2     2   8 use Carp qw(croak);
  2         4  
  2         94  
5 2     2   778 use YAML::XS 0.41;
  2         4967  
  2         1812  
6             our $VERSION = '1.4'; # 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 4 my $class = shift;
140 2 50       7 my $opts = ref( $_[0] ) ? shift : {@_};
141              
142 2         8 my %self = (
143             files => {
144             path => '/proc',
145             stat => 'stat',
146             }
147             );
148              
149 2 50       6 if ( defined $opts->{initfile} ) {
150 0         0 $self{initfile} = $opts->{initfile};
151             }
152              
153 2         4 foreach my $file ( keys %{ $opts->{files} } ) {
  2         8  
154 0         0 $self{files}{$file} = $opts->{files}->{$file};
155             }
156              
157 2         9 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 3 my $self = shift;
168              
169 2 50 33     14 if ( $self->{initfile} && -r $self->{initfile} ) {
170 0         0 $self->{init} = YAML::XS::LoadFile( $self->{initfile} );
171             }
172             else {
173 2         5 $self->{init} = $self->_load;
174             }
175             }
176              
177             sub get {
178 2     2 1 6 my $self = shift;
179 2         8 my $class = ref $self;
180              
181 2 50       11 if ( !exists $self->{init} ) {
182 0         0 croak "$class: there are no initial statistics defined";
183             }
184              
185 2         10 $self->{stats} = $self->_load;
186 2         12 $self->_deltas;
187              
188 2 50       11 if ( $self->{initfile} ) {
189 0         0 YAML::XS::DumpFile( $self->{initfile}, $self->{init} );
190             }
191              
192 2         11 return $self->{stats};
193             }
194              
195             #
196             # private stuff
197             #
198              
199             sub _load {
200 4     4   10 my $self = shift;
201 4         8 my $class = ref $self;
202 4         8 my $file = $self->{files};
203 4         9 my ( %stats, $iowait, $irq, $softirq, $steal );
204              
205             my $filename =
206 4 50       24 $file->{path} ? "$file->{path}/$file->{stat}" : $file->{stat};
207 4 50       242 open my $fh, '<', $filename
208             or croak "$class: unable to open $filename ($!)";
209              
210 4         347 while ( my $line = <$fh> ) {
211 96 100       348 if ( $line =~ /^(cpu.*?)\s+(.*)$/ ) {
212 68         96 my $cpu = \%{ $stats{$1} };
  68         181  
213             (
214 68         421 @{$cpu}{qw(user nice system idle)},
  68         212  
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       171 $cpu->{iowait} = $iowait if defined $iowait;
222 68 50       134 $cpu->{irq} = $irq if defined $irq;
223 68 50       128 $cpu->{softirq} = $softirq if defined $softirq;
224 68 50       258 $cpu->{steal} = $steal if defined $steal;
225             }
226             }
227              
228 4         61 close($fh);
229 4         34 return \%stats;
230             }
231              
232             sub _deltas {
233 2     2   6 my $self = shift;
234 2         6 my $class = ref $self;
235 2         6 my $istat = $self->{init};
236 2         4 my $lstat = $self->{stats};
237              
238 2         4 foreach my $cpu ( keys %{$lstat} ) {
  2         15  
239 34         60 my $icpu = $istat->{$cpu};
240 34         41 my $dcpu = $lstat->{$cpu};
241 34         45 my $uptime;
242              
243 34         42 while ( my ( $k, $v ) = each %{$dcpu} ) {
  306         774  
244 272 50       470 if ( !defined $icpu->{$k} ) {
245 0         0 croak "$class: not defined key found '$k'";
246             }
247              
248 272 50 33     1056 if ( $v !~ /^\d+\z/ || $dcpu->{$k} !~ /^\d+\z/ ) {
249 0         0 croak "$class: invalid value for key '$k'";
250             }
251              
252 272         543 $dcpu->{$k} -= $icpu->{$k};
253 272         372 $icpu->{$k} = $v;
254 272         435 $uptime += $dcpu->{$k};
255             }
256              
257 34         44 foreach my $k ( keys %{$dcpu} ) {
  34         98  
258 272 100       503 if ( $dcpu->{$k} > 0 ) {
    50          
259 79         281 $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 193         599 $dcpu->{$k} = sprintf( '%.2f', $dcpu->{$k} );
266             }
267             }
268              
269 34         169 $dcpu->{total} = sprintf( '%.2f', 100 - $dcpu->{idle} );
270             }
271             }
272              
273             1;