File Coverage

blib/lib/MonitisMonitorManager.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package MonitisMonitorManager;
2              
3 1     1   44876 use 5.008008;
  1         3  
  1         68  
4             require XML::Simple;
5             require Monitis;
6             require Thread;
7             require URI;
8 1     1   730 use Thread qw(async);
  0            
  0            
9              
10             use strict;
11             no strict "refs";
12             use warnings;
13             use threads::shared;
14             use URI::Escape;
15             use MonitisMonitorManager::MonitisConnection;
16             use MonitisMonitorManager::M3Logger;
17             use Carp;
18             use Date::Manip;
19             use File::Basename;
20             use JSON;
21             use Data::Dumper;
22              
23             #################
24             ### CONSTANTS ###
25             #################
26              
27             require Exporter;
28              
29             our @ISA = qw(Exporter);
30              
31             # Items to export into callers namespace by default. Note: do not export
32             # names by default without a very good reason. Use EXPORT_OK instead.
33             # Do not simply export all your public functions/methods/constants.
34              
35             # This allows declaration use MonitisMonitorManager ':all';
36             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
37             # will save memory.
38             our %EXPORT_TAGS = ( 'all' => [ qw(
39            
40             ) ] );
41              
42             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
43              
44             our @EXPORT = qw(
45            
46             );
47              
48             our $VERSION = '3.12';
49              
50             # use the same constant as in the Perl-SDK
51             use constant DEBUG => $ENV{MONITIS_DEBUG} || 0;
52              
53             # constants for HTTP statistics
54             use constant {
55             EXECUTION_PLUGIN_DIR => "Execution",
56             PARSING_PLUGIN_DIR => "Parsing",
57             COMPUTE_PLUGIN_DIR => "Compute",
58             };
59              
60             our %monitis_datatypes = ( 'boolean', 1, 'integer', 2, 'string', 3, 'float', 4 );
61              
62             # a helper variable to signal threads to quit on time
63             my $condition_loop_stop :shared = 0;
64              
65             #####################
66             ### CTOR AND DTOR ###
67             #####################
68              
69             # constructor
70             sub new {
71             my $class = shift;
72             my $self = {@_};
73             bless $self, $class;
74              
75             # initialize a static variable
76             $self->{monitis_datatypes} = \%monitis_datatypes;
77              
78             # initialize M3Logger
79             $self->{m3logger} = MonitisMonitorManager::M3Logger->instance();
80             $self->{m3logger}->set_syslog_logging($self->is("syslog"));
81             $self->{m3logger}->log_message ("debug", "M3 starting");
82              
83             # open the given XML file
84             open (FILE, $self->{configuration_xml} || croak "Failed to open configuration XML: $!");
85             my $templated_xml = "";
86             while () { $templated_xml .= $_; }
87              
88             # run the macros which would change all the %SOMETHING% to a proper value
89             run_macros($templated_xml);
90              
91             # load execution plugins
92             $self->load_plugins_in_directory(
93             plugin_table_name => "execution_plugins",
94             plugin_directory => EXECUTION_PLUGIN_DIR);
95              
96             # load parsing plugins
97             $self->load_plugins_in_directory(
98             plugin_table_name => "parsing_plugins",
99             plugin_directory => PARSING_PLUGIN_DIR);
100              
101             # load compute plugins
102             $self->load_plugins_in_directory(
103             plugin_table_name => "compute_plugins",
104             plugin_directory => COMPUTE_PLUGIN_DIR);
105              
106             my $xml_parser = XML::Simple->new(ForceArray => 1);
107             $self->{config_xml} = $xml_parser->XMLin($templated_xml);
108              
109             # a shortcut to the agents structure
110             $self->{agents} = $self->{config_xml}->{agent};
111              
112             # initialize MonitisConnection - async class for Monitis interaction
113             $self->{monitis_connection} = MonitisMonitorManager::MonitisConnection->new(
114             apikey => "$self->{config_xml}->{apicredentials}[0]->{apikey}",
115             secretkey => "$self->{config_xml}->{apicredentials}[0]->{secretkey}",
116             );
117              
118             # automatically add monitors
119             $self->add_agents();
120              
121             return $self;
122             }
123              
124             # destructor
125             sub DESTROY {
126             my $self = shift;
127              
128             # call parent dtor (not that there is any, but just to make it clean)
129             $self->SUPER::DESTROY if $self->can("SUPER::DESTROY");
130             # umn, why would destroy be called multiple times?
131             # because we pass $self to every running thread, so shallow copying
132             # will occur. only the main thread will have MonitisConnection defined
133             # though
134             defined($self->{monitis_connection}) and $self->{monitis_connection}->stop();
135             }
136              
137             ##########################
138             ### CORE FUNCTIONALITY ###
139             ##########################
140              
141             # add a single monitor
142             sub add_monitor {
143             my $self = shift;
144             my ($args) = {@_};
145             my $agent_name = $args->{agent_name};
146             my $monitor_name = $args->{monitor_name};
147              
148             my $monitor_xml_path = $self->{agents}->{$agent_name}->{monitor}->{$monitor_name};
149              
150             # get the monitor tag
151             my $monitor_tag = $self->get_monitor_tag(
152             agent_name => $agent_name,
153             monitor_name => $monitor_name);
154             my $result_params = "";
155             my $additional_result_params = "";
156             foreach my $metric_name (keys %{$monitor_xml_path->{metric}}) {
157             if ($self->metric_name_not_reserved($metric_name)) {
158             my $uom = $monitor_xml_path->{metric}->{$metric_name}->{uom}[0];
159             my $metric_type = $monitor_xml_path->{metric}->{$metric_name}->{type}[0];
160             my $data_type = ${ $self->{monitis_datatypes} }{$metric_type} or croak "Incorrect data type '$metric_type'";
161             if (defined($monitor_xml_path->{metric}->{$metric_name}->{additional})) {
162             # it's an additional parameter
163             $additional_result_params .= "$metric_name:$metric_name:$uom:$data_type;";
164             } else {
165             $result_params .= "$metric_name:$metric_name:$uom:$data_type;";
166             }
167             }
168             }
169              
170             # monitor type (can also be undef)
171             my $monitor_type = $self->{agents}->{$agent_name}->{monitor}->{$monitor_name}->{type};
172              
173             # we'll let external execution plugins dictate if they want to expose
174             # additional counters (HTTP statistics for instance)
175             # find the relevant execution plugin and execute its additional counters
176             # function
177             foreach my $execution_plugin (keys %{$self->{execution_plugins}} ) {
178             if (defined($monitor_xml_path->{$execution_plugin}[0])) {
179             foreach my $execution_xml_base (@{$monitor_xml_path->{$execution_plugin}}) {
180             # it's called a URI since it can be anything, from a command line
181             # executable, URL, SQL command...
182             $self->{m3logger}->log_message ("debug", "Calling extra_counters_cb for plugin: '$execution_plugin', monitor_name->'$monitor_name'");
183             # executable, URL, SQL command...
184             $result_params .= $self->{execution_plugins}{$execution_plugin}->extra_counters_cb($self->{monitis_datatypes}, $execution_xml_base);
185             }
186             }
187             }
188              
189             # remove redundant last ';'
190             $result_params =~ s/;$//;
191              
192             # a simple sanity check
193             if ($result_params eq "") {
194             $self->{m3logger}->log_message ("info", "ResultParams are empty for monitor '$monitor_name'... Skipping!");
195             return;
196             }
197              
198             $self->{m3logger}->log_message ("debug", "Adding monitor '$monitor_name' with metrics '$result_params'");
199              
200             # call Monitis using the api context provided
201             if ($self->is("dry_run")) {
202             # don't output this line if just testing configuration
203             not $self->is("test_config") and $self->{m3logger}->log_message ("info", "This is a dry run, the monitor '$monitor_name' was not really added.");
204             } else {
205             my @add_monitor_optional_params;
206             defined($monitor_type) && push @add_monitor_optional_params, type => $monitor_type;
207             if($additional_result_params ne "") { push @add_monitor_optional_params, additionalResultParams => $additional_result_params; }
208             $self->add_monitor_raw(
209             monitor_name => $monitor_name,
210             monitor_tag => $monitor_tag,
211             result_params => $result_params,
212             optional_params => \@add_monitor_optional_params);
213             }
214             }
215              
216             # add all monitors for all agents
217             sub add_agents {
218             my $self = shift;
219              
220             # iterate on agents and add them one by one
221             foreach my $agent_name (keys %{$self->{agents}}) {
222             $self->{m3logger}->log_message ("debug", "Adding agent '$agent_name'");
223             $self->add_agent_monitors(agent_name => $agent_name);
224             }
225             }
226              
227             # add one agent
228             sub add_agent_monitors {
229             my $self = shift;
230             my ($args) = {@_};
231             my $agent_name = $args->{agent_name};
232            
233             # iterate on all monitors and add them
234             foreach my $monitor_name (keys %{$self->{agents}->{$agent_name}->{monitor}} ) {
235             $self->{m3logger}->log_message ("debug", "Adding monitor '$monitor_name' for agent '$agent_name'");
236             $self->add_monitor(
237             agent_name => $agent_name,
238             monitor_name => $monitor_name);
239             }
240             }
241              
242             # invoke a single monitor
243             sub invoke_monitor {
244             my $self = shift;
245             my ($args) = {@_};
246             my $agent_name = $args->{agent_name};
247             my $monitor_name = $args->{monitor_name};
248              
249             # get the xml path for that monitor
250             my $monitor_xml_path = $self->{agents}->{$agent_name}->{monitor}->{$monitor_name};
251              
252             my $output = "";
253             my $execution_called = undef;
254              
255             # result set hash
256             my %results = ();
257             my %additional_results = ();
258              
259             # if just testing monitors - print a nice message
260             ($self->is("test_config")) and $self->{m3logger}->log_message ("info", "Testing monitor '$monitor_name': ");
261             my $config_ok = 1;
262              
263             # find the relevant execution plugin and execute it
264             # TODO execution might be out of order in some cases
265             foreach my $execution_plugin (keys %{$self->{execution_plugins}} ) {
266             if (defined($monitor_xml_path->{$execution_plugin}[0])) {
267             foreach my $execution_xml_base (@{$monitor_xml_path->{$execution_plugin}}) {
268             # it's called a URI since it can be anything, from a command line
269             # executable, URL, SQL command...
270             $self->{m3logger}->log_message ("debug", "Calling execution plugin: '$execution_plugin', execution_xml_base->'$execution_xml_base', monitor_name->'$monitor_name'");
271             my %returned_results = ();
272             if ($self->is("test_config")) {
273             my %tmp_hash = ();
274             eval {
275             $self->{execution_plugins}{$execution_plugin}->get_config($execution_xml_base, \%tmp_hash);
276             };
277             if ($@) {
278             $self->{m3logger}->log_message ("err", "Configuration error: $@");
279             $config_ok = 0;
280             }
281             } else {
282             $output .= $self->{execution_plugins}{$execution_plugin}->execute($execution_xml_base, \%returned_results, $monitor_name);
283             $output .= "\n";
284              
285             # merge the returned results into the main %results hash
286             @results{keys %returned_results} = values %returned_results;
287              
288             # we will not break execution as we might execute a few plugins
289             $execution_called = 1;
290             }
291             }
292             }
293             }
294              
295             # just testing configuration? - alright, quit!
296             if ($self->is("test_config")) {
297             ($config_ok == 1) and $self->{m3logger}->log_message ("info", "Monitor '$monitor_name' -> Configuration is OK");
298             return;
299             }
300              
301             # did we call anything at all??
302             if (!defined($execution_called)) {
303             croak "Could not find proper execution plugin for monitor '$monitor_name'";
304             }
305              
306             my $retval = 1;
307             # if mass load is set, we'll handle the lines one by one
308             if ($self->is("mass_load")) {
309             foreach my $line (split /[\r\n]+/, $output) {
310             $retval = $self->handle_output_chunk(
311             agent_name => $agent_name,
312             monitor_xml_path => $monitor_xml_path,
313             monitor_name => $monitor_name,
314             ref_results => \%results,
315             ref_additional_results => \%additional_results,
316             output => $line);
317             }
318             } else {
319             $retval = $self->handle_output_chunk(
320             agent_name => $agent_name,
321             monitor_xml_path => $monitor_xml_path,
322             monitor_name => $monitor_name,
323             ref_results => \%results,
324             ref_additional_results => \%additional_results,
325             output => $output);
326             }
327             }
328              
329             # handle a chunk of output after executing plugins
330             # basically we parse stuff here...
331             sub handle_output_chunk {
332             my $self = shift;
333             my ($args) = {@_};
334             my $agent_name = $args->{agent_name};
335             my $monitor_name = $args->{monitor_name};
336             my $monitor_xml_path = $args->{monitor_xml_path};
337             my $output = $args->{output};
338             my %results = %{$args->{ref_results}};
339             my %additional_results = %{$args->{ref_additional_results}};
340              
341             foreach my $metric_name (keys %{$monitor_xml_path->{metric}} ) {
342             # call the relevant parsing plugin
343             my %returned_results = ();
344              
345             # run the parsing plugin one by one
346             foreach my $potential_parsing_plugin (keys %{$monitor_xml_path->{metric}->{$metric_name}}) {
347             if (defined($self->{parsing_plugins}{$potential_parsing_plugin})) {
348             $self->{m3logger}->log_message ("debug", "Calling parsing plugin: '$potential_parsing_plugin'");
349             $self->{parsing_plugins}{$potential_parsing_plugin}->parse($metric_name, $monitor_xml_path->{metric}->{$metric_name}, $output, \%returned_results);
350             }
351             }
352              
353             # call the relevant compute plugins
354             # TODO computation might be out of order in some cases when chaining
355             foreach my $potential_compute_plugin (keys %{$monitor_xml_path->{metric}->{$metric_name}}) {
356             if (defined($self->{compute_plugins}{$potential_compute_plugin})) {
357             foreach my $code (@{$monitor_xml_path->{metric}->{$metric_name}->{$potential_compute_plugin}}) {
358             $self->{m3logger}->log_message ("debug", "Calling compute plugin: '$potential_compute_plugin'");
359             my $code = $monitor_xml_path->{metric}->{$metric_name}->{$potential_compute_plugin}[0];
360             $self->{compute_plugins}{$potential_compute_plugin}->compute($agent_name, $monitor_name, $monitor_xml_path, $code, \%returned_results);
361             }
362             }
363             }
364              
365             # merge the returned results into the main %results hash
366             if (defined($monitor_xml_path->{metric}->{$metric_name}->{additional})) {
367             @additional_results{keys %returned_results} = values %returned_results;
368             } else {
369             @results{keys %returned_results} = values %returned_results;
370             }
371             }
372              
373             # TODO 'MONITIS_CHECK_TIME' hardcoded
374             # if MONITIS_CHECK_TIME is defined, use it as the timestamp for updating data
375             # note: @checktime can be empty, then we'll calculate the current timestamp
376             my @checktime;
377             if (defined($results{MONITIS_CHECK_TIME})) {
378             if (int($results{MONITIS_CHECK_TIME}) == $results{MONITIS_CHECK_TIME}) {
379             # no need for date manipulation
380             push @checktime, "checktime" => $results{MONITIS_CHECK_TIME};
381             } else {
382             my $date = new Date::Manip::Date;
383             $date->parse($results{MONITIS_CHECK_TIME});
384             # checktime here is seconds, update_data_for_monitor will multiply by
385             # 1000 to make it milliseconds
386             push @checktime, "checktime" => $date->secs_since_1970_GMT();
387             }
388             # and remove it from the hash
389             delete $results{MONITIS_CHECK_TIME};
390             }
391              
392             # format results
393             my $formatted_results = format_results(\%results);
394             my $formatted_additional_results = format_results_json(\%additional_results);
395              
396             return $self->update_data_for_monitor(
397             agent_name => $agent_name,
398             monitor_name => $monitor_name,
399             results => $formatted_results,
400             additional_results => $formatted_additional_results,
401             @checktime);
402             }
403              
404             # update data for a monitor, calling Monitis API
405             sub update_data_for_monitor {
406             my $self = shift;
407             my ($args) = {@_};
408             my $agent_name = $args->{agent_name};
409             my $monitor_name = $args->{monitor_name};
410             my $results = $args->{results};
411             my $additional_results = $args->{additional_results};
412              
413             # did the user specify a checktime?
414             my $checktime;
415             if (defined($args->{checktime})) {
416             $checktime = $args->{checktime} * 1000;
417             } else {
418             # get the time now (time returns time in seconds, multiply by 1000
419             # for miliseconds)
420             $checktime = time * 1000;
421             }
422              
423             # sanity check of results...
424             if ($results eq "") {
425             $self->{m3logger}->log_message ("info", "Result set is empty! did it parse well? - Will not update any data!");
426             return;
427             }
428              
429             if ($self->is("dry_run")) {
430             $self->{m3logger}->log_message ("info", "OK");
431             $self->{m3logger}->log_message ("info", "This is a dry run, data for monitor '$monitor_name' was not really updated.");
432             return;
433             }
434              
435             # queue it on MonitisConnection which will handle the rest
436             my $monitor_tag = $self->get_monitor_tag(
437             agent_name => $agent_name,
438             monitor_name => $monitor_name);
439             $self->update_data_for_monitor_raw(
440             agent_name => $agent_name,
441             monitor_name => $monitor_name,
442             monitor_tag => $monitor_tag,
443             checktime => $checktime,
444             results => $results,
445             additional_results => $additional_results);
446             }
447              
448             # invoke all agents, one by one
449             sub invoke_agents {
450             my $self = shift;
451             foreach my $agent_name (keys %{$self->{agents}} ) {
452             $self->invoke_agent_monitors(agent_name => $agent_name);
453             }
454             }
455              
456             # invoke all monitors, one by one
457             sub invoke_agent_monitors {
458             my $self = shift;
459             my ($args) = {@_};
460             my $agent_name = $args->{agent_name};
461             foreach my $monitor_name (keys %{$self->{agents}->{$agent_name}->{monitor}}) {
462             $self->invoke_monitor(
463             agent_name => $agent_name,
464             monitor_name => $monitor_name);
465             }
466             }
467              
468             # signals threads to stop execution
469             sub agents_loop_stop {
470             MonitisMonitorManager::M3Logger->instance()->log_message ("info", "Stopping execution...");
471             lock($condition_loop_stop);
472             $condition_loop_stop = 1;
473             cond_broadcast($condition_loop_stop);
474             }
475              
476             # invoke all agents in a loop with timers enabled
477             sub invoke_agents_loop {
478             my $self = shift;
479             # initialize all the agents
480             my @threads = ();
481              
482             foreach my $agent_name (keys %{$self->{agents}} ) {
483             push @threads, threads->create(\&invoke_agent_monitors_loop, $self, agent_name => $agent_name);
484             }
485             my $running_threads = @threads;
486              
487             # register SIGINT to stop the loop
488             local $SIG{'INT'} = \&MonitisMonitorManager::agents_loop_stop;
489              
490             do {
491             foreach my $thread (@threads) {
492             if($thread->is_joinable()) {
493             $thread->join();
494             $self->{m3logger}->log_message ("debug", "Thread '$thread' has quitted.");
495             $running_threads--;
496             }
497             }
498             sleep 1;
499             } while($running_threads > 0);
500             }
501              
502             # invoke all monitors of an agent in a loop, taking care to sleep between
503             # executions
504             sub invoke_agent_monitors_loop {
505             my $self = shift;
506             my ($args) = {@_};
507             my $agent_name = $args->{agent_name};
508             my $agent_interval = $self->{agents}->{$agent_name}->{interval};
509             $self->{m3logger}->log_message ("debug", "Agent '$agent_name' will be invoked every '$agent_interval' seconds'");
510              
511             # this loop will break when the user will hit ^C (SIGINT)
512             do {
513             foreach my $monitor_name (keys %{$self->{agents}->{$agent_name}->{monitor}}) {
514             $self->invoke_monitor(
515             agent_name => $agent_name,
516             monitor_name => $monitor_name);
517             }
518             lock($condition_loop_stop);
519             cond_timedwait($condition_loop_stop, time() + $agent_interval);
520             } while(not $condition_loop_stop);
521             }
522              
523             #####################
524             ### RAW FUNCTIONS ###
525             #####################
526              
527             # handles a raw command (add_monitor, update_data)
528             sub handle_raw_command {
529             my $self = shift;
530             my ($args) = {@_};
531             my $raw_command = $args->{raw_command};
532              
533             $self->{m3logger}->log_message ("debug", "Raw command is: '$raw_command'");
534             my (@raw_parameters) = split /\s+/, $raw_command;
535             my $command = shift @raw_parameters;
536              
537             # a quick debug message
538             $self->{m3logger}->log_message ("debug", "Handling raw command: '$command'");
539              
540             for ($command) {
541             /add_monitor/ and do {
542             my $monitor_name = shift @raw_parameters;
543             my $monitor_tag = shift @raw_parameters;
544             my $result_params = shift @raw_parameters;
545             my $additional_result_params = shift @raw_parameters;
546             my @optional_parameters;
547             if($additional_result_params ne "") { push @optional_parameters, additionalResultParams => $additional_result_params; }
548             $self->add_monitor_raw(
549             monitor_name => $monitor_name,
550             monitor_tag => $monitor_tag,
551             result_params => $result_params,
552             optional_params => \@optional_parameters);
553             };
554             /update_data/ and do {
555             my $monitor_name = shift @raw_parameters;
556             my $monitor_tag = shift @raw_parameters;
557             my $results = shift @raw_parameters;
558             my $additional_results = shift @raw_parameters;
559             $self->update_data_for_monitor_raw(
560             monitor_name => $monitor_name,
561             monitor_tag => $monitor_tag,
562             checktime => time * 1000,
563             results => $results,
564             additional_results => $additional_results);
565             };
566             /list_monitors/ and do {
567             $self->list_monitors_raw();
568             };
569             /delete_monitor/ and do {
570             my $monitor_id = shift @raw_parameters;
571             $self->delete_monitor_raw(monitor_id => $monitor_id);
572             };
573             }
574             }
575              
576             # updated raw data for monitor
577             sub add_monitor_raw {
578             my $self = shift;
579              
580             # simply forward the parameters!
581             $self->{monitis_connection}->add_monitor(@_);
582             }
583              
584             # list monitors
585             sub list_monitors_raw {
586             my $self = shift;
587             my @monitors = $self->{monitis_connection}->list_monitors();
588             my $i = 0;
589              
590             printf("ID |Name |Tag |Type |\n");
591             printf("-----|---------------|-------------------------|---------------|\n");
592             while (defined($monitors[0][$i])) {
593             my ($monitor_name) = $monitors[0][$i]->{name};
594             my ($monitor_type) = $monitors[0][$i]->{type};
595             my ($monitor_tag) = $monitors[0][$i]->{tag};
596             my ($monitor_id) = $monitors[0][$i]->{id};
597             printf("%-5s|%-15s|%-25s|%-15s|\n", $monitor_id, $monitor_name, $monitor_tag, $monitor_type);
598             $i++;
599             }
600             }
601              
602             # delete a monitor
603             sub delete_monitor_raw {
604             my $self = shift;
605             $self->{monitis_connection}->delete_monitor(@_);
606             }
607              
608             # update data for a monitor, the internal function
609             sub update_data_for_monitor_raw {
610             my $self = shift;
611             $self->{monitis_connection}->queue(@_);
612             }
613              
614              
615             ###############################
616             ### SMALL UTILITY FUNCTIONS ###
617             ###############################
618              
619             # a simple function to dynamically load all perl packages in a given
620             # directory
621             sub load_plugins_in_directory {
622             my $self = shift;
623             my ($args) = {@_};
624             my $plugin_table_name = $args->{plugin_table_name};
625             my $plugin_directory = $args->{plugin_directory};
626              
627             # initialize a new plugin table
628             $self->{$plugin_table_name} = ();
629              
630             # TODO a little ugly - but this is how we're going to discover where M3
631             # was installed...
632             my $m3_perl_module_directory = dirname($INC{"MonitisMonitorManager.pm"}) . "/MonitisMonitorManager";
633             my $full_plugin_directory = $m3_perl_module_directory . "/" . $plugin_directory;
634             # iterate on all plugins in directory and load them
635             foreach my $plugin_file (<$full_plugin_directory/*.pm>) {
636             my $plugin_name = "MonitisMonitorManager::" . $plugin_directory . "::" . basename($plugin_file);
637             $plugin_name =~ s/\.pm$//g;
638             # load the plugin
639             eval {
640             require "$plugin_file";
641             $plugin_name->name();
642             };
643             if ($@) {
644             croak "error: $@";
645             } else {
646             $self->{m3logger}->log_message ("debug", "Loading plugin '" . $plugin_name . "'->'" . $plugin_name->name() . "'");
647             $self->{$plugin_table_name}{$plugin_name->name()} = "$plugin_name";
648             }
649             }
650             }
651              
652              
653             # tests an attribute, such as 'dry_run', 'mass_load', 'test_config' etc.
654             sub is {
655             my ($self, $attribute) = @_;
656             if (defined($self->{$attribute}) and $self->{$attribute} == 1) {
657             return 1;
658             } else {
659             return 0;
660             }
661             }
662              
663             # print the XML after it was templated
664             sub templated_xml {
665             my $self = shift;
666             my $xmlout = XML::Simple->new(RootName => 'config');
667             return $xmlout->XMLout($self->{config_xml});
668             }
669              
670             # formats a monitor tag from a name
671             sub get_monitor_tag {
672             my $self = shift;
673             my ($args) = {@_};
674             my $agent_name = $args->{agent_name};
675             my $monitor_name = $args->{monitor_name};
676              
677             # if monitor tag is defined, use it!
678             if (defined ($self->{agents}->{$agent_name}->{monitor}->{$monitor_name}->{tag}) ) {
679             my $monitor_tag = $self->{agents}->{$agent_name}->{monitor}->{$monitor_name}->{tag};
680             $self->{m3logger}->log_message ("debug", "Obtained monitor tag '$monitor_tag' from XML");
681             return $monitor_tag;
682             } else {
683             # make a monitor tag from name
684             { $_ = $monitor_name; s/ /_/g; return $_ }
685             }
686             }
687              
688             # formats the hash of results into a string
689             sub format_results(%) {
690             my (%results) = %{$_[0]};
691             my $formatted_results = "";
692             foreach my $key (keys %results) {
693             $formatted_results .= $key . ":" . uri_escape($results{$key}) . ";";
694             }
695             # remove redundant last ';'
696             $formatted_results =~ s/;$//;
697             return $formatted_results;
698             }
699              
700             # formats the hash of results into a string
701             sub format_results_json(%) {
702             my (%results) = %{$_[0]};
703             return "[" . encode_json(\%results) . "]";
704             }
705              
706             # simply replaces the %SOMETHING% with the relevant
707             # return of a defined function
708             sub run_macros() {
709             $_[0] =~ s/%(\w+)%/replace_template($1)/eg;
710             }
711              
712             # macro functions
713             sub replace_template($) {
714             my ($template) = @_;
715             my $callback = "_get_$template";
716             return &$callback;
717             }
718              
719             sub metric_name_not_reserved($$) {
720             my $self = shift;
721             my ($metric_name) = @_;
722             return $metric_name ne "MONITIS_CHECK_TIME";
723             }
724              
725              
726             # Preloaded methods go here.
727              
728             1;
729             __END__