#!/usr/bin/perl -w
use strict;

use Getopt::Long;
use POSIX;

my ($percentile,$stat,$site_identifier) = validate_options();

my $numbers = [];

my $do_reqtime;

if ($stat eq 'reqtime') {
	$do_reqtime = 1;
}

while (<STDIN>) {

	my $str = $_;

	#Note, this was mainly lifted from /usr/share/ng-tools/perl/AnyData/Format/NGPerfWebLog.pm 

    my(@row) = $str =~
        /^\s*(\S*) (\S*) (\S*) \[([^\]]*)\] "((?:(?:\\\\)*\\"|[^"])*)" (\S*) (\S*)\s*(.*)$/;
    next unless defined $row[0];

    #ELB load checks
    if ($row[5] eq '408' && $row[4] eq '-' && $row[6] eq '-') {
        next;
    }

	if (
		$site_identifier
		&& (
			$row[2] !~ m/([^\/]+)\//
			|| $1 ne $site_identifier
		)
	) {
		next;
	}

    my ($client, $referer, $reqtime,  $bytesin, $bytesout, $ngperfstats, $postargs);
    if ($row[7] =~ /^"((?:(?:\\\\)*\\"|[^"])*)"\s+"((?:(?:\\\\)*\\"|[^"])*)"\s*(.*)$/) {
        # Have client & referer
        $referer = $1;
        $client  = $2; # Agent!

        if ($3 =~ /^(-|\d+)\s+(-|\d+)\s+(-|\d+)\s*(.*)$/) {
            # Have reqtime(apache) bytesin bytesout
            $reqtime  = $1;
            $bytesin  = $2;
            $bytesout = $3;
            if ($4 =~ /^\{([^}]*)\}\s*(.*)$/) {
                $ngperfstats = $1;
            }
        }
    }
    $client   ||= '';
    $referer  ||= '';
    $reqtime  ||= '';
    $bytesin  ||= '';
    $bytesout ||= '';
    $ngperfstats ||= '';
    $postargs ||= '';
    ($row[7],$row[8],$row[9],$row[10],$row[11],$row[12])=($client,$referer,$reqtime,$bytesin,$bytesout,$ngperfstats);

	if ($do_reqtime) {
		if ($reqtime) {
			push $numbers, ($reqtime / 1000000);
		}
	}

}

my @sorted_numbers = sort { $b <=> $a} @$numbers;

my $count = @sorted_numbers;

my $number_to_discard = ceil($count / 100) * (100 - $percentile);

if (exists($sorted_numbers[$number_to_discard])) {
	print $sorted_numbers[$number_to_discard] . "\n";
} else {
	print "0.0\n";
}
exit(0);

sub validate_options {

	my $percentile = 95;
	my $stat = 'reqtime';
	my $site_identifier;
	my $show_help;

	my @valid_stats = ('reqtime');

	if (
		not GetOptions("percentile:s" => \$percentile, "stat:s" => \$stat, 'site-identifier=s' => \$site_identifier, 'help' => \$show_help)
		or $show_help
	) {

		my $FH;

		if ($show_help) {
			$FH = *STDOUT;
		} else {
			$FH = *STDERR;
		}

		print $FH "\n\n";
		print $FH "Usage\n";
		print $FH "cat /var/log/http/access_log | $0 [--number XX (defaults to 95)] [--stat (reqtime) (defaults to reqtime)] [--site-identifier (sitename)] \n\n";
		print $FH "--percentile (int)         : The highest percentile value to output. Eg if you want the 95th percentile of the lowest value, use 5\n";
		print $FH "--stat (string)            : Show the value for this stat. Only supported stats are: " . join(', ',@valid_stats) . "\n";
		print $FH "--site-identifier (string) : The site identifier, eg 'im1' for the 'oca_im1' account\n";
		print $FH "\n\n";

		exit($show_help ? 0 : 1);
	}

	if ($percentile < 1 || $percentile > 99) {
		die("percentile must be between 1 and 99 (inclusive)")
	}

	my $stat_found = 0;

	foreach my $valid_stat(@valid_stats) {
		if ($valid_stat eq $stat) {
			$stat_found = 1;
		}
	}

	if (! $stat_found) {
		die("Invalid stat requested. Supported stats : " . join(', ',@valid_stats));
	}

	return ($percentile,$stat,$site_identifier);
}
