public/Message/Measure-Performance.ps1
using module '..\..\modules\Enums.psm1' using module '..\..\modules\Helper\DateTimeHelper.psm1' using module '..\..\modules\Helper\StringHelper.psm1' using module '..\..\modules\Helper\ObjectHelper.psm1' using module '..\..\modules\Session.psd1' function Measure-Performance{ [Alias('mspf')] param( # Audit log source file from where the messages will be loaded. [Parameter(Mandatory=$true)] [SOURCE] $source, # Which layer we should measure by its performance as total result. Default is the source layer. [SOURCE_TYPE]$targetType, # Referent message time taken as baseline from where the messages will be start analyzing. [string] $referentTime, # Timeframe in which the messages will be analyzed after the referent time. [string]$timeSpan, # Filter messages which total time in milliseconds is above this value. [int32] $aboveProcessingTime, # Filter messages which total time in milliseconds is bellow this value. Typically used in a combination with aboveProcessingTime. [int32] $bellowProcessingTime, # List of excluding message types of the analysis. Default is none message. [string[]] $exclude = @(), # List of including message types of the analysis. Default is All messages. [string[]] $include = $null, # If we would like to provide general summary of the listed messages, this switch should be provide, otherwise not. [switch] $summary = $false, # In case of summarized report, we might provide analyzed block in milliseconds in which messages will be categorized. [int32] $intervalBlock = 500, # To avoid long list of grouped results, in case of summarized report and lower interval blocks in time, this could optimize # the display of the displayed groups percentage value to not be displayed if it is under the threshold. [int32] $percentageThreshold = 5, # calculate absolute differences between the each hop [switch] $showAbsoluteNumbers, # ignore the provider timestamp in the calculation, i.e. take the timestamp when it was received on the adapter [switch] $ignoreProviderTimestamp ) #region Init if ([Session]::activeSessions.Count -eq 0){ Write-Error 'There is no active session. Import audit logs before they are analyzed.' return } $afterDateTime, $beforeDateTime = [DateTimeHelper]::getAfterBefore($referentTime, $timeSpan) if ($timeSpan -and -not $referentTime){ $referentTime = (now)} $logFile = [Session]::getCurrent().auditLogFile $processor = [ProcessorFactory]::getBySource($source) # if there is no target specified, analyze the source if (-not $targetType) { $targetType=$processor.sourceType } $totalLines = $logFile.AssignFile($source) $thresholdLines = 0; $analyzedLines = 0; $count = 0 try { $maxBlocks = [int32](10000/$intervalBlock) } catch { $maxBlocks = 200 } $threshold = @() $allTimes = @() # initialize all thresholds for ($i=0; $i -le $maxBlocks; $i++) { $threshold+=0 } if($referentTime) { $count = $logFile.Seek($afterDateTime) } else { $count = 0 } #endregion Write-Output "Loading $source messages ($totalLines lines)..." while (-not $logFile.EOF()) { $line = $logFile.ReadLine() if ($line -and $line.created_at -lt $beforeDateTime){ $processor.ProcessMessage($line) if ((-not $include -or ($include -and $processor.message.changeType -in $include)) -and -not ($exclude -and $processor.message.changeType -in $exclude)) { $processor.message.CalculatePerformance($targetType, $showAbsoluteNumbers, $ignoreProviderTimestamp) if ((($aboveProcessingTime -and $processor.message.performance.total -ge $aboveProcessingTime) -or (-not $aboveProcessingTime)) -and ` (($bellowProcessingTime -and $processor.message.performance.total -le $bellowProcessingTime) -or (-not $bellowProcessingTime))){ # list all messages based on the source-target relationship if (($targetType -in ([SOURCE_TYPE]::backend, [SOURCE_TYPE]::feedService)) -or ` ($targetType -in ([SOURCE_TYPE]::adapter, [SOURCE_TYPE]::provider) -and ` -not ([ProcessorFactory]::getSourceByProducer($processor.message.producer) -in ([SOURCE]::sb, [SOURCE]::core)))){ $allTimes += $processor.message.performance.total $analyzedLines += 1 # classify processing times in correct threshold group if ($summary){ $i = ([Math]::floor($processor.message.performance.total/$intervalBlock)) if ($i -ge $maxBlocks) { $threshold[$maxBlocks] += 1 } else { $threshold[$i] += 1 } } else { Write-Output $processor.message.PerformanceToOutput() $thresholdLines += 1 } } } } } $count++ $percentage = 100 * $count / $totalLines Write-Progress -Activity "Calculating processing times..." -PercentComplete $percentage } Write-Progress -Activity "Calculating processing times..." -Completed if ($analyzedLines -gt 0){ if ($summary){ Write-Output "Summary of total $analyzedLines analyzed lines:" $percentile = [Session]::getCurrent().config.percentile Write-Output ([StringHelper]::groupValueByBlocks($threshold, $intervalBlock, $percentageThreshold, $percentile)) $sortedAllTimes = ($allTimes | Sort-Object) $printLines = [ordered]@{} foreach ($i in $percentile) { $array = $sortedAllTimes | Select-Object -First $([Math]::Floor($i * $analyzedLines)) $average = ($array | Measure-Object -Average).Average $median = [StringHelper]::getMedian($array) $line = @(("{0}th" -f ($i * 100)), ([DateTimeHelper]::FormatMilliseconds($sortedAllTimes[$([Math]::Floor($i * $analyzedLines - 1))])), ([DateTimeHelper]::FormatMilliseconds("{0:N0}" -f $average)), ([DateTimeHelper]::FormatMilliseconds("{0:N0}" -f $median))) $printLines.Add($i, $line) } Write-Table -title 'Percentile analysis:' -columns @('percentile', 'time', 'average', 'median') -values $printLines } else { Write-Output ("Total {0} out of {1} ({2:P1}) were processed above {3}." ` -f @($thresholdLines, $analyzedLines, ($thresholdLines/$analyzedLines), ([DateTimeHelper]::FormatMilliseconds($aboveProcessingTime)))) } } else { Write-Output "No lines for analysis." } } |