File Coverage

blib/lib/Linux/GetPidstat/Collector/Parser.pm
Criterion Covered Total %
statement 46 46 100.0
branch 11 12 91.6
condition 4 6 66.6
subroutine 11 11 100.0
pod 0 1 0.0
total 72 76 94.7


line stmt bran cond sub pod time code
1             package Linux::GetPidstat::Collector::Parser;
2 23     23   78493 use 5.008001;
  23         89  
3 23     23   104 use strict;
  23         46  
  23         397  
4 23     23   106 use warnings;
  23         108  
  23         849  
5              
6 23     23   116 use Exporter qw(import);
  23         153  
  23         763  
7 23     23   125 use List::Util qw(sum reduce);
  23         34  
  23         13661  
8              
9             our @EXPORT = qw(parse_pidstat_output);
10              
11             sub parse ($) {
12 20     20 0 3602 my $lines = shift;
13              
14 20         94 my $ret;
15              
16 20         158 my $mapping = _get_metric_rule_mapping();
17 20         75 my $pid_rule = delete $mapping->{pid};
18 20         179 while (my ($name, $metric_rule) = each %$mapping) {
19 140         374 my $metric = _get_metric_mean($metric_rule, $pid_rule, $lines);
20 140 100       618 unless (defined $metric) {
21 5         205 warn (sprintf "Empty metric: name=%s, lines=%s\n",
22             $name, join ',', @$lines);
23 5         78 return;
24             }
25              
26             # ex. cpu => 21.0
27 135         657 $ret->{$name} = $metric;
28             }
29              
30 15         239 return $ret;
31             }
32              
33             sub _get_metric_rule_mapping() {
34 745     745   1261 my $convert_from_kilobytes = sub { my $raw = shift; return $raw * 1000 };
  745     20   1919  
  20         366  
35              
36             return {
37 20         657 pid => {
38             column_num => 2,
39             },
40             cpu => {
41             column_num => 6,
42             },
43             memory_percent => {
44             column_num => 12,
45             },
46             memory_rss => {
47             column_num => 11,
48             convert_func => $convert_from_kilobytes,
49             },
50             stk_size => {
51             column_num => 13,
52             convert_func => $convert_from_kilobytes,
53             },
54             stk_ref => {
55             column_num => 14,
56             convert_func => $convert_from_kilobytes,
57             },
58             disk_read_per_sec => {
59             column_num => 15,
60             convert_func => $convert_from_kilobytes,
61             },
62             disk_write_per_sec => {
63             column_num => 16,
64             convert_func => $convert_from_kilobytes,
65             },
66             cswch_per_sec => {
67             column_num => 18,
68             },
69             nvcswch_per_sec => {
70             column_num => 19,
71             },
72             };
73             }
74              
75             sub _get_metric_mean($$) {
76 140     140   282 my ($metric_rule, $pid_rule, $lines) = @_;
77              
78 140         334 my %metrics;
79 140         305 for (@$lines) {
80 2517         9331 my @fields = split " ";
81              
82 2517         4569 my $pid = $fields[$pid_rule->{column_num}];
83 2517 100 100     10486 next unless defined $pid && $pid =~ /^\d+$/;
84              
85 1341         2676 my $metric = $fields[$metric_rule->{column_num}];
86 1341 50 33     5012 next unless defined $metric && $metric =~ /^[-+]?[0-9.]+$/;
87 1341 100       3007 if (my $cf = $metric_rule->{convert_func}) {
88 745         1484 $metric = $cf->($metric);
89             }
90              
91 1341 100       3075 $metrics{$pid} = [] unless exists $metrics{$pid};
92 1341         1982 push @{ $metrics{$pid} }, $metric;
  1341         4818  
93             }
94              
95 140 100       382 return unless %metrics;
96 135     342   1333 return reduce { $a + _mean(@$b) } (0, values %metrics);
  342         880  
97             }
98              
99             sub _mean(@) {
100 342     342   3204 return sprintf '%.2f', sum(@_)/@_;
101             }
102              
103             *parse_pidstat_output = \&parse;
104              
105             1;
106             __END__