File Coverage

blib/lib/Sys/Statistics/Linux/Compilation.pm
Criterion Covered Total %
statement 94 125 75.2
branch 35 74 47.3
condition 2 9 22.2
subroutine 15 15 100.0
pod 4 4 100.0
total 150 227 66.0


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Sys::Statistics::Linux::Compilation - Statistics compilation.
4              
5             =head1 SYNOPSIS
6              
7             use Sys::Statistics::Linux;
8              
9             my $lxs = Sys::Statistics::Linux->new( loadavg => 1 );
10             my $stat = $lxs->get;
11              
12             foreach my $key ($stat->loadavg) {
13             print $key, " ", $stat->loadavg($key), "\n";
14             }
15              
16             # or
17              
18             use Sys::Statistics::Linux::LoadAVG;
19             use Sys::Statistics::Linux::Compilation;
20              
21             my $lxs = Sys::Statistics::Linux::LoadAVG->new();
22             my $load = $lxs->get;
23             my $stat = Sys::Statistics::Linux::Compilation->new({ loadavg => $load });
24              
25             foreach my $key ($stat->loadavg) {
26             print $key, " ", $stat->loadavg($key), "\n";
27             }
28              
29             # or
30              
31             foreach my $key ($stat->loadavg) {
32             print $key, " ", $stat->loadavg->{$key}, "\n";
33             }
34              
35             =head1 DESCRIPTION
36              
37             This module provides different methods to access and filter the statistics compilation.
38              
39             =head1 METHODS
40              
41             =head2 new()
42              
43             Create a new C object. This creator is only useful if you
44             don't call C of C. You can create a new object with:
45              
46             my $lxs = Sys::Statistics::Linux::LoadAVG->new();
47             my $load = $lxs->get;
48             my $stat = Sys::Statistics::Linux::Compilation->new({ loadavg => $load });
49              
50             =head2 Statistic methods
51              
52             =over 4
53              
54             =item sysinfo()
55              
56             =item cpustats()
57              
58             =item procstats()
59              
60             =item memstats()
61              
62             =item pgswstats()
63              
64             =item netstats()
65              
66             =item netinfo()
67              
68             C provides raw data - no deltas.
69              
70             =item sockstats()
71              
72             =item diskstats()
73              
74             =item diskusage()
75              
76             =item loadavg()
77              
78             =item filestats()
79              
80             =item processes()
81              
82             =back
83              
84             All methods returns the statistics as a hash reference in scalar context. In list all methods
85             returns the first level keys of the statistics. Example:
86              
87             my $net = $stat->netstats; # netstats as a hash reference
88             my @dev = $stat->netstats; # the devices eth0, eth1, ...
89             my $eth0 = $stat->netstats('eth0'); # eth0 statistics as a hash reference
90             my @keys = $stat->netstats('eth0'); # the statistic keys
91             my @vals = $stat->netstats('eth0', @keys); # the values for the passed device and @keys
92             my $val = $stat->netstats('eth0', $key); # the value for the passed device and key
93              
94             Sorted ...
95              
96             my @dev = sort $stat->netstats;
97             my @keys = sort $stat->netstats('eth0');
98              
99             =head2 pstop()
100              
101             This method is looking for top processes and returns a sorted list of PIDs as an array or
102             array reference depending on the context. It expected two values: a key name and the number
103             of top processes to return.
104              
105             As example you want to get the top 5 processes with the highest cpu usage:
106              
107             my @top5 = $stat->pstop( ttime => 5 );
108             # or as a reference
109             my $top5 = $stat->pstop( ttime => 5 );
110              
111             If you want to get all processes:
112              
113             my @top_all = $stat->pstop( ttime => $FALSE );
114             # or just
115             my @top_all = $stat->pstop( 'ttime' );
116              
117             =head2 search(), psfind()
118              
119             Both methods provides a simple scan engine to find special statistics. Both methods except a filter
120             as a hash reference. It's possible to pass the statistics as second argument if the data is not stored
121             in the object.
122              
123             The method C scans for statistics and rebuilds the hash tree until that keys that matched
124             your filter and returns the hits as a hash reference.
125              
126             my $hits = $stat->search({
127             processes => {
128             cmd => qr/\[su\]/,
129             owner => qr/root/
130             },
131             cpustats => {
132             idle => 'lt:10',
133             iowait => 'gt:10'
134             },
135             diskusage => {
136             '/dev/sda1' => {
137             usageper => 'gt:80'
138             }
139             }
140             });
141              
142             This would return the following matches:
143              
144             * processes with the command "[su]"
145             * processes with the owner "root"
146             * all cpu where "idle" is less than 50
147             * all cpu where "iowait" is grather than 10
148             * only disk '/dev/sda1' if "usageper" is grather than 80
149              
150             The method C scans for processes only and returns a array reference with all process
151             IDs that matched the filter. Example:
152              
153             my $pids = $stat->psfind({ cmd => qr/init/, owner => 'eq:apache' });
154              
155             This would return the following process ids:
156              
157             * processes that matched the command "init"
158             * processes with the owner "apache"
159              
160             There are different match operators available:
161              
162             gt - grather than
163             lt - less than
164             eq - is equal
165             ne - is not equal
166              
167             Notation examples:
168              
169             gt:50
170             lt:50
171             eq:50
172             ne:50
173              
174             Both argumnents have to be set as a hash reference.
175              
176             Note: the operators < > = ! are not available any more. It's possible that in further releases
177             could be different changes for C and C. So please take a look to the
178             documentation if you use it.
179              
180             =head1 EXPORTS
181              
182             No exports.
183              
184             =head1 TODOS
185              
186             * Are there any wishs from your side? Send me a mail!
187              
188             =head1 REPORTING BUGS
189              
190             Please report all bugs to .
191              
192             =head1 AUTHOR
193              
194             Jonny Schulz .
195              
196             Thanks to Moritz Lenz for his suggestion for the name of this module.
197              
198             =head1 COPYRIGHT
199              
200             Copyright (c) 2006, 2007 by Jonny Schulz. All rights reserved.
201              
202             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
203              
204             =cut
205              
206             package Sys::Statistics::Linux::Compilation;
207              
208 15     15   95 use strict;
  15         33  
  15         696  
