Home > Hobbit / Xymon, Lighty > Monitoring lighttpd in Xymon / Hobbit

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");
}
  1. No comments yet.
  1. No trackbacks yet.