#!/usr/bin/perl
# Author: Andrew Theurer
#
# The purpose of this script is to convert iostat-stdout.txt
# into either (depending on how this script is invoked):
#
#   CSV files and statically generated graphs
#   with embedded javascript, using d3.js libraries
#
# Usage:
#
#   iostat-postprocess <dir>
#
#   dir = directory where iostat-stdout.txt can be found
#
# Note:
#
#   iostat-stdout.txt must be generated from "iostat -N -t -y -x -m <interval>"

use strict;
use warnings;

use lib $ENV{'pbench_lib_dir'};
no lib ".";
use GenData qw(gen_data);

my $dir = shift;

die "Non-default options, skipping post-processing for iostat" if (-f $dir . "/iostat.options");

my $dev;
my %iostat; # For gen_data()
my $timestamp_ms;

# read the iostat-stdout.txt
open(IOSTAT_TXT, $dir . "/iostat-stdout.txt") || die "could not find " . $dir . "/iostat-stdout.txt\n";
while (my $line = <IOSTAT_TXT>) {
	chomp $line;
	# Each sample should start with a time stamp (the -t in iostat).
	# When we find this, update our timestamp for the hash.
	if ( $line =~ /^\d\d\/\d\d\/\d\d(\d\d)?\s\d\d:\d\d:\d\d(\s[AP]M)?/ ) {
		my $timestamp=`date --date="$line" +%s.%N`;
		$timestamp_ms = $timestamp * 1000;
	}
	#     1    2    3     4     5      6      7     8     9      10      11     12       13       14    15    16
	#Device  r/s  w/s rMB/s wMB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq-sz wareq-sz svctm %util
	#sdc    0.00 0.00  0.00  0.00   0.00   0.00  0.00  0.00    0.00    0.00   0.00     0.00     0.00  0.00  0.00
	#
	#                 1            2            3            4            5            6            7            8            9           10           11           12           13           14           15           16
	#                            r/s          w/s        rMB/s        wMB/s       rrqm/s       wrqm/s        %rrqm        %wrqm      r_await      w_await       aqu-sz     rareq-sz     wareq-sz        svctm        %util
	if ( $line =~ /(\S+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)(.*)/ ) {
		$dev = $1;
		my %iops = ( 'Read' => $2, 'Write' => $3 );
		my %mbps = ( 'Read' => $4, 'Write' => $5 );
		my %rqms = ( 'Read' => $6, 'Write' => $7 );
		my %rw_tput_stats = ( 'IOPS' => \%iops, 'MegabytesSec' => \%mbps, 'RequestMergesSec' => \%rqms );
		my %wait_ms = ( 'Read' => $10, 'Write' => $11 );
		my %reqsize_kb = ( 'Read' => $13, 'Write' => $14 );
		my %rw_count_stats = ( 'RequestSizeKB' => \%reqsize_kb, 'RequestWaitMs' => \%wait_ms );
		my %rw_stats = ( 'throughput' => \%rw_tput_stats, 'count' => \%rw_count_stats );
		my %other_count_stats = ( 'QueueSize' => $12, 'Utilization' => $16 );

		# Each data series is for one device (sda).  On some graphs, read and write
		# series are included in to one graph (instead of having one read-ops chart
		# and another write-ops chart), so each series needs "-read" or
		# "-write" appended to keep them distinct.
		$iostat{disk}{"Utilization_percent"}{$dev}{$timestamp_ms} = $other_count_stats{'Utilization'};
		$iostat{disk}{"Throughput_MB_per_sec"}{$dev . "-read"}{$timestamp_ms} = $rw_stats{'throughput'}{'MegabytesSec'}{'Read'};
		$iostat{disk}{"Throughput_MB_per_sec"}{$dev . "-write"}{$timestamp_ms} = $rw_stats{'throughput'}{'MegabytesSec'}{'Write'};
		$iostat{disk}{"Request_Merges_per_sec"}{$dev . "-read"}{$timestamp_ms} = $rw_stats{'throughput'}{'RequestMergesSec'}{'Read'};
		$iostat{disk}{"Request_Merges_per_sec"}{$dev . "-write"}{$timestamp_ms} = $rw_stats{'throughput'}{'RequestMergesSec'}{'Write'};
		$iostat{disk}{"IOPS"}{$dev . "-read"}{$timestamp_ms} = $rw_stats{'throughput'}{'IOPS'}{'Read'};
		$iostat{disk}{"IOPS"}{$dev . "-write"}{$timestamp_ms} = $rw_stats{'throughput'}{'IOPS'}{'Write'};
		$iostat{disk}{"Request_Size_in_512_byte_sectors"}{$dev}{$timestamp_ms} = ($rw_stats{'count'}{'RequestSizeKB'}{'Read'}
			+ $rw_stats{'count'}{'RequestSizeKB'}{'Write'}) * 2;
		$iostat{disk}{"Request_Size_in_kB"}{$dev . "-read"}{$timestamp_ms} = $rw_stats{'count'}{'RequestSizeKB'}{'Read'};
		$iostat{disk}{"Request_Size_in_kB"}{$dev . "-write"}{$timestamp_ms} = $rw_stats{'count'}{'RequestSizeKB'}{'Write'};
		$iostat{disk}{"Queue_Size"}{$dev}{$timestamp_ms} = $other_count_stats{'QueueSize'};
		$iostat{disk}{"Wait_Time_msec"}{$dev . "-read"}{$timestamp_ms} = $rw_stats{'count'}{'RequestWaitMs'}{'Read'};
		$iostat{disk}{"Wait_Time_msec"}{$dev . "-write"}{$timestamp_ms} = $rw_stats{'count'}{'RequestWaitMs'}{'Write'};
	}
}
close(IOSTAT_TXT);
# define the graph types
# if you want something other than lineChart, put it here
my %graph_type;
# threshold for displying a series in a graph
my %graph_threshold;
$graph_threshold{disk}{"Utilization_percent"} = 1;
$graph_threshold{disk}{"Throughput_MB_per_sec"} = 1;
$graph_threshold{disk}{"IOPS"} = 1;
$graph_threshold{disk}{"Wait_Time_msec"} = 0.1;
$graph_threshold{disk}{"Request_Size_in_512_byte_sectors"} = 0.1;
$graph_threshold{disk}{"Request_Size_in_kB"} = 0.1;
$graph_threshold{disk}{"Request_Merges_per_sec"} = 0.1;
$graph_threshold{disk}{"Queue_Size"} = 0.01;
gen_data(\%iostat, \%graph_type, \%graph_threshold, $dir);
