Monitoring lighttpd in Xymon / Hobbit
My employer starting using lighttpd on one layer of our architecture about a year or so ago, until now that layer has kind of been a black box to the majority of the technical staff due to not having mod_status enabled. In preparation for it being turned on (I requested it be so after using it on my own servers), I have created a Xymon Monitor (formally know as Hobbit) script which hits the /server-status page on the localhost and reports that data back to Xymon. The data it reports includes requests per second and “amount increase since last script run” for the “Total KBytes” and “Total Accesses” numbers. I also created a graph for the requests per seconds stat.
The Graph definition is as follows:
[lighttpd] TITLE lighttpd Requests/Second YAXIS # reqs/sec DEF:RPS=lighttpd.rrd:reqpersec:AVERAGE LINE2:RPS#0000CC:reqs/sec COMMENT: GPRINT:RPS:LAST:Requests per Second : %5.1lf (cur) GPRINT:RPS:MAX: : %5.1lf (max) GPRINT:RPS:MIN: : %5.1lf (min) GPRINT:RPS:AVERAGE: : %5.1lf (avg)
The Xymon scripts source code is:
#!/usr/bin/perl -w
#############################################################################
# $Id: mi-lighttpd.pl 21 2009-05-07 19:22:28Z rar $
#############################################################################
use strict;
use File::Slurp;
use LWP::Simple;
use Data::Dumper;
my $port = 80;
my $bbtest = 'lighttpd';
#############################################################################
## BB and related test constants
#############################################################################
use constant CLEAR => 'clear';
use constant GREEN => 'green';
use constant YELLOW => 'yellow';
use constant RED => 'red';
use constant PURPLE => 'purple';
{
#############################################################################
## Setup Variables
#############################################################################
my $DATA = "";
my $color = GREEN;
my $status = $bbtest . " OK";
my $previous_run;
my $current_run;
my $restarted = 0;
my @delta_tests = ( 'total_kbytes', 'total_accesses', 'uptime' );
my @counter_tests = ( 'total_accesses', 'total_kbytes', 'uptime', 'reqpersec' );
my @write_log;
my $backup_log = "$ENV{BBTMP}/$ENV{MACHINE}.lighttpd.data";
my %lighttpd_states = (
'_' => 'awaiting_conn',
'.' => 'connect',
'r' => 'reading_req',
'R' => 'reading_req_post',
's' => 'sending_reply',
'S' => 'sending_reply_end',
'q' => 'request_start',
'Q' => 'request_end',
'W' => 'write',
'h' => 'handle_request',
'C' => 'close',
'E' => 'hard_error',
);
my %error_states = (
'reqpersec' => '100',
'sending_reply' => '100'
);
my %warn_states = (
'reqpersec' => '75',
'sending_reply' => '75'
);
#############################################################################
## Gather previous run data & current data
#############################################################################
# Get Last Status
if ( -e $backup_log ) {
#Split Apart Data
my @data = read_file($backup_log);
if (@data) {
foreach my $line (@data) {
chomp($line);
my ( $key, $value ) = split( /=/, $line, 2 );
$previous_run->{$key} = $value;
}
}
else {
$previous_run = 0;
}
}
my $status_data = get "http://localhost:$port/server-status?auto";
#############################################################################
## Munge the data up to get what we want
#############################################################################
if ( defined($status_data) ) {
my @data = split( /n/, $status_data );
foreach my $line (@data) {
chomp($line);
my ( $key, $value ) = split( /: /, $line );
$key =~ s/ /_/g;
$key = lc($key);
$current_run->{$key} = $value;
}
# Create array of new values to save for our next run
foreach ( keys %{$current_run} ) {
push @write_log, "$_=$current_run->{$_}n";
}
# Calculate Incremental Data
if ($previous_run) {
# We need to check if we restarted here to avoid negitives
if ($current_run->{uptime} > $previous_run->{uptime} ){
foreach (@delta_tests) {
$current_run->{$_} = $current_run->{$_} - $previous_run->{$_};
}
}
else {
$status = $bbtest . " Restarted";
$color = YELLOW;
$restarted = 1;
}
}
# Break out scoreboard data
foreach ( keys %lighttpd_states ) {
$current_run->{ $lighttpd_states{$_} } = 0;
}
foreach ( split( //, $current_run->{scoreboard} ) ) {
$current_run->{ $lighttpd_states{$_} }++;
}
if ( !$restarted ) {
# Get Req/Sec since last check
$current_run->{reqpersec} = sprintf "%.2F", ( $current_run->{total_accesses} / $current_run->{uptime} ) if $current_run->{uptime};
## save our counter tests for the next run incase we
## lighttpd gets restarted we have some non-zero data to send in
foreach (@counter_tests) {
push @write_log, "cur_$_=$current_run->{$_}n";
}
# Check for warning states
foreach ( keys %warn_states ) {
if ( $current_run->{$_} > $warn_states{$_} ) {
$color = YELLOW;
$status = $bbtest . " $_ > $warn_states{$_}";
}
}
# Check for error states
foreach ( keys %error_states ) {
if ( $current_run->{$_} > $error_states{$_} ) {
$color = RED;
$status = $bbtest . " $_ > $error_states{$_}";
}
}
}
else {
## So we restarted, and we don't want to send nothing
## and we don't want to send negitives on calculated tests
## since we saved them last run for this purpose, we'll send in
## our last run stats to keep from having huge drops in the
## graphs.
foreach (@counter_tests) {
$current_run->{$_} = sprintf "%.2F", $previous_run->{ "cur_".$_ };
}
}
# Delete Some Unwanted Data
delete $current_run->{scoreboard};
delete $current_run->{uptime};
# Create Hobbit Data
foreach ( sort keys %{$current_run} ) {
$DATA .= "$_:$current_run->{$_}n";
}
# Actually Write last run file
write_file( $backup_log, @write_log );
}
else {
$status = $bbtest . " unable to get server-status";
$color = CLEAR;
}
#############################################################################
## Give data to hobbit
#############################################################################
# hobbit formatted output
my $report_date = `/bin/date`;
chomp($report_date);
## DEV DEBUG
#print "$ENV{BB} $ENV{BBDISP} 'status apollo,xipnet,net.$bbtest $color $report_date - $statusnn$DATA'n";
system("$ENV{BB} $ENV{BBDISP} 'status apollo,xipnet,net.$bbtest $color $report_date - $statusnn$DATA'n");
}