contrib/collection3: Option to turn stacking off in GenericStacking
[collectd.git] / contrib / collection3 / lib / Collectd / Graph / Type / GenericStacked.pm
1 package Collectd::Graph::Type::GenericStacked;
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   group_files_by_plugin_instance ident_to_filename sanitize_type_instance
24   get_faded_color sort_idents_by_type_instance));
25
26 return (1);
27
28 sub getGraphsNum
29 {
30   my $obj = shift;
31   my $group = group_files_by_plugin_instance (@{$obj->{'files'}});
32
33   return (scalar (keys %$group));
34 }
35
36 sub getRRDArgs
37 {
38   my $obj = shift;
39   my $index = shift;
40
41   my $group = group_files_by_plugin_instance (@{$obj->{'files'}});
42   my @group = sort (keys %$group);
43
44   my $rrd_opts = $obj->{'rrd_opts'} || [];
45   my $format = $obj->{'rrd_format'} || '%5.1lf';
46
47   my $idents = $group->{$group[$index]};
48   my $ds_name_len = 0;
49
50   my $ds = $obj->getDataSources ();
51   if (!$ds)
52   {
53     confess ("obj->getDataSources failed.");
54   }
55   if (@$ds != 1)
56   {
57     confess ("I can only work with RRD files that have "
58       . "exactly one data source!");
59   }
60   my $data_source = $ds->[0];
61
62   my $rrd_title = $obj->getTitle ($idents->[0]);
63
64   my $colors = $obj->{'rrd_colors'} || {};
65   my @ret = ('-t', $rrd_title, @$rrd_opts);
66
67   my $ignore_unknown = $obj->{'ignore_unknown'} || 0;
68   if ($ignore_unknown)
69   {
70     if ($ignore_unknown =~ m/^(yes|true|on)$/i)
71     {
72       $ignore_unknown = 1;
73     }
74     else
75     {
76       $ignore_unknown = 0;
77     }
78   }
79
80   my $stacking = $obj->{'stacking'};
81   if ($stacking)
82   {
83     if ($stacking =~ m/^(no|false|off|none)$/i)
84     {
85       $stacking = 0;
86     }
87     else
88     {
89       $stacking = 1;
90     }
91   }
92
93   if (defined $obj->{'rrd_vertical'})
94   {
95     push (@ret, '-v', $obj->{'rrd_vertical'});
96   }
97
98   if ($obj->{'custom_order'})
99   {
100     sort_idents_by_type_instance ($idents, $obj->{'custom_order'});
101   }
102
103   if ($ignore_unknown)
104   {
105     my $new_idents = [];
106     for (@$idents)
107     {
108       if (exists ($obj->{'ds_names'}{$_->{'type_instance'}}))
109       {
110         push (@$new_idents, $_);
111       }
112     }
113
114     if (@$new_idents)
115     {
116       $idents = $new_idents;
117     }
118   }
119
120   $obj->{'ds_names'} ||= {};
121   my @names = map { $obj->{'ds_names'}{$_->{'type_instance'}} || $_->{'type_instance'} } (@$idents);
122
123   for (my $i = 0; $i < @$idents; $i++)
124   {
125     my $ident = $idents->[$i];
126     my $filename = ident_to_filename ($ident);
127
128     if ($ds_name_len < length ($names[$i]))
129     {
130       $ds_name_len = length ($names[$i]);
131     }
132
133     # Escape colons _after_ the length has been checked.
134     $names[$i] =~ s/:/\\:/g;
135
136     push (@ret,
137       "DEF:min${i}=${filename}:${data_source}:MIN",
138       "DEF:avg${i}=${filename}:${data_source}:AVERAGE",
139       "DEF:max${i}=${filename}:${data_source}:MAX");
140   }
141
142   if ($stacking) {
143     for (my $i = @$idents - 1; $i >= 0; $i--)
144     {
145       if ($i == (@$idents - 1))
146       {
147         push (@ret,
148           "CDEF:cdef${i}=avg${i},UN,0,avg${i},IF");
149       }
150       else
151       {
152         my $j = $i + 1;
153         push (@ret,
154           "CDEF:cdef${i}=avg${i},UN,0,avg${i},IF,cdef${j},+");
155       }
156     }
157
158     for (my $i = 0; $i < @$idents; $i++)
159     {
160       my $type_instance = $idents->[$i]{'type_instance'};
161       my $color = '000000';
162       if (exists $colors->{$type_instance})
163       {
164         $color = $colors->{$type_instance};
165       }
166
167       $color = get_faded_color ($color);
168
169       push (@ret,
170         "AREA:cdef${i}#${color}");
171     }
172   }
173   else
174   {
175     for (my $i = @$idents - 1; $i >= 0; $i--)
176     {
177       push (@ret,
178         "CDEF:cdef${i}=avg${i}");
179     }
180   }
181
182
183   for (my $i = 0; $i < @$idents; $i++)
184   {
185     my $type_instance = $idents->[$i]{'type_instance'};
186     my $ds_name = sprintf ("%-*s", $ds_name_len, $names[$i]);
187     my $color = '000000';
188     if (exists $colors->{$type_instance})
189     {
190       $color = $colors->{$type_instance};
191     }
192     push (@ret,
193       "LINE1:cdef${i}#${color}:${ds_name}",
194       "GPRINT:min${i}:MIN:${format} Min,",
195       "GPRINT:avg${i}:AVERAGE:${format} Avg,",
196       "GPRINT:max${i}:MAX:${format} Max,",
197       "GPRINT:avg${i}:LAST:${format} Last\\l");
198   }
199
200   return (\@ret);
201 }
202
203 sub getGraphArgs
204 {
205   my $obj = shift;
206   my $index = shift;
207
208   my $group = group_files_by_plugin_instance (@{$obj->{'files'}});
209   my @group = sort (keys %$group);
210
211   my $idents = $group->{$group[$index]};
212
213   my @args = ();
214   for (qw(hostname plugin plugin_instance type))
215   {
216     if (defined ($idents->[0]{$_}))
217     {
218       push (@args, $_ . '=' . $idents->[0]{$_});
219     }
220   }
221
222   return (join (';', @args));
223 } # getGraphArgs
224
225
226 # vim: set shiftwidth=2 softtabstop=2 tabstop=8 :