File Coverage

blib/lib/Sys/Statistics/Linux/CpuStats.pm
Criterion Covered Total %
statement 66 78 84.6
branch 18 32 56.2
condition 2 6 33.3
subroutine 8 9 88.8
pod 4 4 100.0
total 98 129 75.9


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Sys::Statistics::Linux::CpuStats - Collect linux cpu statistics.
4              
5             =head1 SYNOPSIS
6              
7             use Sys::Statistics::Linux::CpuStats;
8              
9             my $lxs = Sys::Statistics::Linux::CpuStats->new;
10             $lxs->init;
11             sleep 1;
12             my $stats = $lxs->get;
13              
14             Or
15              
16             my $lxs = Sys::Statistics::Linux::CpuStats->new(initfile => $file);
17             $lxs->init;
18             my $stats = $lxs->get;
19              
20             =head1 DESCRIPTION
21              
22             Sys::Statistics::Linux::CpuStats gathers cpu statistics from the virtual
23             F filesystem (procfs).
24              
25             For more information read the documentation of the front-end module
26             L.
27              
28             =head1 CPU STATISTICS
29              
30             Generated by F for each cpu (cpu0, cpu1 ...). F without
31             a number is the summary.
32              
33             user - Percentage of CPU utilization at the user level.
34             nice - Percentage of CPU utilization at the user level with nice priority.
35             system - Percentage of CPU utilization at the system level.
36             idle - Percentage of time the CPU is in idle state.
37             total - Total percentage of CPU utilization.
38              
39             Statistics with kernels >= 2.6.
40              
41             iowait - Percentage of time the CPU is in idle state because an I/O operation
42             is waiting to complete.
43             irq - Percentage of time the CPU is servicing interrupts.
44             softirq - Percentage of time the CPU is servicing softirqs.
45             steal - Percentage of stolen CPU time, which is the time spent in other
46             operating systems when running in a virtualized environment (>=2.6.11).
47              
48             =head1 METHODS
49              
50             =head2 new()
51              
52             Call C to create a new object.
53              
54             my $lxs = Sys::Statistics::Linux::CpuStats->new;
55              
56             Maybe you want to store/load the initial statistics to/from a file:
57              
58             my $lxs = Sys::Statistics::Linux::CpuStats->new(initfile => '/tmp/cpustats.yml');
59              
60             If you set C it's not necessary to call sleep before C.
61              
62             It's also possible to set the path to the proc filesystem.
63              
64             Sys::Statistics::Linux::CpuStats->new(
65             files => {
66             # This is the default
67             path => '/proc'
68             stat => 'stat',
69             }
70             );
71              
72             =head2 init()
73              
74             Call C to initialize the statistics.
75              
76             $lxs->init;
77              
78             =head2 get()
79              
80             Call C to get the statistics. C returns the statistics as a hash reference.
81              
82             my $stats = $lxs->get;
83              
84             =head2 raw()
85              
86             Get raw values.
87              
88             =head1 EXPORTS
89              
90             No exports.
91              
92             =head1 SEE ALSO
93              
94             B
95              
96             =head1 REPORTING BUGS
97              
98             Please report all bugs to .
99              
100             =head1 AUTHOR
101              
102             Jonny Schulz .
103              
104             =head1 COPYRIGHT
105              
106             Copyright (c) 2006, 2007 by Jonny Schulz. All rights reserved.
107              
108             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
109              
110             =cut
111              
112             package Sys::Statistics::Linux::CpuStats;
113              
114 2     2   11 use strict;
  2         4  
  2         82  
115 2     2   11 use warnings;
  2         4  
  2         71  
116 2     2   9 use Carp qw(croak);
  2         3  
  2         2020  
