NAME
Net::Peep - Perl extension for Peep: The Network Auralizer.
DESCRIPTION
Peep is an open source free software network monitoring tool issued under the Gnu General Public License that presents information via audio output. Network diagnosis with Peep is made not only based on single network events, but the network as a whole "sounds normal."
Although Peep has found much use as a monitoring tool, the tool has been designed to allow customized clients to be created for virtually any purpose. It could be used, for example, to create a stock ticker or to parse input from a web cam with ImageMagick and create aural output based on the nature of the image.
Please refer to the section on creating a custom client below for more information.
SYNOPSIS
This document serves as an introduction to the Peep clients and the Peep client architecture.
REQUIRES
File::Tail
Time::HiRes
Net::Ping::External
Filesys::DiskFree
Proc::ProcessTable
INTRODUCTION
Peep is built on a client-server model in which the clients generate "events" based on user-defined criteria (e.g., whether a packet denial has been logged or a broken link on a web site was found). One or several Peep servers are then notified of the events by clients, at which time an audio signal is generated.
The clients, which include such applications as logparser
and sysmonitor
and for which this document constitutes introductory documentation, are written in Perl, IMHO about the coolest language ever. The bulk of the client code is composed of a set of Perl modules comprising objects and base classes for use by Peep clients and their derivatives.
The server, peepd
, is written in C.
Both the client and server are available for download free of charge from the Peep homepage located at
The Peep client modules and executables are also available on the CPAN (Comprehensive Perl Archive Network) for installation via the time-honored
perl -MCPAN -e
"install Net::Peep"
In fact, this is the preferred method of installation of the Peep clients.
Consult the core Peep documentation for more information on installation and usage of Peep.
The Peep client library is composed of the following core modules:
Perl Modules
------------
Net::Peep A non-functional module. Simply holds
POD documentation
for
Peep; in fact,
it holds the documentation that you are
reading right now!
Net::Peep::Conf The Peep configuration object. An
object representation of peep.conf.
Net::Peep::Parser The Peep configuration file parser. Reads
peep.conf and populates Peep::Conf
appropriately.
Net::Peep::BC The Peep broadcast module. Used to notify Peep
servers that an event
has
been generated.
Net::Peep::Log Provides utility methods
for
logging, debugging,
and benchmarking.
Net::Peep::Client Base and utility class
for
Peep clients and
client modules.
Net::Peep::Client::Logparser Utility class
for
the logparser client.
Net::Peep::Client::Sysmonitor Utility class
for
the sysmonitor client.
Net::Peep::Client::Pinger Utility class
for
the pinger client.
Net::Peep::Peck Utility class
for
the peck client.
Net::Peep::Notifier A class Peep uses to
send
out e-mail
notifications.
There are a variety of helper classes other than those mentioned above that server a variety of useful functions. Consult the individual PODs for more information.
Clients
-------
logparser Generates events based on matching regular
expressions to tailed logs (e.g.,
/var/
log
/messages).
sysmonitor Generates events based on
system
events (e.g.,
load average exceeding 2.0).
pinger Generates events based on whether a host
is responsive.
peck Generates ad hoc Peep events. Primarily
for
testing purposes.
keytest Generates ad hoc Peep events. Primarily
for
fun.
Please refer to the individual modules of the Peep distribution (e.g., Net::Peep::BC) or the Peep client executables (e.g., logparser) for further documentation.
CREATING A CUSTOM PEEP CLIENT
One of the most powerful features of Peep is the ability to create customized clients to use Peep for whatever you like. Although Peep is used widely as a systems and network monitor because it is well suited to the task, you could do anything from creating a stock monitoring client to creating a client that will take output from a web cam, parse it with ImageMagick (see http://www.imagemagick.org and http://www.imagemagick.org/www/perl.html) and generate real-time sound effects based on what you see.
With the whole of the CPAN at your disposal, the sky is the limit.
The Net::Peep::Client module and other helper classes make constructing a custom Peep client a breeze.
It is quite formulaic, and once you have done it once, you will already feel like it is old hat. In describing the process, we will create the first example mentioned above: A client to monitor stock prices. All told, the code is only 50 lines (only 33 statements!) and took me about a half hour to write.
The client will wake up every 60 seconds, get some stock quotes over the web, and depending on whether the stock is above or below a certain price, will alert you with both a peep and an e-mail notification.
Bear in mind that you really do not need to know much Perl to create a client. If you are a newbie, just copy what is done here while using your favorite Perl book to figure out whatever you do not understand.
The full code listing is given at the end of this section for reference.
SOME PRELIMINARIES
The ticker
requires a Perl module by the name of Finance::Quote
.
I will assume that the reader is familiar with how to install a Perl module. For those who are unfamiliar with the process of installing a Perl module from the CPAN, a hint:
sudo perl -MCPAN -e
'install Finance::Quote'
THE CLIENT CONFIGURATION
First, create a section in the Peep configuration file, peep.conf
, for your client. (peep.conf
would typically be put in your /usr/local/etc
directory during install.) peep.conf
is heavily commented, so you should use that as a reference as well as this document.
The section begins with a client
declaration and ends with an end client
declaration.
There is some window dressing you have to add, including a class
and port
declaration. You can just copy those from one of the other clients.
You can also put an optional default
section, which specifies any defaults for command-line options. See the logparser
section of peep.conf
for an example.
Next (and this is where you are doing the real work), you create the config
section.
Between the config
and end config
, you can put anything you want. You will see what this section is all about in a bit, but for now let us just create a section that lists some stock symbols and related information we will need for the client.
If you want to receive e-mail notifications, you can include an optional notification
section following the config
section as well which will describe who is to be sent the e-mail and some other information.
The whole thing looks like this:
client ticker
class morgenstern
port 1999
config
# Stock symbol Stock exchange Event Max Min
RHAT nasdaq red-hat 4.0 3.6
SUNW nasdaq sun-microsystems 9.0 8.0
end config
notification
notification-hosts morgenstern
notification-recipients collin.starkweather
@colorado
.edu
notification-level
warn
end notification
end client ticker
Finally, you should define the events you just created. An event named red-hat
is associated with the stock symbol for Red Hat (no endorsement implied) and one named sun-microsystems
is associated with, you guessed it, Sun Microsystems (again, no endorsement implied).
So let us tie these events into some sounds. Going down to the events
block in the configuration file, put in the following:
events
# Event Type | Path to Sound File | # of sounds to load
...
red-hat /usr/
local
/share/peep/sounds/misc/events/rooster.* 1
sun-microsystems /usr/
local
/share/peep/sounds/misc/events/doorbell.* 1
end events
This will cause a rooster to crow when RHAT
goes out of bounds and a doorbell to chime when the same happens with SUNW
.
THE CODE
Creating the client itself is really quite easy. There is going to be alot of discussion in this section, and the code is quite liberally commented. However there are actually only 50 lines (and only 33 statements - some statements span lines for clarity) of code to create the entire client. So you should not feel intimidated. There is really not much to it.
I assume that the reader has some working knowledge of Perl. If you are just starting out, I would recommend that you look up
to supplement any other learning you are doing. It is a very helpful forum and a real boon to those just starting out.
- OPEN A FILE
-
Open a file called
ticker
in your text editor of choice. - USE SOME MODULES
-
The first thing we will create is the
use
section. This will read in all of the objects we need. I will also use thestrict
pragma. Usingstrict
is a habit I highly recommend:#!/usr/bin/perl
use
strict;
use
Net::Peep::BC;
use
Net::Peep::Log;
use
Net::Peep::Client;
use
Net::Peep::Notifier;
use
Finance::Quote;
After using
strict
, several Peep modules are used. TheNet::Peep::BC
module is used to send a broadcast to the server to let it know it is supposed to play a sound.Net::Peep::Log
is a helpful module if you need to create some well-formatted output. (We will use it in a couple of places to let ourselves know what we are doing.)The
Net::Peep::Client
module is the real workhorse. That is what will enable us to write a client in 33 statements or less. TheNet::Peep::Notifier
andNet::Peep::Notification
modules are used to send e-mail notifications. (I want to know it if my stocks take a nosedive and I am out of my office!)Next is the
Finance::Quote
module, which we will use to fetch the stock prices.Finally we declare some global variables with the
vars
pragma. You will see what these are used for later. - INSTANTIATE SOME OBJECTS
-
We will be using three objects in the main section of the script: A logging object, a Peep client object, and the object that gets our stock quotes for us.
$logger
= new Net::Peep::Log;
$client
= new Net::Peep::Client;
$quoter
= new Finance::Quote;
- WORKING WITH THE CLIENT OBJECT
-
Now we will work some magic with the client object.
The first thing we do is give the client a name. We will call our client 'ticker'.
$client
->name(
'ticker'
);
Now we need to initialize the client.
$client
->initialize();
There are a variety of command-line options that will be read and parsed during the initialization. If you would like to supply some of your own command-line options to the initialization, you can do so using the format of the
Getopt::Long
object with something like:my
$foo
=
''
;
my
%options
= (
'foo=s'
=>\
$foo
, ... );
$client
->initialize(
%options
);
Next we will tell the client what it will use to parse the
config
block we defined above. We will simply pass it a reference to a subroutine which we will define later. How about we call the subroutineparse
?$client
->parser( \
&parse
);
Now that we have told the client what to use to parse the
config
block, we can tell it to read in the configuration information from the Peep configuration file:my
$conf
=
$client
->configure();
The return value of the configure method,
$conf
, is aNet::Peep::Conf
object containing the information gleaned from the Peep configuration file and a variety of useful methods. See theNet::Peep::Conf
PODs for more information.After the configuration information is read, we will start the client on its way. The first thing we do is tell the client what to do every time it wakes up. We will feed it a callback (another reference to a subroutine, this one called
loop
) which will be run every time the client wakes up. Then we will start the client up, telling it to wake up every 60 seconds and execute the callback.$client
->callback( \
&loop
);
$client
->MainLoop(60);
That is all there is to it! Well, almost. We mentioned two subroutines above which we have not yet defined. So the last thing we will do is write these subroutines.
- THE PARSER
-
The parser is given everything between the
config
andend config
lines in the section of the configuration file we defined above.Though you can parse it any way you like, I favor using a regular expression. They seem to intimidate people because they look so cryptic, but they were much easier for me to get the hang of than I expected.
# This subroutine will be used to parse the following 2 lines from
# peep.conf (see above) and store the information in %config:
# RHAT nasdaq red-hat 4.0 3.6
# SUNW nasdaq sun-microsystems 9.0 8.0
sub
parse {
for
my
$line
(
@_
) {
if
(
$line
=~ /^\s*([A-Z]+)\s+(\w+)\s+([\w\-]+)\s+([\d\.]+)\s+([\d\.]+)/) {
my
(
$symbol
,
$exchange
,
$event
,
$max
,
$min
) = ($1,$2,$3,$4,$5,$6);
$config
{
$symbol
} = {
event
=>
$event
,
exchange
=>
$exchange
,
max
=>
$max
,
min
=>
$min
};
}
}
}
# end sub parse
We basically create a data structure from the
%config
hash. The keys of the hash are the stock symbols and the values are hash references used to describe some information about the stock symbol such as what stock exchange to look at, what event (sound) to play, and what the maximum and minimum prices that will trigger the event are.The information that we get from the configuration file will be used in the next section to trigger the event and the e-mail notification.
- THE CALLBACK
-
Finally, the meat of the client: The callback. I will leave it as an exercise to the reader to browse the documentation for
Finance::Quote
.First the code, then the explanation:
sub
loop {
for
my
$key
(
sort
keys
%config
) {
$logger
->
log
(
"Checking the price of [$key] ..."
);
# Fetch some information about the stock including the price
my
%results
=
$quoter
->fetch(
$config
{
$key
}->{
'exchange'
},
$key
);
my
$price
=
$results
{
$key
,
'price'
};
$logger
->
log
(
"\tThe price of [$key] is [$price]."
);
if
(
$price
>
$config
{
$key
}->{
'max'
} or
$price
<
$config
{
$key
}->{
'min'
}) {
$logger
->
log
(
"\tThe price is out of bounds! Sending notification ...."
);
# The price is out of bounds! We'll start peeping ...
my
$broadcast
= Net::Peep::BC->new(
'ticker'
,
$conf
);
$broadcast
->
send
(
'ticker'
,
type
=>0,
sound
=>
$config
{
$key
}->{
'event'
},
location
=>128,
priority
=>0,
volume
=>255);
my
$notifier
= new Net::Peep::Notifier;
my
$notification
= new Net::Peep::Notification;
$notification
->client(
'ticker'
);
$notification
->status(
'crit'
);
$notification
->datetime(
time
());
$notification
->message(
"The price of $key is $price!"
);
$notifier
->notify(
$notification
);
}
}
}
# end sub loop
In the callback, we loop over the stock symbols we found in the
parse
subroutine described above withfor
my
$key
(
sort
keys
%config
) {
...
}
For each stock symbol, we fetch the price and other information using
my
%results
=
$quoter
->fetch(
$config
{
$key
}->{
'exchange'
},
$key
);
Next, we check if the price is greater than the maximum or less than the minimum defined in the configuration file:
if
(
$price
>
$config
{
$key
}->{
'max'
} or
$price
<
$config
{
$key
}->{
'min'
}) {
...
}
If it is, we first send a message to the Peep server to play a sound. We do this by instantiating a
Net::Peep::BC
, the Peep broadcast object, and calling itssend
method.my
$broadcast
= Net::Peep::BC->new(
'ticker'
,
$conf
);
$broadcast
->
send
(
'ticker'
,
type
=>0,
sound
=>
$config
{
$key
}->{
'event'
},
location
=>128,
priority
=>0,
volume
=>255);
The
type
option indicates the type of sound (0 for an event, 1 for a state). The sound option tells it what type of sound it should play (in this case eitherred-hat
orsun-microsystems
). The remainder of the settings are described in theNet::Peep::BC
documentation.Second, we send out an e-mail notification. This is done by creating a
Net::Peep::Notifier
object, which will actually send the e-mail, and giving it aNet::Peep::Notification
object properly populated with information that will be included in the e-mail:my
$notifier
= new Net::Peep::Notifier;
my
$notification
= new Net::Peep::Notification;
$notification
->client(
'ticker'
);
$notification
->status(
'crit'
);
$notification
->datetime(
time
());
$notification
->message(
"The price of $key is $price!"
);
$notifier
->notify(
$notification
);
For more information, consult the documentation for these objects.
It is worth noting that this does not imply that we will receive an e-mail every 60 seconds. The notification system sends out a notification when it first receives one, then sends all subsequent notifications in a bundle at regular intervals (you can set the bundling interval in
peep.conf
) .We have created a Peep client from scratch! Let us see how it works ....
RUN THE CLIENT
Simply as an example, I would start the server with
./peepd -S /usr/
local
/etc/peep.conf --nodaemon
I use the --nodeamon
flag so that I can watch the output.
Then
./ticker --noautodiscovery --server=localhost --port=2001 \
--nodaemon --config=/usr/
local
/etc/peep.conf
DROP US A LINE
We would be interested in any clients that are created, both out of curiosity and because the code may be useful to others. Our e-mail addresses are given below.
AUTHOR
Michael Gilfix <mgilfix@eecs.tufts.edu> Copyright (C) 2001
Collin Starkweather <collin.starkweather@colorado.edu>
ACKNOWLEDGEMENTS
Many thanks to the folks at SourceForge for creating a robust development environment to support open source projects such as Peep.
If you are not familiar with SourceForge, please visit their site at
SEE ALSO
perl(1), peepd(1), logparser, sysmonitor, pinger, peck, keytest.
TERMS AND CONDITIONS
This software is issued under the Gnu General Public License.
For more information, write to Michael Gilfix (mgilfix@eecs.tufts.edu).
This version of Peep is open source; you can redistribute it and/or modify it under the terms listed in the file COPYING included with the full Peep distribution which can be found at
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
RELATED SOFTWARE
For those interested in a robust network and systems monitoring tools, your humble author has found Big Brother to be a valuable resource which is complementary to Peep. Big Brother is an open source product and there are a large number of user-contributed plug-ins which make it ideal for a variety of needs.
You can find more information on Big Brother at
Those who enjoy Peep may also enjoy checking out logplay, which is similar in concept but fills a different niche.
You can find more information on logplay at
Logplay is not under active development at the time, though many ideas from the project are being incorporated into Peep with the assistance of the author, Rando Christensen, who has generously donated his time in many productive discussions.
Please contact me at
collin.starkweather
@colorado
.edu
if you have any questions.
APPENDIX A: THE STOCK TICKER CONFIGURATION
client ticker
class morgenstern
port 1999
config
# Stock symbol Stock exchange Event Max Min
RHAT nasdaq red-hat 4.0 3.6
SUNW nasdaq sun-microsystems 9.0 8.0
end config
notification
notification-hosts morgenstern
notification-recipients collin.starkweather
@colorado
.edu
notification-level
warn
end notification
end client ticker
events
# Event Type | Path to Sound File | # of sounds to load
...
red-hat /usr/
local
/share/peep/sounds/misc/events/rooster.* 1
sun-microsystems /usr/
local
/share/peep/sounds/misc/events/doorbell.* 1
end events
APPENDIX B: THE STOCK TICKER
Note the PODs at the beginning of the script. When the script is run with the help flag
./ticker --help
the client will display whatever PODs are included with the script.
#!/usr/bin/perl
=head1 NAME
ticker - A stock monitoring client written for Peep: The Network
Auralizer.
=head1 USAGE
./ticker --help
./ticker --noautodiscovery --server=localhost --port=2001 --nodaemon
If you have any problems, try turning on debugging output with
something like --debug=9.
=head1 CONFIGURATION
To use this client, include a section like the following in peep.conf:
client ticker
class home
port 1999
config
# Stock symbol Stock exchange Event Max Min
RHAT nasdaq red-hat 4.0 3.6
SUNW nasdaq sun-microsystems 9.0 8.0
end config
notification
notification-hosts localhost
notification-recipients bogus.user@bogusdomain.com
notification-level warn
end notification
end client ticker
and another section in the events block with something like
events
#Event Type | Path to Sound File | # of sounds to load
...
red-hat /usr/local/share/peep/sounds/misc/events/rooster.* 1
sun-microsystems /usr/local/share/peep/sounds/misc/events/doorbell.* 1
end events
=head1 AUTHOR
Collin Starkweather <collin.starkweather@colorado.edu> Copyright (C) 2001
=head1 SEE ALSO
perl(1), peepd(1), Net::Peep, Net::Peep::Client, Net::Peep::BC,
Net::Peep::Notifier, Net::Peep::Notification, Finance::Quote
=cut
# Always use strict :-)
use
strict;
use
Net::Peep::BC;
use
Net::Peep::Log;
use
Net::Peep::Client;
use
Net::Peep::Notifier;
use
Finance::Quote;
# The Net::Peep::Log object will allow us to print out some things in
# a nicely formatted way so we can tell ourselves what we're doing ...
$logger
= new Net::Peep::Log;
# Instantiate a Peep client object. The client object handles most of
# the dirty work for us so we don't have to worry about things such as
# forking in daemon mode or parsing the command-line options or the
# Peep configuration file. Its a very sophisticated object with many
# useful functions. For more information, type
#
# perldoc Net::Peep::Client
$client
= new Net::Peep::Client;
$quoter
= new Finance::Quote;
# First we have to give the client a name
$client
->name(
'ticker'
);
# Now we initialize the client. If the initialization returns a false
# value, we display documentation for the script.
$client
->initialize() ||
$client
->pods();
# Now we assign a parser that will parse the 'ticker' section of the
# Peep configuration file
$client
->parser( \
&parse
);
# Now we tell the client to get the information from the configuration
# file. It returns a Net::Peep::Conf, the Peep configuration object,
# which contains information from the configuration file.
$conf
=
$client
->configure();
# Register a callback which will be executed every 60 seconds. The
# callback is simply a function which checks the price of the stock
# and peeps every time it exceeds the maximum or minimum price that
# has been set.
$client
->callback( \
&loop
);
# Start looping. The callback will be executed every 60 seconds ...
$client
->MainLoop(60);
sub
parse {
# Parse the config section for the ticker client in the Peep
# configuration file
# We'll use a regular expression to extract the ticker information
# and stuff it into a data structure (the global variable %config)
# This subroutine will be used to parse lines from peep.conf such
# as the following and store the information in %config:
# RHAT nasdaq red-hat 4.0 3.6
# SUNW nasdaq sun-microsystems 9.0 8.0
for
my
$line
(
@_
) {
if
(
$line
=~ /^\s*([A-Z]+)\s+(\w+)\s+([\w\-]+)\s+([\d\.]+)\s+([\d\.]+)/) {
my
(
$symbol
,
$exchange
,
$event
,
$max
,
$min
) = ($1,$2,$3,$4,$5,$6);
$config
{
$symbol
} = {
event
=>
$event
,
exchange
=>
$exchange
,
max
=>
$max
,
min
=>
$min
};
}
}
}
# end sub parse
sub
loop {
for
my
$key
(
sort
keys
%config
) {
$logger
->
log
(
"Checking the price of [$key] ..."
);
# Fetch some information about the stock including the price
my
%results
=
$quoter
->fetch(
$config
{
$key
}->{
'exchange'
},
$key
);
my
$price
=
$results
{
$key
,
'price'
};
$logger
->
log
(
"\tThe price of [$key] is [$price]."
);
if
(
$price
>
$config
{
$key
}->{
'max'
} or
$price
<
$config
{
$key
}->{
'min'
}) {
$logger
->
log
(
"\tThe price is out of bounds! Sending notification ...."
);
# The price is out of bounds! We'll start peeping ...
my
$broadcast
= Net::Peep::BC->new(
'ticker'
,
$conf
);
$broadcast
->
send
(
'ticker'
,
type
=>0,
sound
=>
$config
{
$key
}->{
'event'
},
location
=>128,
priority
=>0,
volume
=>255);
# In case we're away from our desk, we'll also send out an
# e-mail notification. Don't want to miss the action!
my
$notifier
= new Net::Peep::Notifier;
my
$notification
= new Net::Peep::Notification;
$notification
->client(
'ticker'
);
$notification
->status(
'crit'
);
$notification
->datetime(
time
());
$notification
->message(
"The price of $key is $price!"
);
$notifier
->notify(
$notification
);
}
}
}
# end sub loop