1 package Collectd::Graph::Type::TableSize;
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.
18 use strict;
19 use warnings;
20 use base ('Collectd::Graph::Type');
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));
26 use RRDs ();
28 return (1);
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 }
42 for (@$data)
43 {
44 my $line = $_;
46 for (@$line)
47 {
48 my $ds = $_;
50 if (defined ($ds))
51 {
52 $value = $ds;
53 }
54 }
55 } # for (@$data)
57 return ($value);
58 } # _get_last_value
60 sub getLastValues
61 {
62 my $obj = shift;
63 my $last_value = {};
65 if (exists ($obj->{'last_value'}))
66 {
67 return ($obj->{'last_value'});
68 }
70 for (@{$obj->{'files'}})
71 {
72 my $file = $_;
74 $last_value->{$file} = _get_last_value ($file);
75 }
76 $obj->{'last_value'} = $last_value;
77 return ($obj->{'last_value'});
78 } # getLastValues
80 sub _group_files
81 {
82 my $obj = shift;
83 my $data = [];
84 my @files;
85 my $last_values;
87 $last_values = $obj->getLastValues ();
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'}});
109 for (my $i = 0; $i < @files; $i++)
110 {
111 my $file = $files[$i];
112 my $j = int ($i / 10);
114 $data->[$j] ||= [];
115 push (@{$data->[$j]}, $file);
116 }
118 return ($data);
119 } # _group_files
121 sub getGraphsNum
122 {
123 my $obj = shift;
124 my $group = _group_files ($obj);
126 return (0 + @$group);
127 }
129 sub getRRDArgs
130 {
131 my $obj = shift;
132 my $index = shift;
134 my $group = _group_files ($obj);
136 my $rrd_opts = $obj->{'rrd_opts'} || [];
137 my $format = $obj->{'rrd_format'} || '%5.1lf';
139 my $idents = $group->[$index];
140 my $ds_name_len = 0;
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];
154 my $rrd_title = $obj->getTitle ($idents->[0]);
156 my $colors = $obj->{'rrd_colors'} || {};
157 my @ret = ('-t', $rrd_title, @$rrd_opts);
159 if (defined $obj->{'rrd_vertical'})
160 {
161 push (@ret, '-v', $obj->{'rrd_vertical'});
162 }
164 if ($obj->{'custom_order'})
165 {
166 sort_idents_by_type_instance ($idents, $obj->{'custom_order'});
167 }
169 $obj->{'ds_names'} ||= {};
170 my @names = map { $obj->{'ds_names'}{$_->{'type_instance'}} || $_->{'type_instance'} } (@$idents);
172 for (my $i = 0; $i < @$idents; $i++)
173 {
174 my $ident = $idents->[$i];
175 my $filename = ident_to_filename ($ident);
177 if ($ds_name_len < length ($names[$i]))
178 {
179 $ds_name_len = length ($names[$i]);
180 }
182 # Escape colons _after_ the length has been checked.
183 $names[$i] =~ s/:/\\:/g;
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 }
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 }
212 return (\@ret);
213 }
215 sub getGraphArgs
216 {
217 my $obj = shift;
218 my $index = shift;
220 my $group = _group_files ($obj);
221 my $idents = $group->[$index];
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");
233 return (join (';', @args));
234 } # getGraphArgs
236 # vim: set shiftwidth=2 softtabstop=2 tabstop=8 :