This is another contribution from the Xymon list provided by Sigurður Guðbrandsson (www.raforninn.is)


The problem with parsing is to know what you want to parse.

The first step is to send your information to hobbit and see it displayed.

Second step is to configure hobbitlaunch.cfg file to send the data from the column to your script. FROM /etc/hobbit/hobbitlaunch.cfg

[rrdstatus]
        ENVFILE /usr/lib/hobbit/server/etc/hobbitserver.cfg
        NEEDS hobbitd
        CMD hobbitd_channel --channel=status --log=$BBSERVERLOGS/rrd-status.log hobbitd_rrd \
                                     --extra-tests=hitastig \
                                     --extra-script=/usr/lib/hobbit/server/ext/rrd_digitemp.pl \
                                     --rrddir=$BBVAR/rrd

The –extra-tests is the definition of what columns you want to parse. You can have as many columns as you like, comma separated. The –extra-script is the path to the script that you wish to run to do the parsing. You can only have one there.

Then you have to edit hobbitserver.cfg and add the test to TEST2RRD and GRAPHS variables. Then either reboot the server or kill hobbit_channel processes (they should restart the next time they are scheduled to run)

To begin to know what you have to parse, just tell the script to write to some file (overwrite, not append .. Unless of course you want it to grow bigger and bigger). It should be very similar to what the web site shows. Alternatively there should be a way to use the bb program to display it, but I didn't bother finding out how.

Then of course you do your parsing. I recommend that you read about RRD graphs and how you can display different values (is it a counter, is it a variable like temperature, percentage etc etc) on the official RRD website.

You should receive 3 args from hobbit when it runs your script, it behaves so:

$scriptname $hostname $testname $messagefile

The messagefile is a temporary file which you shall parse.

The final stage is to output your information to hobbit in a way it understands, printing directly to STDOUT. The format is so, note that you don’t have to have the type GAUGE, replace with what you need:

DS:<datasetname>:GAUGE:600:0:100
<Testname>.<sensorname>.rrd
<value>
DS:<datasetname>:GAUGE:600:0:100
<Testname>.<sensor2name>.rrd
<value>
Etc etc.. 

A tip for the wise, I had a lot of struggle with this when I was making it, and then realised that I can't have the dataset names any different in all the files, it has to be static, that is, one name.

Then you should check if there are any RRD files being made. They should be located in /var/lib/hobbit/rrd/<hostname>/ or /usr/local/hobbit/data/rrd/<hostname> (if you installed manually instead of a package).

Then there comes the fun, to be able to show off your results in a graph. You should edit hobbitgraph.cfg file for that. Mine looks like this:

[hitastig]
        FNPATTERN hitastig.(.*).rrd
        TITLE Hitastig
        YAXIS Celsius
        DEF:h@RRDIDX@=@RRDFN@:temperature:AVERAGE
        LINE2:h@RRDIDX@#@COLOR@:@RRDPARAM@
        GPRINT:h@RRDIDX@:LAST: \: %5.1lf (cur)
        GPRINT:h@RRDIDX@:MAX: \: %5.1lf (max)
        GPRINT:h@RRDIDX@:MIN: \: %5.1lf (min)
        GPRINT:h@RRDIDX@:AVERAGE: \: %5.1lf (avg)\n

The files it expects are hitastig.<sensorname>.rrd, don't let that extra dot fool you, it needs to be there. See in the DEF line, the name I chose for the datasets is temperature. (I remind you again, it needs to be static)

If you do this successfully, you should see a graph in hobbit as soon as you finish this last thing (just let the website refresh once).

For reference (and of course to future developers that will read the mailing list archive) I will attach my scripts here so you know what to expect.

dgitemp.pl – This script reads from digitemp values, names and peak values from the MySQL database and sends them to hobbit.

#!/usr/bin/perl
# This script reads digitemp values and writes them to a # temporary file which the hobbit client sends out to # the Xymon Monitor.
# This script really should be rewritten so it will contain subs for operations.
# That would be much more tidier.
# Written by Sigurdur Gudbrandsson
# sigurdur@raforninn.is
 
use strict;
use DBI;
 
# Lets declare our variables
 
my $db_user = "username"; # Change to whatever your username is 
my $db_pass = "password"; # Change to whatever your password is 
my $db_name = "stats"; 
my $table_meta = "digitemp_metadata"; 
my $table = "digitemp";
 
# We need to get some variables from the environment, don't change this 
my $BB = $ENV{BB}; 
my $BBDISP = $ENV{BBDISP}; 
my $MACHINE = $ENV{MACHINE}; 
my $BBTMP = $ENV{BBTMP};
 
# Change this to whatever you want your test to be named 
my $testname = "hitastig";
 
# Don't change this or your test will never be green 
my $color = "green";
 
# Set this to other than 0 if you want to debug 
my $debug = 0;
 
# Lets connect to the database
my $dbh = DBI->connect("DBI:mysql:$db_name","$db_user","$db_pass")
          or die "I cannot connect to dbi:mysql:$db_name as $db_user - DBI::errstr\n";
 
# Lets get the sensor ID's, names and min/max values
my $sql = "SELECT SerialNumber,name,description,min,max FROM $db_name.$table_meta";
 
my $sth = $dbh->prepare($sql) or die "Can't execute statement $sql because: $DBI::errstr"; 
$sth->execute();
 
my (@sensors) = ();
while (my @ary = $sth->fetchrow_array()) {
        if ($ary[3] == "NULL") {
                $ary[3] = 0.000;
        }
        if ($ary[4] == "NULL") {
                $ary[4] = 99.999;
        }
        push(@sensors, [@ary]);  # [@ary] is a reference 
}
$sth->finish();
 
