Panoptes::Monitor
Panoptes comes with a handful of monitors, and others are on the way as I port them from my GRID::Panoptes prototype. The list of plugins I have developed or intend to develop include:
- system monitors including CPU, Memory, and disk utilization
- Tail - follow the tail of a growing log file
- RSS - monitor for new entries in RSS feeds
- IMAP - monitor an IMAP inbox for new email
- OutlookWeb - monitor an inbox through Outlook Web Access
- IRC - monitor IRC for activity, also Yahoo and AIM via BitlBee
- IdleOSX - monitor for active/idle time on OS X
- Twitter - monitor twitter and identica posts
- WebChangeMon - monitor web pages for new software releases
- Weather - monitor the local temperature
Here's some information for anyone who wants to create their own monitors.
Guiding Principals
The overall goal for the monitoring component is to minimize the number of side-effects on the system. To this end the monitors should be as small and efficient as possible.
The idea is that no significant processing or analysis of the data is done in the monitoring layer. All significant processing of the data should be performed by the rules component.
Moose
Panoptes::Monitor is built on Moose, a (post)modern object system for Perl 5.
In most cases you won't need to know much about Moose, it just makes the code a lot more readable.
Some of the components use Mouse rather than Moose since Mouse is pure perl (a requirement for use with the grid component).
Scheduling
All scheduling in Panoptes::Monitor is done by POE, a powerful framework for writing cooperatively multitasked programs:
So your monitor can harness all the power that is POE.
In most cases, though, your monitoring plugin need not know anything about POE. All you will need to do is set the 'refresh' attribute on your object and it will be scheduled automatically. If the monitoring daemon is restarted, your plugin will automatically be scheduled to run again at the previously scheduled time.
has 'refresh' => ( is => 'rw',
required => 1,
);
Keeping POE code out of the monitors makes testing much simpler since, in most cases, you won't have to start the POE kernel to test your monitor.
Messaging
Any time a monitor observes a new/interesting event, it generates a message. A message is really just a simple perl hash that can be a simple set of key/value pairs or have values that are complex data structures. Messages have no enforced schema. For example, a plugin that checks the ping time to a remote host might run the ping command, parse the output, and then send a message with the data that was retrieved:
$self->messaging->send( { host => $ping_host,
count => $packets_total,
loss => $packets_lost,
ave => $average_rt,
} );
You'll need an attributed defined in your monitor to access the messaging object:
has 'messaging' => ( is => 'rw',
required => 1,
);
State Database
Panoptes::Monitor uses DBD::Deep to store any state data required by your monitor.
In many cases monitors may not need to store any state data at all. For example, a monitor that checks the temperature every 15 minutes simply generates a message every 15 minutes. However, a plugin that checks for messages in an IMAP inbox every few minutes needs to cache the ids of the messages that are currently in the inbox to prevent constantly re-sending the same messages over and over again.
In general the state database should be used rather that keeping values in memory. This ensures that the monitoring engine can safely be killed at any time and will start right up where it left off.
In general, try to avoid over-using the state database. The job of your monitor is simply to generate a message when a new event occurs.
In order to access the state database, simply include the following attribute in your monitor:
has 'state' => ( is => 'rw',
required => 1,
);
Hello World
All that being said, let's build at a simple 'Hello World' type monitoring plugin.
package Panoptes::Monitor::HelloWorld;
use Mouse;
has 'messaging' => ( is => 'ro',
required => 1,
);
has 'config' => ( is => 'ro',
required => 1,
);
has 'state' => ( is => 'rw',
required => 1,
);
# a description of your service
has 'service' => ( is => 'rw',
isa => 'Str',
default => 'Hello World Service',
);
# refresh is set in seconds, this monitor will be run every 3 minutes
has 'refresh' => ( is => 'rw',
isa => 'Int',
default => 180,
);
# a moose role that enforces the interface and provides schedule()
with 'Panoptes::Monitor::Roles::Monitor';
sub initialize {
my ( $self ) = @_;
# run the check() routine at frequency specified by 'refresh'
$self->schedule();
}
# your monitor must define a 'check' method
sub check {
my ( $self ) = @_;
# if this monitor has ever run before, then don't send the message again.
# this is just a silly way of demonstrating the state database.
return if $self->state->{done};
# send a message with the subject set to 'hello world'
$self->messaging->send( { subject => "hello world" } );
# set a flag in the state database so we don't re-send this
# message every few minutes. this is just a silly way of
# showing how to use the state db.
$self->state->{done} = 1;
}
1;
Config
Sorry, this is a different tutorial... Coming soon....
has 'config' => ( is => 'rw',
required => 1,
);
Examples
There are plenty of examples in the directory
panoptes-monitor/lib/Panoptes/Monitor/