#!/usr/bin/env perl
#
# FILE:
# sumstats
#
# FUNCTION:
# compute various averages from multiuser report files.
#
# USAGE:
# sumstats reports/*
# or
# cat * | sumstats
#
# HISTORY:
# Written Linas Vepstas May 1998
#
# --------------------------------------------------------
# --------------------------------------------------------

# add a search path to find "timelocal.pl" and other required 
# bits and bytes on various oddly-installed machines.
# This is a hack, as the sysadmin really should install correctly, 
# but for now, this will hold water.
push (@INC, "/usr/local/lib/perl5/5.00501");
($inky=$0) =~ s/sumstats//;
push (@INC, $inky);

require "pagestats.pl";

# --------------------------------------------------------
# --------------------------------------------------------
# --------------------------------------------------------
# main


# print usage
if (0 > $#ARGV) {
	print "Usage: \n";
	print "$0 [<client_stats_file> [...]]\n";
	print "\n";
	print "\tCompute summary statistics from several input files.\n";
	print "\tThe input files are assumed to be report files generated\n";
	print "\tby the webclient tool. The output file generated is very\n";
	print "\tsimilar in format to the input, but contains data that is\n";
	print "\tthe summary of all of the input files put together.\n";
	print "\tSome additional session statistics are printed.\n";
	die "\n";
}

# read the list of urls
&geturlist;

# print the url list
for ($i=0; $i<$numurls; $i++) {
	print "Info: $i $method[$i] $url[$i] \n";
}

if (0 >= $numurls) {
	die "Error: unable to read the list of URL's from the report files";
}
print ("-----------------------------------\n");

# look for these statistics
$statname[0] = "first_data_response_time";
$statname[1] = "response_times";
$statname[2] = " net_delay";
$statname[3] = " ssl_ovhd";
$statname[4] = "html_response_times";
$statname[5] = " html_net_delay";
$statname[6] = " html_ssl_ovhd";
$statname[7] = "connect_times";
$statname[8] = " tcp_connect_times";
$statname[9] = " ssl_connect_ovhd";
$statname[10] = " ssl_net_delay_connect";
$statname[11] = "header_delays";
$statname[12] = " ssl_header_ovhd";
$statname[13] = " ssl_net_delay_header";
$statname[14] = "transfer_times";
$statname[15] = " ssl_transfer_ovhd";
$statname[16] = " ssl_net_delay_transfer";
$statname[17] = "think_time";
$statname[18] = "request_time";

# get the statistics
&getstats;
print "\n\n";

# compute the mean and the stddev
foreach $s (@statname) {
	foreach $j (@titles) {
		$cnt = $nobs {$s, $j };
		# if ssl is turned off, then the nobs will be zero
		# for some of the stats.  This will lead to a divide by zero...
		if (0 < $cnt) {
			$avgtime {$s, $j} = $meantime {$s, $j } / $cnt;
			$avg = $avgtime {$s, $j };
			$stdev = $msqtime {$s, $j } / $cnt; 
			$stdev -= $avg * $avg;
			# due to round-off errors in the printed figures, 
			# the computed mean-square can go negative.  
			# In that case, clamp it to zero.
			if (0 > $stdev) { $stdev = 0; }
			$stdevtime {$s, $j } = sqrt ( $stdev );
		}
	}
}

#
# now round everything to milliseconds
#
foreach $s (@statname) {
	foreach $j (@titles) {
		$avgtime {$s, $j }   = &round ($avgtime {$s, $j }, 1000);
		$stdevtime {$s, $j } = &round ($stdevtime {$s, $j }, 1000);
		$mintime {$s, $j }   = &round ($mintime {$s, $j }, 1000);
		$maxtime {$s, $j }   = &round ($maxtime {$s, $j }, 1000);
	}
}

