Merge branch 'master' into sr/pf
[collectd.git] / contrib / collection3 / lib / Collectd / Graph / Type / TableSize.pm
1 package Collectd::Graph::Type::TableSize;
2
3 # Copyright (C) 2008,2009  Florian octo Forster <octo at verplant.org>
4 #
5 # This program is free software; you can redistribute it and/or modify it under
6 # the terms of the GNU General Public License as published by the Free Software
7 # Foundation; only version 2 of the License is applicable.
8 #
9 # This program is distributed in the hope that it will be useful, but WITHOUT
10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
12 # details.
13 #
14 # You should have received a copy of the GNU General Public License along with
15 # this program; if not, write to the Free Software Foundation, Inc.,
16 # 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17
18 use strict;
19 use warnings;
20 use base ('Collectd::Graph::Type');
21
22 use Collectd::Graph::Common (qw($ColorCanvas $ColorFullBlue $ColorHalfBlue
23   ident_to_filename sanitize_type_instance
24   get_random_color sort_idents_by_type_instance));
25
26 use RRDs ();
27
28 return (1);
29
30 sub _get_last_value
31 {
32   my $ident = shift;
33   my $value = undef;
34   my $filename = ident_to_filename ($ident);
35   my ($start ,$step ,$names ,$data) = RRDs::fetch ($filename, 'AVERAGE', '-s', '-3600');
36   if (my $errmsg = RRDs::error ())
37   {
38     print STDERR "RRDs::fetch ($filename) failed: $errmsg\n";
39     return;
40   }
41
42   for (@$data)
43   {
44     my $line = $_;
45
46     for (@$line)
47     {
48       my $ds = $_;
49
50       if (defined ($ds))
51       {
52         $value = $ds;
53       }
54     }
55   } # for (@$data)
56
57   return ($value);
58 } # _get_last_value
59
60 sub getLastValues
61 {
62   my $obj = shift;
63   my $last_value = {};
64
65   if (exists ($obj->{'last_value'}))
66   {
67     return ($obj->{'last_value'});
68   }
69
70   for (@{$obj->{'files'}})
71   {
72     my $file = $_;
73
74     $last_value->{$file} = _get_last_value ($file);
75   }
76   $obj->{'last_value'} = $last_value;
77   return ($obj->{'last_value'});
78 } # getLastValues
79
80 sub _group_files
81 {
82   my $obj = shift;
83   my $data = [];
84   my @files;
85   my $last_values;
86
87   $last_values = $obj->getLastValues ();
88
89   @files = sort
90   { 
91     if (!defined ($last_values->{$a}) && !defined ($last_values->{$b}))
92     {
93       return (0);
94     }
95     elsif (!defined ($last_values->{$a}))
96     {
97       return (1);
98     }
99     elsif (!defined ($last_values->{$b}))
100     {
101       return (-1);
102     }
103     else
104     {
105       return ($last_values->{$a} <=> $last_values->{$b});
106     }
107   } (@{$obj->{'files'}});
108
109   for (my $i = 0; $i < @files; $i++)
110   {
111     my $file = $files[$i];
112     my $j = int ($i / 10);
113
114     $data->[$j] ||= [];
115     push (@{$data->[$j]}, $file);
116   }
117
118   return ($data);
119 } # _group_files
120
121 sub getGraphsNum
122 {
123   my $obj = shift;
124   my $group = _group_files ($obj);
125
126   return (0 + @$group);
127 }
128
129 sub getRRDArgs
130 {
131   my $obj = shift;
132   my $index = shift;
133
134   my $group = _group_files ($obj);
135
136   my $rrd_opts = $obj->{'rrd_opts'} || [];
137   my $format = $obj->{'rrd_format'} || '%5.1lf';
138
139   my $idents = $group->[$index];
140   my $ds_name_len = 0;
141
142   my $ds = $obj->getDataSources ();
143   if (!$ds)
144   {
145     confess ("obj->getDataSources failed.");
146   }
147   if (@$ds != 1)
148   {
149     confess ("I can only work with RRD files that have "
150       . "exactly one data source!");
151   }
152   my $data_source = $ds->[0];
153
154   my $rrd_title = $obj->getTitle ($idents->[0]);
155
156   my $colors = $obj->{'rrd_colors'} || {};
157   my @ret = ('-t', $rrd_title, @$rrd_opts);
158
159   if (defined $obj->{'rrd_vertical'})
160   {
161     push (@ret, '-v', $obj->{'rrd_vertical'});
162   }
163
164   if ($obj->{'custom_order'})
165   {
166     sort_idents_by_type_instance ($idents, $obj->{'custom_order'});
167   }
168
169   $obj->{'ds_names'} ||= {};
170   my @names = map { $obj->{'ds_names'}{$_->{'type_instance'}} || $_->{'type_instance'} } (@$idents);
171
172   for (my $i = 0; $i < @$idents; $i++)
173   {
174     my $ident = $idents->[$i];
175     my $filename = ident_to_filename ($ident);
176
177     if ($ds_name_len < length ($names[$i]))
178     {
179       $ds_name_len = length ($names[$i]);
180     }
181     
182     # Escape colons _after_ the length has been checked.
183     $names[$i] =~ s/:/\\:/g;
184
185     push (@ret,
186       "DEF:min${i}=${filename}:${data_source}:MIN",
187       "DEF:avg${i}=${filename}:${data_source}:AVERAGE",
188       "DEF:max${i}=${filename}:${data_source}:MAX");
189   }
190
191   for (my $i = 0; $i < @$idents; $i++)
192   {
193     my $type_instance = $idents->[$i]{'type_instance'};
194     my $ds_name = sprintf ("%-*s", $ds_name_len, $names[$i]);
195     my $color = '000000';
196     if (exists $colors->{$type_instance})
197     {
198       $color = $colors->{$type_instance};
199     }
200     else
201     {
202       $color = get_random_color ();
203     }
204     push (@ret,
205       "LINE1:avg${i}#${color}:${ds_name}",
206       "GPRINT:min${i}:MIN:${format} Min,",
207       "GPRINT:avg${i}:AVERAGE:${format} Avg,",
208       "GPRINT:max${i}:MAX:${format} Max,",
209       "GPRINT:avg${i}:LAST:${format} Last\\l");
210   }
211
212   return (\@ret);
213 }
214
215 sub getGraphArgs
216 {
217   my $obj = shift;
218   my $index = shift;
219
220   my $group = _group_files ($obj);
221   my $idents = $group->[$index];
222
223   my @args = ();
224   for (qw(hostname plugin plugin_instance type))
225   {
226     if (defined ($idents->[0]{$_}))
227     {
228       push (@args, $_ . '=' . $idents->[0]{$_});
229     }
230   }
231   push (@args, "index=$index");
232
233   return (join (';', @args));
234 } # getGraphArgs
235
236 # vim: set shiftwidth=2 softtabstop=2 tabstop=8 :