Converting performance data to reports

In my previous article about collecting performance data from remote-servers we looked at a script for extracting perf-data from multiple servers.

This script is used to convert the extracted CSV file into an HTML report.


# define the first field in the file - this will be the x-axis for most graphs
# and can also be eliminated from the report
$timeField = "(PDH-CSV 4.0) (GMT Standard Time)(0)"

$testId = 201611301041
$inFilePath = "C:\jmeter\results\$testId"

# add some start / end filters
$startDate = Get-Date "2016-11-30 10:30:00"
$endDate = Get-Date "2016-11-30 10:45:00"

$headers = @()
$counterNames = @()
$dataSet = @()

# Open the PerfMon CSV file
$csv = Import-Csv $inFilePath\$testId.csv

# extract a list of the headers
$headers = $csv | Get-Member -MemberType NoteProperty | select name

# for each of the headers extract a unique list of the servers being monitored
ForEach($header in ($headers | Where { $_ -notlike "*network*" }))
$counterName = ($header -split "\\\\")[2].Trim('}')
if (-not $counterNames.Contains($counterName)){
$counterNames += $counterName

$counterNames = @("system\processor queue length",
".net clr exceptions(_global_)\# of exceps thrown / sec")

# date/values "[date, value]" for use on the Google Chart

# reuse the date strings if they haven't changed
[datetime]$previousTime = Get-Date;

# the date must be a JavaScript date, so some manipulation will be required.
$jsDate = ""

# loop through the CSV file and create a list of counters and
$csv | Foreach-Object {
foreach ($property in $_.PSObject.Properties)
$counterDate = [datetime]::ParseExact($_.$timeField, "MM/dd/yyyy HH:mm:ss.fff", $null)

# if the record is before or after the threshold, ignore the data
if ($counterDate -lt $startDate -or $counterDate -gt $endDate){
"This row is out of the date range being processed."

# if the time hasn't changed since the last time, we don't need to process this again
if ($previousTime -ne $counterDate){
$jsDate = Get-Date $counterDate -format "yyyy,MM,dd,HH,mm,ss"
$previousTime = $counterDate
# if the value is empty, or property name is the same as the time field, don't include
if (-not [String]::IsNullOrWhiteSpace($property.Value) -and $propertyName -ne $timeField) {

$objDataRow = New-Object System.Object
$objDataRow | Add-Member -type NoteProperty -name Name -value $property.Name
$objDataRow | Add-Member -type NoteProperty -name Value -value ("[new Date({0}),{1}]" -f $jsDate, $property.Value)
$dataSet += $objDataRow

$objDataRow.Name.Substring(0,30) + ": " + $objDataRow.Value

[string] $headerName = ""

# build html
$html = "<html>`n"
$html += "<head>`n"
$html += "<script type='text/javascript' src=''></script>`n"
$html += "
<script type='text/javascript'>
// Load the Visualization API and the corechart package.
google.charts.load('current', {'packages':['corechart']});

$html += "</head>`n"
$html += "<body>`n"

$html += "<h1>Performance report</h1>`n"

ForEach($counterName in $counterNames){

if ($counterName.Length -gt 0){
$html += "<h2>{0}</h2>`n" -f $counterName

# tidy up the name, so it can be used as a unique JS reference
$jsCounterName = $counterName.Replace(" ","").Replace("/","").Replace("\","").Replace("#","").Replace(":","").Replace("(","").Replace(")","").Replace("%","").Replace("[","").Replace("]","").Replace(".","").Replace("-","").Replace("_","").Replace("{","").Replace("}","")

# loop through each header to find the like-for-like counters
ForEach($header in $headers | Where { $_.Name -like "*$counterName*"}) {

# if there aren't any records, don't output it
if (($dataSet | Where { $_.Name -eq $header.Name } | Measure ) -eq 0){

$chartData = [string]::Join(",",($dataSet | Where { $_.Name -eq $header.Name } | Select -ExpandProperty Value ))

$html += ("<div id='{0}_chart_div'></div>`n" -f $jsCounterName)

$html += "<script type='text/javascript'>
// Set a callback to run when the Google Visualization API is loaded.
     google.charts.setOnLoadCallback(drawChart" + $jsCounterName + ");

     function drawChart" + $jsCounterName + "() {
             // Create the data table.
             var data = new google.visualization.DataTable();
             data.addColumn('date', 'Time');

             data.addRows([" + $chartData + "]);

             data.addRows([" + $chartData + "]);

             // Set chart options
             var options = {'title':title,

             // Instantiate and draw our chart, passing in some options.
             var chart = new google.visualization.LineChart(document.getElementById('" + $jsCounterName + "_chart_div'));
             chart.draw(data, options);
$html += "<hr>`n"

$html += "</body>`n"
$html += "</html>`n"

$html | out-file -force -Encoding ascii "$inFilePath\$testId.html"

This will extract data from the saved CSV file, and create an HTML file using the rich Google Chart API to generate the graphs.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

A Website.

Up ↑

%d bloggers like this: