1 # collectd - Collectd.pm
2 # Copyright (C) 2007-2009 Sebastian Harl
4 # This program is free software; you can redistribute it and/or modify it
5 # under the terms of the GNU General Public License as published by the
6 # Free Software Foundation; only version 2 of the License is applicable.
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # General Public License for more details.
13 # You should have received a copy of the GNU General Public License along
14 # with this program; if not, write to the Free Software Foundation, Inc.,
15 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 # Sebastian Harl <sh at tokkee.org>
31 if (! $Config{'useithreads'}) {
32 die "Perl does not support ithreads!";
38 our @ISA = qw( Exporter );
44 plugin_dispatch_values
50 plugin_dispatch_notification
80 'filter_chain' => [ qw(
105 push @{$EXPORT_TAGS{'all'}}, grep {! $seen{$_}++ } @{$EXPORT_TAGS{$_}}
106 foreach keys %EXPORT_TAGS;
113 Exporter::export_ok_tags ('all');
115 my @plugins : shared = ();
116 my @fc_plugins : shared = ();
117 my %cf_callbacks : shared = ();
120 TYPE_CONFIG, "config",
124 TYPE_SHUTDOWN, "shutdown",
126 TYPE_NOTIF, "notify",
135 my %fc_exec_names = (
142 FC_CB_CREATE, "create",
143 FC_CB_DESTROY, "destroy"
146 foreach my $type (keys %types) {
147 $plugins[$type] = &share ({});
150 foreach my $type (keys %fc_types) {
151 $fc_plugins[$type] = &share ({});
159 if ("Collectd" eq $caller) {
162 return plugin_log ($lvl, $msg);
165 sub ERROR { _log (scalar caller, LOG_ERR, shift); }
166 sub WARNING { _log (scalar caller, LOG_WARNING, shift); }
167 sub NOTICE { _log (scalar caller, LOG_NOTICE, shift); }
168 sub INFO { _log (scalar caller, LOG_INFO, shift); }
169 sub DEBUG { _log (scalar caller, LOG_DEBUG, shift); }
171 sub plugin_call_all {
176 our $cb_name = undef;
178 if (! defined $type) {
182 if (TYPE_LOG != $type) {
183 DEBUG ("Collectd::plugin_call_all: type = \"$type\" ("
184 . $types{$type} . "), args=\""
185 . join(', ', map { defined($_) ? $_ : '<undef>' } @_) . "\"");
188 if (! defined $plugins[$type]) {
189 ERROR ("Collectd::plugin_call_all: unknown type \"$type\"");
194 lock %{$plugins[$type]};
195 %plugins = %{$plugins[$type]};
198 foreach my $plugin (keys %plugins) {
199 $cb_name = $plugins{$plugin};
200 my $status = call_by_name (@_);
209 $err = "callback returned false";
212 if (TYPE_LOG != $type) {
213 ERROR ("Execution of callback \"$cb_name\" failed: $err");
222 elsif (TYPE_INIT == $type) {
223 ERROR ("${plugin}->init() failed with status $status. "
224 . "Plugin will be disabled.");
226 foreach my $type (keys %types) {
227 plugin_unregister ($type, $plugin);
230 elsif (TYPE_LOG != $type) {
231 WARNING ("${plugin}->$types{$type}() failed with status $status.");
237 # Collectd::plugin_register (type, name, data).
240 # init, read, write, shutdown, data set
246 # reference to the plugin's subroutine that does the work or the data set
248 sub plugin_register {
253 DEBUG ("Collectd::plugin_register: "
254 . "type = \"$type\" (" . $types{$type}
255 . "), name = \"$name\", data = \"$data\"");
257 if (! ((defined $type) && (defined $name) && (defined $data))) {
258 ERROR ("Usage: Collectd::plugin_register (type, name, data)");
262 if ((! defined $plugins[$type]) && (TYPE_DATASET != $type)
263 && (TYPE_CONFIG != $type)) {
264 ERROR ("Collectd::plugin_register: Invalid type \"$type\"");
268 if ((TYPE_DATASET == $type) && ("ARRAY" eq ref $data)) {
269 return plugin_register_data_set ($name, $data);
271 elsif ((TYPE_CONFIG == $type) && (! ref $data)) {
272 my $pkg = scalar caller;
274 if ($data !~ m/^$pkg\:\:/) {
275 $data = $pkg . "::" . $data;
279 $cf_callbacks{$name} = $data;
281 elsif ((TYPE_DATASET != $type) && (! ref $data)) {
282 my $pkg = scalar caller;
283 if ($data !~ m/^$pkg\:\:/) {
284 $data = $pkg . "::" . $data;
286 if (TYPE_READ == $type) {
287 return plugin_register_read($name, $data);
289 if (TYPE_WRITE == $type) {
290 return plugin_register_write($name, $data);
292 if (TYPE_LOG == $type) {
293 return plugin_register_log($name, $data);
295 if (TYPE_NOTIF == $type) {
296 return plugin_register_notification($name, $data);
298 if (TYPE_FLUSH == $type) {
299 return plugin_register_flush($name, $data);
301 lock %{$plugins[$type]};
302 $plugins[$type]->{$name} = $data;
305 ERROR ("Collectd::plugin_register: Invalid data.");
311 sub plugin_unregister {
315 DEBUG ("Collectd::plugin_unregister: type = \"$type\" ("
316 . $types{$type} . "), name = \"$name\"");
318 if (! ((defined $type) && (defined $name))) {
319 ERROR ("Usage: Collectd::plugin_unregister (type, name)");
323 if (TYPE_DATASET == $type) {
324 return plugin_unregister_data_set ($name);
326 elsif (TYPE_CONFIG == $type) {
328 delete $cf_callbacks{$name};
330 elsif (TYPE_READ == $type) {
331 return plugin_unregister_read ($name);
333 elsif (TYPE_WRITE == $type) {
334 return plugin_unregister_write($name);
336 elsif (TYPE_LOG == $type) {
337 return plugin_unregister_log ($name);
339 elsif (TYPE_NOTIF == $type) {
340 return plugin_unregister_notification($name);
342 elsif (TYPE_FLUSH == $type) {
343 return plugin_unregister_flush($name);
345 elsif (defined $plugins[$type]) {
346 lock %{$plugins[$type]};
347 delete $plugins[$type]->{$name};
350 ERROR ("Collectd::plugin_unregister: Invalid type.");
362 if (! defined $args{'valuelists'}) {
363 ERROR ("Collectd::plugin_write: Missing 'valuelists' argument.");
367 DEBUG ("Collectd::plugin_write:"
368 . (defined ($args{'plugins'}) ? " plugins = $args{'plugins'}" : "")
369 . (defined ($args{'datasets'}) ? " datasets = $args{'datasets'}" : "")
370 . " valueslists = $args{'valuelists'}");
372 if (defined ($args{'plugins'})) {
373 if ("ARRAY" eq ref ($args{'plugins'})) {
374 @plugins = @{$args{'plugins'}};
377 @plugins = ($args{'plugins'});
384 if ("ARRAY" eq ref ($args{'valuelists'})) {
385 @valuelists = @{$args{'valuelists'}};
388 @valuelists = ($args{'valuelists'});
391 if (defined ($args{'datasets'})) {
392 if ("ARRAY" eq ref ($args{'datasets'})) {
393 @datasets = @{$args{'datasets'}};
396 @datasets = ($args{'datasets'});
400 @datasets = (undef) x scalar (@valuelists);
403 if ($#datasets != $#valuelists) {
404 ERROR ("Collectd::plugin_write: Invalid number of datasets.");
408 foreach my $plugin (@plugins) {
409 for (my $i = 0; $i < scalar (@valuelists); ++$i) {
410 _plugin_write ($plugin, $datasets[$i], $valuelists[$i]);
422 DEBUG ("Collectd::plugin_flush:"
423 . (defined ($args{'timeout'}) ? " timeout = $args{'timeout'}" : "")
424 . (defined ($args{'plugins'}) ? " plugins = $args{'plugins'}" : "")
425 . (defined ($args{'identifiers'})
426 ? " identifiers = $args{'identifiers'}" : ""));
428 if (defined ($args{'timeout'}) && ($args{'timeout'} > 0)) {
429 $timeout = $args{'timeout'};
432 if (defined ($args{'plugins'})) {
433 if ("ARRAY" eq ref ($args{'plugins'})) {
434 @plugins = @{$args{'plugins'}};
437 @plugins = ($args{'plugins'});
444 if (defined ($args{'identifiers'})) {
445 if ("ARRAY" eq ref ($args{'identifiers'})) {
446 @ids = @{$args{'identifiers'}};
449 @ids = ($args{'identifiers'});
456 foreach my $plugin (@plugins) {
457 foreach my $id (@ids) {
458 _plugin_flush($plugin, $timeout, $id);
470 our $cb_name = undef;
473 if (! ((defined $type) && (defined $name) && (defined $cb_type))) {
474 ERROR ("Usage: Collectd::fc_call(type, name, cb_type, ...)");
478 if (! defined $fc_plugins[$type]) {
479 ERROR ("Collectd::fc_call: Invalid type \"$type\"");
483 if (! defined $fc_plugins[$type]->{$name}) {
484 ERROR ("Collectd::fc_call: Unknown "
485 . ($type == FC_MATCH ? "match" : "target")
490 DEBUG ("Collectd::fc_call: "
491 . "type = \"$type\" (" . $fc_types{$type}
492 . "), name = \"$name\", cb_type = \"$cb_type\" ("
493 . $fc_cb_types{$cb_type} . ")");
496 lock %{$fc_plugins[$type]};
497 %proc = %{$fc_plugins[$type]->{$name}};
500 if (FC_CB_EXEC == $cb_type) {
501 $cb_name = $proc{$fc_exec_names{$type}};
503 elsif (FC_CB_CREATE == $cb_type) {
504 if (defined $proc{'create'}) {
505 $cb_name = $proc{'create'};
511 elsif (FC_CB_DESTROY == $cb_type) {
512 if (defined $proc{'destroy'}) {
513 $cb_name = $proc{'destroy'};
520 $status = call_by_name (@_);
529 $err = "callback returned false";
532 ERROR ("Execution of fc callback \"$cb_name\" failed: $err");
545 DEBUG ("Collectd::fc_register: "
546 . "type = \"$type\" (" . $fc_types{$type}
547 . "), name = \"$name\", proc = \"$proc\"");
549 if (! ((defined $type) && (defined $name) && (defined $proc))) {
550 ERROR ("Usage: Collectd::fc_register(type, name, proc)");
554 if (! defined $fc_plugins[$type]) {
555 ERROR ("Collectd::fc_register: Invalid type \"$type\"");
559 if (("HASH" ne ref ($proc)) || (! defined $proc->{$fc_exec_names{$type}})
560 || ("" ne ref ($proc->{$fc_exec_names{$type}}))) {
561 ERROR ("Collectd::fc_register: Invalid proc.");
565 for my $p (qw( create destroy )) {
566 if ((defined $proc->{$p}) && ("" ne ref ($proc->{$p}))) {
567 ERROR ("Collectd::fc_register: Invalid proc.");
574 foreach my $p (keys %fc) {
575 my $pkg = scalar caller;
577 if ($p !~ m/^(create|destroy|$fc_exec_names{$type})$/) {
581 if ($fc{$p} !~ m/^$pkg\:\:/) {
582 $fc{$p} = $pkg . "::" . $fc{$p};
586 lock %{$fc_plugins[$type]};
587 if (defined $fc_plugins[$type]->{$name}) {
588 WARNING ("Collectd::fc_register: Overwriting previous "
589 . "definition of match \"$name\".");
592 if (! _fc_register ($type, $name)) {
593 ERROR ("Collectd::fc_register: Failed to register \"$name\".");
597 $fc_plugins[$type]->{$name} = \%fc;
601 sub _plugin_dispatch_config {
605 our $cb_name = undef;
607 if (! (defined ($plugin) && defined ($config))) {
611 if (! defined $cf_callbacks{$plugin}) {
612 WARNING ("Found a configuration for the \"$plugin\" plugin, but "
613 . "the plugin isn't loaded or didn't register "
614 . "a configuration callback.");
620 $cb_name = $cf_callbacks{$plugin};
622 call_by_name ($config);
627 # vim: set sw=4 ts=4 tw=78 noexpandtab :