117              
118             our $VERSION = '0.20';
119              
120             sub new {
121 2     2 1 5 my $class = shift;
122 2 50       10 my $opts = ref($_[0]) ? shift : {@_};
123              
124 2         10 my %self = (
125             files => {
126             path => '/proc',
127             stat => 'stat',
128             }
129             );
130              
131 2 50       9 if (defined $opts->{initfile}) {
132 0         0 require YAML::Syck;
133 0         0 $self{initfile} = $opts->{initfile};
134             }
135              
136 2         3 foreach my $file (keys %{ $opts->{files} }) {
  2         11  
137 0         0 $self{files}{$file} = $opts->{files}->{$file};
138             }
139              
140 2         15 return bless \%self, $class;
141             }
142              
143             sub raw {
144 0     0 1 0 my $self = shift;
145 0         0 my $stat = $self->_load;
146 0         0 return $stat;
147             }
148              
149             sub init {
150 2     2 1 4 my $self = shift;
151              
152 2 50 33     19 if ($self->{initfile} && -r $self->{initfile}) {
153 0         0 $self->{init} = YAML::Syck::LoadFile($self->{initfile});
154             } else {
155 2         6 $self->{init} = $self->_load;
156             }
157             }
158              
159             sub get {
160 2     2 1 9 my $self = shift;
161 2         13 my $class = ref $self;
162              
163 2 50       14 if (!exists $self->{init}) {
164 0         0 croak "$class: there are no initial statistics defined";
165             }
166              
167 2         12 $self->{stats} = $self->_load;
168 2         11 $self->_deltas;
169              
170 2 50       15 if ($self->{initfile}) {
171 0         0 YAML::Syck::DumpFile($self->{initfile}, $self->{init});
172             }
173              
174 2         15 return $self->{stats};
175             }
176              
177             #
178             # private stuff
179             #
180              
181             sub _load {
182 4     4   10 my $self = shift;
183 4         9 my $class = ref $self;
184 4         1427 my $file = $self->{files};
185 4         7 my (%stats, $iowait, $irq, $softirq, $steal);
186              
187 4 50       26 my $filename = $file->{path} ? "$file->{path}/$file->{stat}" : $file->{stat};
188 4 50       295 open my $fh, '<', $filename or croak "$class: unable to open $filename ($!)";
189              
190 4         545 while (my $line = <$fh>) {
191 96 100       405 if ($line =~ /^(cpu.*?)\s+(.*)$/) {
192 68         73 my $cpu = \%{$stats{$1}};
  68         231  
193 68         309 (@{$cpu}{qw(user nice system idle)},
  68         423  
194             $iowait, $irq, $softirq, $steal) = split /\s+/, $2;
195             # iowait, irq and softirq are only set
196             # by kernel versions higher than 2.4.
197             # steal is available since 2.6.11.
198 68 50       268 $cpu->{iowait} = $iowait if defined $iowait;
199 68 50       160 $cpu->{irq} = $irq if defined $irq;
200 68 50       181 $cpu->{softirq} = $softirq if defined $softirq;
201 68 50       447 $cpu->{steal} = $steal if defined $steal;
202             }
203             }
204              
205 4         81 close($fh);
206 4         36 return \%stats;
207             }
208              
209             sub _deltas {
210 2     2   7 my $self = shift;
211 2         5 my $class = ref $self;
212 2         7 my $istat = $self->{init};
213 2         6 my $lstat = $self->{stats};
214              
215 2         4 foreach my $cpu (keys %{$lstat}) {
  2         15  
216 34         67 my $icpu = $istat->{$cpu};
217 34         49 my $dcpu = $lstat->{$cpu};
218 34         37 my $uptime;
219              
220 34         47 while (my ($k, $v) = each %{$dcpu}) {
  306         1578  
221 272 50       600 if (!defined $icpu->{$k}) {
222 0         0 croak "$class: not defined key found '$k'";
223             }
224              
225 272 50 33     1722 if ($v !~ /^\d+\z/ || $dcpu->{$k} !~ /^\d+\z/) {
226 0         0 croak "$class: invalid value for key '$k'";
227             }
228              
229 272         652 $dcpu->{$k} -= $icpu->{$k};
230 272         419 $icpu->{$k} = $v;
231 272         560 $uptime += $dcpu->{$k};
232             }
233              
234 34         48 foreach my $k (keys %{$dcpu}) {
  34         147  
235 272 100       649 if ($dcpu->{$k} > 0) {
    50          
236 132         678 $dcpu->{$k} = sprintf('%.2f', 100 * $dcpu->{$k} / $uptime);
237             } elsif ($dcpu->{$k} < 0) {
238 0         0 $dcpu->{$k} = sprintf('%.2f', 0);
239             } else {
240 140         618 $dcpu->{$k} = sprintf('%.2f', $dcpu->{$k});
241             }
242             }
243              
244 34         270 $dcpu->{total} = sprintf('%.2f', 100 - $dcpu->{idle});
245             }
246             }
247              
248             1;