# Now we have all the sensors in a two dimensional array, @sensors 
# Also, if there is a NULL value in min or max, it has been substituted with a value
 
# Now we will get the temperature of each sensor from the database 
# and check if the temp is too high or too low.
 
my $count = 0;
while (@{sensors[$count]}) {
        print "WHILE: entering first while loop\n" if ($debug);
        my $sql = "SELECT Fahrenheit FROM $db_name.$table WHERE SerialNumber='$sensors[$count][0]' ORDER BY dtKey DESC LIMIT 0,1";
        print "SQL: term is \" $sql \" \n" if ($debug);
        my $sth = $dbh->prepare($sql) or die "Can't execute statement $sql because: $DBI::errstr";
        $sth->execute();
        $sensors[$count][5] = $sth->fetchrow_array();
        if ($sensors[$count][5] > $sensors[$count][4]){
                print "IF: status for $sensors[$count][1] is red\n" if ($debug);
                $sensors[$count][6] = "&red";
                $color = "red";
        }
        elsif ($sensors[$count][5] < $sensors[$count][3]){
                print "IF: status for $sensors[$count][1] is yellow\n" if ($debug);
                $sensors[$count][6] = "&yellow";
                if ($color != "red"){
                        $color = "yellow";
                }
        }
        else {
                print "IF: status for $sensors[$count][1] is green\n" if ($debug);
                $sensors[$count][6] = "&green";
        }
        $sth->finish();
        $count++;
}
 
# We can close the database now
$dbh->disconnect(); 
 
# Next is to get our results into an array 
# For reference, 0=SerialNumber 1=name 2=description 3=min 4=max 5=value 6=color in our array
 
my $tmp = "\n";         # First line in the array
print $color if ($debug);
$count = 0;
while (@{sensors[$count]}) {
        print "WHILE: entering second while loop\n" if ($debug);
        print "WHILE: $sensors[$count][1] is being printed\n" if ($debug);
        $tmp = $tmp."    $sensors[$count][6]    $sensors[$count][1] = $sensors[$count][5]\n";
        $tmp = $tmp."            : min=$sensors[$count][3] max=$sensors[$count][4]\n";
        $tmp = $tmp."            : $sensors[$count][2]\n\n";
        $count++;
}
 
# Now we decode from UTF-8 to latin1 (iso-8859-1) if there is anything in utf8 open(TEMP, ">$BBTMP/$testname.tmp.txt"); 
print TEMP $tmp; close(TEMP);
 
# Now we get the converted data
$tmp = `/usr/bin/iconv -f utf8 -t iso-8859-1 $BBTMP/$testname.tmp.txt`;
 
# Now finally we output the information to our beloved hobbit 
my $date = localtime; 
my $cmd = "$BB $BBDISP \"status $MACHINE.$testname $color $date \n $tmp \n \"";
system($cmd);
 
print $cmd if ($debug);
print $tmp if ($debug);
 
exit;

Here is the output from this script:

    &green    Tölvu_kæling = 21.25 C
            : min=1.000 max=25.000
            : This sensor has not yet been described

    &green    Verkstæði = 25.81 C
            : min=0.000 max=99.999
            : This sensor has not yet been described

    &green    Tölvuskápur = 22.12 C
            : min=14.000 max=25.000
            : This sensor has not yet been described 

    &green    Tölvu_kæl_út = 46.38 C
            : min=0.000 max=99.999
            : This sensor has not yet been described

rrd_digitemp.pl – This script parses the information from hobbit and produces the channel data to make the RRD files.

#!/usr/bin/perl
use strict;
 
# Input parameters: Hostname, testname (column), and messagefile 
my $hostname=$ARGV[0]; 
my $testname=$ARGV[1]; 
my $fname=$ARGV[2];
 
my ($line1, @line, @buff, @key, @value, $value, @tmp);
 
open(IN,"$fname");
read(IN, $line1, 10000);
@line=split('\n',$line1);
@buff = grep(/ = /,@line);
close(IN);
chomp(@buff);                                   # Lets strip the newline if there is any.
for( my $i = 0; $i < scalar(@buff); $i++)       # Now we go through the whole array of lines
{
        $buff[$i] = substr($buff[$i], 10);      # Trimming the beginning
        $buff[$i] =~ s/ C//g;                      # Removing the end
        $buff[$i] =~ s/ //g;                        # Removing all the whitespace
        @tmp = split('=', $buff[$i]);
        $key[$i] = makesafe($tmp[0]);
        $value[$i] = $tmp[1];
#        print $buff[$i]."\n";                   # Printing a test line to view the results
}
 
open(IN,">>/var/log/hobbit/custrrd.log");
write($buff[1]);
close(IN); 
 
# The next loop will print out the information for making the RRD file.
for( my $i = 0; $i < scalar(@key); $i++ ) {
        print "DS:temperature:GAUGE:600:0:100\n";      # Prints out each sensor name
#       print "DS:".$key[$i].":GAUGE:600:0:100\n";      # Prints out each sensor name
        print $testname.".".$key[$i].".rrd\n";          # Prints out the rrd file name
        print $value[$i]."\n";                          # Prints out the value
}
 
 
 
# This sub produces safe output so hobbit will be able to make the files 
# (It seems that hobbit doesn't like special letters in file names) 
sub makesafe {
        my $word = shift;
        $word =~ s/ö/o/g;
        $word =~ s/á/a/g;
        $word =~ s/í/i/g;
        $word =~ s/é/e/g;
        $word =~ s/ó/o/g;
        $word =~ s/ý/y/g;
        $word =~ s/ú/u/g;
        $word =~ s/æ/ae/g;
        $word =~ s/ð/d/g;
        $word =~ s/þ/th/g;
#       $word =~ s/_//g;
#       $word = lc($word);
        return $word;
}
 
exit;