209 15     15   94 use warnings;
  15         27  
  15         534  
210 15     15   82 use Carp qw(croak);
  15         30  
  15         1396  
211              
212             our $VERSION = '0.10';
213              
214             # Creating the statistics accessors
215             BEGIN {
216 15     15   44 foreach my $stat (qw/sysinfo procstats memstats sockstats loadavg filestats/) {
217 15     15   87 no strict 'refs';
  15         30  
  15         6717  
218 90         460 *{$stat} = sub {
219 15     15   88 use strict 'refs';
  15         25  
  15         2134  
220 46     46   20216 my ($self, @keys) = @_;
221 46 50       168 return () unless $self->{$stat};
222 46 50       114 if (@keys) {
223 0         0 return @{$self->{$stat}}{@keys};
  0         0  
224             }
225 46 50       358 return wantarray ? keys %{$self->{$stat}} : $self->{$stat};
  0         0  
226 90         425 };
227             }
228 15         38 foreach my $stat (qw/cpustats pgswstats netstats netinfo diskstats diskusage processes/) {
229 15     15   79 no strict 'refs';
  15         27  
  15         980  
230 105         21470 *{$stat} = sub {
231 15     15   81 use strict 'refs';
  15         32  
  15         6320  
232 103     103   52323 my ($self, $sub, @keys) = @_;
233 103 50       390 return () unless $self->{$stat};
234 103 50       246 if ($sub) {
235 0         0 my $ref = $self->{$stat};
236 0 0       0 return () unless exists $ref->{$sub};
237 0 0       0 if (@keys) {
238 0         0 return @{$ref->{$sub}}{@keys};
  0         0  
239             } else {
240 0 0       0 return wantarray ? keys %{$ref->{$sub}} : $ref->{$sub};
  0         0  
241             }
242             }
243 103 50       888 return wantarray ? keys %{$self->{$stat}} : $self->{$stat};
  0         0  
244 105         549 };
245             }
246             }
247              
248             sub new {
249 16     16 1 695 my ($class, $stats) = @_;
250 16 50       159 unless (ref($stats) eq 'HASH') {
251 0         0 croak 'Usage: $class->new( \%statistics )';
252             }
253 16         151 return bless $stats, $class;
254             }
255              
256             sub search {
257 2     2 1 49 my $self = shift;
258 2 50       13 my $filter = ref($_[0]) eq 'HASH' ? shift : {@_};
259 2         4 my $class = ref($self);
260 2         8 my %hits = ();
261              
262 2         10 foreach my $opt (keys %{$filter}) {
  2         13  
263              
264 5 50       15 unless (ref($filter->{$opt}) eq 'HASH') {
265 0         0 croak "$class: not a hash ref opt '$opt'";
266             }
267              
268             # next if the object isn't loaded
269 5 50       24 next unless exists $self->{$opt};
270 5         11 my $fref = $filter->{$opt};
271 5         15 my $proc = $self->{$opt};
272 5         5 my $subref;
273              
274             # we search for matches for each key that is defined
275             # in %filter and rebuild the tree until that key that
276             # matched the searched string
277              
278 5         9 foreach my $x (keys %{$fref}) {
  5         25  
279 10 50       29 if (ref($fref->{$x}) eq 'HASH') {
280             # if the key $proc->{eth0} doesn't exists
281             # then we continue with the next defined filter
282 0 0       0 next unless exists $proc->{$x};
283 0         0 $subref = $proc->{$x};
284              
285 0         0 while ( my ($name, $value) = each %{$fref->{$x}} ) {
  0         0  
286 0 0 0     0 if (exists $subref->{$name} && $self->_compare($subref->{$name}, $value)) {
287 0         0 $hits{$opt}{$x}{$name} = $subref->{$name};
288             }
289             }
290             } else {
291 10         10 foreach my $key (keys %{$proc}) {
  10         67  
292 31 100       71 if (ref($proc->{$key}) eq 'HASH') {
293 29         38 $subref = $proc->{$key};
294 29 50 33     200 if (ref $subref->{$x} eq 'HASH') {
    50          
295 0         0 foreach my $y (keys %{$subref->{$x}}) {
  0         0  
296 0 0       0 if ($self->_compare($subref->{$x}->{$y}, $fref->{$x})) {
297 0         0 $hits{$opt}{$key}{$x}{$y} = $subref->{$x}->{$y};
298             }
299             }
300             } elsif (defined $subref->{$x} && $self->_compare($subref->{$x}, $fref->{$x})) {
301 29         260 $hits{$opt}{$key}{$x} = $subref->{$x};
302             }
303             } else { # must be a scalar now
304 2 50 33     23 if (defined $proc->{$x} && $self->_compare($proc->{$x}, $fref->{$x})) {
305 2         14 $hits{$opt}{$x} = $proc->{$x}
306             }
307 2         12 last;
308             }
309             }
310             }
311             }
312             }
313              
314 2 50       20 return wantarray ? %hits : \%hits;
315             }
316              
317             sub psfind {
318 1     1 1 754 my $self = shift;
319 1 50       6 my $filter = ref($_[0]) eq 'HASH' ? shift : {@_};
320 1 50       6 my $proc = $self->{processes} or return undef;
321 1         2 my @hits = ();
322              
323 1         2 PID: foreach my $pid (keys %{$proc}) {
  1         5  
324 8         12 my $proc = $proc->{$pid};
325 8         8 while ( my ($key, $value) = each %{$filter} ) {
  8         29  
326 4 50       10 if (exists $proc->{$key}) {
327 4 50       37 if (ref $proc->{$key} eq 'HASH') {
    50          
328 0         0 foreach my $v (values %{$proc->{$key}}) {
  0         0  
329 0 0       0 if ($self->_compare($v, $value)) {
330 0         0 push @hits, $pid;
331 0         0 next PID;
332             }
333             }
334             } elsif ($self->_compare($proc->{$key}, $value)) {
335 4         7 push @hits, $pid;
336 4         9 next PID;
337             }
338             }
339             }
340             }
341              
342 1 50       6 return wantarray ? @hits : \@hits;
343             }
344              
345             sub pstop {
346 1     1 1 709 my ($self, $key, $count) = @_;
347 1 50       5 unless ($key) {
348 0         0 croak 'Usage: pstop( $key => $count )';
349             }
350 1         3 my $proc = $self->{processes};
351 8         14 my @top = (
352 13         24 map { $_->[0] }
353 8         30 reverse sort { $a->[1] <=> $b->[1] }
354 1         3 map { [ $_, $proc->{$_}->{$key} ] } keys %{$proc}
  1         5  
355             );
356 1 50       8 if ($count) {
357 1         7 @top = @top[0..--$count];
358             }
359 1 50       7 return wantarray ? @top : \@top;
360             }
361              
362             #
363             # private stuff
364             #
365              
366             sub _compare {
367 35     35   60 my ($self, $x, $y) = @_;
368              
369 35 100       473 if (ref($y) eq 'Regexp') {
    100          
    100          
    100          
    50          
370 11         93 return $x =~ $y;
371             } elsif ($y =~ s/^eq://) {
372 1         7 return $x eq $y;
373             } elsif ($y =~ s/^ne://) {
374 2         31 return $x ne $y;
375             } elsif ($y =~ s/^gt://) {
376 3         17 return $x > $y;
377             } elsif ($y =~ s/^lt://) {
378 18         84 return $x < $y;
379             } else {
380 0           croak ref($self).": bad search() / psfind() operator '$y'";
381             }
382              
383 0           return undef;
384             }
385              
386             1;