#!/usr/bin/perl

=head1 INSTALLATION

	This plugin does http requests to specified URLs and takes the response time.
	Use it to monitor remote sites.
	
	LWP::UserAgent and Time::HiRes are required

=head1 CONFIGURATION

  [http_request_time]
  env.url1  http://127.0.0.1/1
  env.url2  http://127.0.0.1/2
  env.url3  http://www.example.com
  env.url3_name  some_munin_internal_name
  env.url3_label Some random page on our website
  env.url3_proxy http://firewall:3128
  env.timeout 3

Timeout is the timeout of any HTTP request. Tune to avoid a complete
timeout of the plugin.

=head1 MAGIC MARKERS

  #%# family=auto
  #%# capabilities=autoconf

=head1 LICENSE

GPLv2

=cut

use strict;
use warnings;
use Munin::Plugin;
use Time::HiRes qw(gettimeofday tv_interval);
my $ret = undef;

need_multigraph();

sub clean {
	my $surl=shift;
	$surl=~s/^https?:\/\///;
	$surl=~s|%[\w\d]|_|g;
	$surl=~s|[^\w\d_]|_|g;
	$surl=~s|_*$||g;
	$surl=~s|^_*||g;
	return $surl;
};

if (! eval "require LWP::UserAgent;")
{
	$ret = "LWP::UserAgent not found";
        if ( ! defined $ARGV[0] ) {
                die $ret;
        }
}

my %URLS;

# timeout in seconds for requests
# slightly lower than the default global timeout (5 seconds)
my $timeout = $ENV{'timeout'} || 3;

for (my $i = 1; $ENV{"url$i"}; $i++)
{
	my $url   = $ENV{"url$i"};
	my $proxy = $ENV{"url${i}_proxy"};
	my $name  = $ENV{"url${i}_name"}  || clean($url);
	my $label = $ENV{"url${i}_label"} || $url;
	
	$URLS{$name}={
		url=>$url,
		proxy=>$proxy,
		label=>$label,
		time=>'U'
	};
}

if ( defined $ARGV[0] and $ARGV[0] eq "autoconf" )
{
	if ($ret)
	{
		print "no ($ret)\n";
		exit 0;
	}

	my $ua = LWP::UserAgent->new(timeout => $timeout);

	foreach my $url (keys %URLS) {
		my $response = $ua->request(HTTP::Request->new('GET',$url));
                if ($response->is_success) {
                	next;
                }
                else {
                        print "no (URL $url: ". $response->message .")\n";
                        exit 0;
                }
	}
	print "yes\n";
	exit 0;
}

if ( defined $ARGV[0] and $ARGV[0] eq "config" )
{
	# master graph
	print "multigraph http_request_time\n";
	print "graph_title HTTP(S) Request response times\n";
	print "graph_args --base 1000\n";
	print "graph_vlabel response time in ms\n";
	print "graph_category other\n";

	my @go;
	foreach my $name (keys %URLS) {
		my $url = $URLS{$name};
		print "$name.label $$url{'label'}\n";
		print "$name.info The response time of a single request\n";
		print "$name.min 0\n";
		print "$name.draw LINE1\n";
		push(@go, $name);
	}

	# multigraphs

	foreach my $name (keys %URLS) {
		my $url = $URLS{$name};
		print "\nmultigraph http_request_time.$name\n";
		print "graph_title $$url{'url'}\n";
		print "graph_args --base 1000\n";
		print "graph_vlabel response time in ms\n";
		print "graph_category other\n";
		print "$name.label $$url{'label'}\n";
		print "$name.info The response time of a single request\n";
		print "$name.min 0\n";
		print "$name.draw LINE1\n";
	}

	exit 0;
}

my $ua = LWP::UserAgent->new(timeout => $timeout);
foreach my $name (keys %URLS) {
	my $url = $URLS{$name};

	if ($url->{proxy}) {
		$ua->proxy(['http', 'ftp'], $url->{proxy});
	}
	else {
		$ua->proxy(['http', 'ftp'], undef);
	}

	# warm up
	my $response = $ua->request(HTTP::Request->new('GET',$$url{'url'}));

	# timed run
	my $t1=[gettimeofday];
	$response = $ua->request(HTTP::Request->new('GET',$$url{'url'}));
	my $t2=[gettimeofday];

	if ($response->is_success) {
		$$url{'time'}=sprintf("%d",tv_interval($t1,$t2)*1000);
	};		
};

print("multigraph http_request_time\n");
foreach my $name (keys %URLS) {
	my $url = $URLS{$name};
	print("$name.value $$url{'time'}\n");
}

foreach my $name (keys %URLS) {
	my $url = $URLS{$name};
	print("\nmultigraph http_request_time.$name\n");
	print("$name.value $$url{'time'}\n");
}

# vim:syntax=perl