foreach $j (@titles) {
	if ($j =~ /Statistics Summary for request:/) {
		print "$j \n";
		@words = split (/:/, $j);
		$m = $words[1];
		print "$m: $method[$m] $url[$m] \n";
	} 
	elsif ($j =~ /Statistics Summary for Requests/) {
		print "*******************************************************\n";
		print "$j \n";
		print "*******************************************************\n";
		@words = split (/ /, $j);
		foreach $m ($words[4] .. $words[6]) {
			print "$m: $method[$m] $url[$m] \n";
		}
	} else 
	{
		print "*******************************************************\n";
		print "$j \n";
		print "*******************************************************\n";
	}
	print "\n";
	print 
"    request                avg       stddev      nobs       min        max\n";
	print 
"----------------------   -------     ------     ------     ------     -----\n";

format STDOUT=
@<<<<<<<<<<<<<<<<<<<<<  @###.###   @###.###     @####   @###.###   @###.###
$s, $avgtime {$s, $j},  $stdevtime {$s, $j}, $nobs {$s, $j}, $mintime {$s, $j}, $maxtime {$s, $j}
.
	foreach $s (@statname) {
		$cnt = $nobs {$s, $j };
		# if ssl is turned off, then the nobs will be zero
		# for the ssl-related stats. Simply don't print these.
		if (0 < $cnt) {
			write STDOUT;
		}
	}
	print "\n";
}


# ------------------------------------------------
# ------------------------------------------------
# compute the per-url response times and throughput

$totalnobs = 0;
$activetime = 0;
$stddev = 0;
$s = "response_times";

# only the URL's will have a lower-case "request" in the section title
foreach $j (@titles) {
	if ($j =~ /Statistics Summary for request:/) {
		$totalnobs += $nobs{$s, $j};
		$activetime += $meantime{$s, $j};
		$stddev += $msqtime {$s, $j};
	}
}

$stddev /= $totalnobs;
$meanie = $activetime / $totalnobs;
$stddev -= $meanie * $meanie ;
$stddev = sqrt ($stddev);

$timeperclient = $activetime / $numfiles;
$urlsperclient = $totalnobs / $numfiles;
$resp = $activetime / $totalnobs;

# get the average elapsed time
$elapsedtime = $total_elapsed_time / $numfiles;
$throughput = $totalnobs / $elapsedtime;

print "\n\n";
print "Throughput: $throughput URL's per second\n";
print "Latency: Seconds per URL: $resp +/- $stddev \n";
print "   ($totalnobs urls fetched by $numfiles clients) \n";
print "   ($urlsperclient urls per client fetched in $elapsedtime seconds)\n";
print "\n";

# ------------------------------------------------
# ------------------------------------------------
# compute the per-page response times and throughput

$totalnobs = 0;
$activetime = 0;
$stddev = 0;
$s = "response_times";

foreach $j (@titles) {
	if ($j =~ /Statistics Summary for Requests/) {
		$totalnobs += $nobs{$s, $j};
		$activetime += $meantime{$s, $j};
		$stddev += $msqtime {$s, $j};
	}
}

$stddev /= $totalnobs;
$meanie = $activetime / $totalnobs;
$stddev -= $meanie * $meanie ;
$stddev = sqrt ($stddev);

$timeperclient = $activetime / $numfiles;
$urlsperclient = $totalnobs / $numfiles;
$resp = $activetime / $totalnobs;

$throughput = $totalnobs / $elapsedtime;

print "\n\n";
print "Throughput: $throughput Pages per second\n";
print "Latency: Seconds per Page: $resp +/- $stddev \n";
print "   ($totalnobs Pages fetched by $numfiles clients) \n";
print "   ($urlsperclient Pages per client fetched in $elapsedtime seconds)\n";
print "\n";

#############################################################

$totalnobs = 0;
$thinky = 0;
$s = "think_time";

foreach $j (@titles) {
	if ($j =~ /Statistics Summary for Requests/) {
		$totalnobs += $nobs{$s, $j};
		$thinky += $meantime{$s, $j};
	}
}

$think_mean = $thinky / $totalnobs;

print "Average measured think time = $think_mean seconds\n";
print "\n";

# ===================== end of file ========================
