statsd histogram to support more than 1 second
[collectd.git] / contrib / collection3 / lib / Collectd / Graph / TypeLoader.pm
1 package Collectd::Graph::TypeLoader;
2
3 =head1 NAME
4
5 Collectd::Graph::TypeLoader - Load a module according to the "type"
6
7 =cut
8
9 # Copyright (C) 2008,2009  Florian octo Forster <octo at verplant.org>
10 #
11 # This program is free software; you can redistribute it and/or modify it under
12 # the terms of the GNU General Public License as published by the Free Software
13 # Foundation; only version 2 of the License is applicable.
14 #
15 # This program is distributed in the hope that it will be useful, but WITHOUT
16 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18 # details.
19 #
20 # You should have received a copy of the GNU General Public License along with
21 # this program; if not, write to the Free Software Foundation, Inc.,
22 # 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23
24 use strict;
25 use warnings;
26
27 use Carp (qw(cluck confess));
28 use Exporter ();
29 use Config::General ('ParseConfig');
30 use Collectd::Graph::Config ('gc_get_config');
31 use Collectd::Graph::Type ();
32
33 @Collectd::Graph::TypeLoader::ISA = ('Exporter');
34 @Collectd::Graph::TypeLoader::EXPORT_OK = ('tl_load_type');
35
36 our @ArrayMembers = (qw(data_sources rrd_opts custom_order));
37 our @ScalarMembers = (qw(rrd_title rrd_format rrd_vertical scale ignore_unknown stacking));
38 our @DSMappedMembers = (qw(ds_names rrd_colors));
39
40 our %MemberToConfigMap =
41 (
42   data_sources => 'datasources',
43   ds_names => 'dsname',
44   rrd_title => 'rrdtitle',
45   rrd_opts => 'rrdoptions',
46   rrd_format => 'rrdformat',
47   rrd_vertical => 'rrdverticallabel',
48   rrd_colors => 'color',
49   scale => 'scale', # GenericIO only
50   custom_order => 'order', # GenericStacked only
51   stacking => 'stacking', # GenericStacked only
52   ignore_unknown => 'ignoreunknown' # GenericStacked only
53 );
54
55 return (1);
56
57 sub _create_object
58 {
59   my $module = shift;
60   my $obj;
61
62   # Surpress warnings and error messages caused by the eval.
63   local $SIG{__WARN__} = sub { return (1); print STDERR "WARNING: " . join (', ', @_) . "\n"; };
64   local $SIG{__DIE__}  = sub { return (1); print STDERR "FATAL: "   . join (', ', @_) . "\n"; };
65
66   eval <<PERL;
67   require $module;
68   \$obj = ${module}->new ();
69 PERL
70   if (!$obj)
71   {
72     return;
73   }
74
75   return ($obj);
76 } # _create_object
77
78 sub _load_module_from_config
79 {
80   my $conf = shift;
81
82   my $module = $conf->{'module'};
83   my $obj;
84   
85   if ($module && !($module =~ m/::/))
86   {
87     $module = "Collectd::Graph::Type::$module";
88   }
89
90   if ($module)
91   {
92     $obj = _create_object ($module);
93     if (!$obj)
94     {
95       #cluck ("Creating an $module object failed");
96       warn ("Creating an $module object failed");
97       return;
98     }
99   }
100   else
101   {
102     $obj = Collectd::Graph::Type->new ();
103     if (!$obj)
104     {
105       cluck ("Creating an Collectd::Graph::Type object failed");
106       return;
107     }
108   }
109
110   for (@ScalarMembers) # {{{
111   {
112     my $member = $_;
113     my $key = $MemberToConfigMap{$member};
114     my $val;
115
116     if (!defined $conf->{$key})
117     {
118       next;
119     }
120     $val = $conf->{$key};
121     
122     if (ref ($val) ne '')
123     {
124       cluck ("Invalid value type for $key: " . ref ($val));
125       next;
126     }
127
128     $obj->{$member} = $val;
129   } # }}}
130
131   for (@ArrayMembers) # {{{
132   {
133     my $member = $_;
134     my $key = $MemberToConfigMap{$member};
135     my $val;
136
137     if (!defined $conf->{$key})
138     {
139       next;
140     }
141     $val = $conf->{$key};
142     
143     if (ref ($val) eq 'ARRAY')
144     {
145       $obj->{$member} = $val;
146     }
147     elsif (ref ($val) eq '')
148     {
149       $obj->{$member} = [split (' ', $val)];
150     }
151     else
152     {
153       cluck ("Invalid value type for $key: " . ref ($val));
154     }
155   } # }}}
156
157   for (@DSMappedMembers) # {{{
158   {
159     my $member = $_;
160     my $key = $MemberToConfigMap{$member};
161     my @val_list;
162
163     if (!defined $conf->{$key})
164     {
165       next;
166     }
167
168     if (ref ($conf->{$key}) eq 'ARRAY')
169     {
170       @val_list = @{$conf->{$key}};
171     }
172     elsif (ref ($conf->{$key}) eq '')
173     {
174       @val_list = ($conf->{$key});
175     }
176     else
177     {
178       cluck ("Invalid value type for $key: " . ref ($conf->{$key}));
179       next;
180     }
181
182     for (@val_list)
183     {
184       my $line = $_;
185       my $ds;
186       my $val;
187
188       if (!defined ($line) || (ref ($line) ne ''))
189       {
190         next;
191       }
192
193       ($ds, $val) = split (' ', $line, 2);
194       if (!$ds || !$val)
195       {
196         next;
197       }
198
199       $obj->{$member} ||= {};
200       $obj->{$member}{$ds} = $val;
201     } # for (@val_list)
202   } # }}} for (@DSMappedMembers)
203
204   return ($obj);
205 } # _load_module_from_config
206
207 sub _load_module_generic
208 {
209   my $type = shift;
210   my $module = ucfirst (lc ($type));
211   my $obj;
212
213   $module =~ s/[^A-Za-z_]//g;
214   $module =~ s/_([A-Za-z])/\U$1\E/g;
215
216   $obj = _create_object ($module);
217   if (!$obj)
218   {
219     $obj = Collectd::Graph::Type->new ();
220     if (!$obj)
221     {
222       cluck ("Creating an Collectd::Graph::Type object failed");
223       return;
224     }
225   }
226
227   return ($obj);
228 } # _load_module_generic
229
230 =head1 EXPORTED FUNCTIONS
231
232 =over 4
233
234 =item B<tl_load_type> (I<$type>)
235
236 Does whatever is necessary to get an object with which to graph RRD files of
237 type I<$type>.
238
239 =cut
240
241 sub tl_load_type
242 {
243   my $type = shift;
244   my $conf = gc_get_config ();
245
246   if (defined ($conf) && defined ($conf->{'type'}{$type}))
247   {
248     return (_load_module_from_config ($conf->{'type'}{$type}));
249   }
250   else
251   {
252     return (_load_module_generic ($type));
253   }
254 } # tl_load_type
255
256 =back
257
258 =head1 SEE ALSO
259
260 L<Collectd::Graph::Type::GenericStacked>
261
262 =head1 AUTHOR AND LICENSE
263
264 Copyright (c) 2008 by Florian Forster
265 E<lt>octoE<nbsp>atE<nbsp>verplant.orgE<gt>. Licensed under the terms of the GNU
266 General Public License, VersionE<nbsp>2 (GPLv2).
267
268 =cut
269
270 # vim: set shiftwidth=2 softtabstop=2 tabstop=8 et fdm=marker :