Data-Parser.ps1
## # Parse-Files # ----------- # This function iterates through the files of a specified directory, parsing each file and # exctracting relevant data from each file. Data is then packaged into an array of objects, # one object per file, and returned along with some meta data. # # Parameters # ---------- # DirName (String) - Path to the directory whose files are to be parsed # Tool (String) - Name of the tool whose data is being parsed (NTTTCP, LATTE, CTStraffic, etc.) # # Return # ------ # HashTable - Object containing an array of dataEntry objects and meta data # ## function Parse-Files { param ( [Parameter(Mandatory=$true)] [string]$DirName, [Parameter()] [string] $Tool ) $files = Get-ChildItem $DirName if ($Tool -eq "NTTTCP") { [Array] $dataEntries = @() foreach ($file in $files) { $fileName = $file.FullName $dataEntry = Parse-NTTTCP -FileName $fileName if ($dataEntry) { $dataEntries += ,$dataEntry } } $rawData = @{ "meta" = @{ "units" = @{ "cycles" = "cycles/byte" "throughput" = "Gb/s" } "goal" = @{ "throughput" = "increase" "cycles" = "decrease" } "format" = @{ "throughput" = "0.00" "cycles" = "0.00" "% change" = "+#.0%;-#.0%;0.0%" } "noTable" = [Array] @("filename", "sessions", "bufferLen", "bufferCount") } "data" = $dataEntries } return $rawData } elseif ($Tool -eq "LATTE") { [Array] $dataEntries = @() foreach ($file in $files) { $fileName = $file.FullName $dataEntry = Parse-LATTE -FileName $fileName $dataEntries += ,$dataEntry } $rawData = @{ "meta" = @{ "units" = @{ "latency" = "us" } "goal" = @{ "latency" = "decrease" } "format" = @{ "latency" = "#.0" "% change" = "+#.0%;-#.0%;0.0%" } "noTable" = [Array]@("filename", "sendMethod", "protocol") } "data" = $dataEntries } return $rawData } elseif ($Tool -eq "CTStraffic") { [Array] $dataEntries = @() foreach ($file in $files) { $fileName = $file.FullName $ErrorActionPreference = "Stop" $dataEntry = Parse-CTStraffic -FileName $fileName if ($dataEntry) { $dataEntries += ,$dataEntry } } $rawData = @{ "meta" = @{ "units" = @{ "throughput" = "Gb" } "goal" = @{ "throughput" = "increase" } "format" = @{ "throughput" = "0.00" "% change" = "+#.0%;-#.0%;0.0%" } "noTable" = [Array]@("filename", "sessions") } "data" = [Array]$dataEntries } return $rawData } } ## # Parse-NTTTCP # ------------ # This function parses a single file containing NTTTCP data in an XML format. Relevant data # is then extracted, packaged into a dataEntry object, and returned. # # Parameters # ---------- # Filename (String) - Path of file to be parsed # # Return # ------ # HashTable - Object containing extracted data # ## function Parse-NTTTCP ([string] $FileName) { if ($FileName.Split(".")[-1] -ne "xml"){ return } [XML]$file = Get-Content $FileName if (-not $file) { Write-Warning "Unable to parse file $FileName" return } [decimal] $cycles = $file.ChildNodes.cycles.'#text' [decimal] $throughput = ([decimal]$file.ChildNodes.throughput[1].'#text') / 1000 # TODO: 1024? [int] $sessions = $file.ChildNodes.parameters.max_active_threads [int] $bufferLen = $file.ChildNodes.bufferLen [int] $bufferCount = $file.ChildNodes.io $dataEntry = @{ "sessions" = $sessions "throughput" = $throughput "cycles" = $cycles "filename" = $FileName "bufferLen" = $bufferLen "bufferCount" = $bufferCount } return $dataEntry } <# .SYNOPSIS Parses CTSTraffic output. .DESCRIPTION This function parses a CTStraffic status log file, generated from the -StatusFilename option. Desired data is collected and returned in a Hashtable. .PARAMETER Filename Path of the status log file to parse. #> function Parse-CTStraffic { param( [String] $Filename ) $data = Get-Content $Filename | ConvertFrom-Csv if (-not ($data | Get-Member -Name "In-Flight")) { Write-Error "'$Filename' is not a valid ctsTraffic status log. Please verify that the log was generated by the -StatusFilename option." return } $throughput = ($data.SendBps | measure -Average).Average / 1GB $maxSessions = ($data."In-Flight" | measure -Max).Max $dataEntry = @{ "sessions" = $maxSessions "throughput" = $throughput "filename" = $Filename } return $dataEntry } ## # Parse-LATTE # ---------- # This function parses a single file containing LATTE data. This function can parse files # containing either raw LATTE data, or a LATTA summary. For raw data, each line contains # a latency sample which is extracted into an array, packaged into a dataEntry # object, and returned. For summary data, the latency histogram and a few other measures # are parsed from the file, packaged into a dataEntry object, and returned. # # Parameters # ---------- # Filename (String) - Path of file to be parsed # # Return # ------ # HashTable - Object containing extracted data # ## function Parse-LATTE ([string] $FileName) { $file = Get-Content $FileName $dataEntry = @{ "filename" = $FileName } $splitline = Remove-EmptyStrings -Arr (([Array]$file)[0]).split(' ') if ($splitline[0] -eq "Protocol") { $histogram = $false foreach ($line in $file) { $splitLine = Remove-EmptyStrings -Arr $line.split(' ') if ($splitLine.Count -eq 0) { continue } if ($splitLine[0] -eq "Protocol") { $dataEntry.protocol = $splitLine[-1] } if ($splitLine[0] -eq "MsgSize") { $dataEntry.msgSize = $splitLine[-1] # Not currently used for anything } if ($splitLine[0] -eq "Interval(usec)") { $dataEntry.latency = [HashTable] @{} $histogram = $true continue } if ($histogram) { $dataEntry.latency.([Int32]$splitLine[0]) = [Int32] $splitLine[-1] } } if (-not $histogram) { Write-Warning "No histogram in file $filename" return } } else { [Array] $latency = @() foreach ($line in $file) { if (-not ($line -match "\d+")) { Write-Warning "Error Parsing file $FileName" return } $latency += ,[int]$line } $dataEntry.latency = $latency $dataEntry.protocol = (($FileName.Split('\'))[-1].Split('.'))[0].ToUpper() } $dataEntry.sendMethod = (($FileName.Split('\'))[-1].Split('.'))[2] return $dataEntry } ## # Remove-EmptyStrings # ------------------- # This function removes all empty strings from the given array # # Parameters # ---------- # Arr (string[]) - Array of strings # # Return # ------ # Array of strings with all empty strings removed # ## function Remove-EmptyStrings ($Arr) { $newArr = [Array] @() foreach ($val in $arr) { if ($val -ne "") { $newArr += $val.Trim() } } return $newArr } |