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'
using module '..\..\modules\FeedProcessor\Auditlog\Message.psm1'

function Measure-Performance{
    [Alias('mspf')]
    param(
        # input message for analysis
        [Parameter(ValueFromPipeline=$true, Mandatory=$true)]
        [Message] $message,
        # 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.
        [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
    )

    BEGIN {
        $thresholdLines = 0; $analyzedLines = 0

        try {
            $maxBlocks = [int32](10000/$intervalBlock)
        }
        catch {
            $maxBlocks = 200
        }
        $threshold = @()
        $allTimes = @()
        for ($i=0; $i -le $maxBlocks; $i++) { $threshold += 0 }
    }
    PROCESS {

        if (-not $targetType) { $targetType = $message.sourceType }

        if ((-not $include -or ($include -and $message.changeType -in $include)) -and -not ($exclude -and $message.changeType -in $exclude)) {
            $message.CalculatePerformance($targetType, $showAbsoluteNumbers, $ignoreProviderTimestamp)

            if ((($aboveProcessingTime -and $message.performance.total -ge $aboveProcessingTime) -or (-not $aboveProcessingTime)) -and `
                    (($bellowProcessingTime -and $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($message.producer) -in ([SOURCE]::sb, [SOURCE]::core)))){

                    $allTimes += $message.performance.total
                    $analyzedLines += 1
                    # classify processing times in correct threshold group
                    if ($summary){
                        $i = ([Math]::floor($message.performance.total/$intervalBlock))
                        $threshold[[Math]::min($i, $maxBlocks)] += 1
                    }
                    else {
                        Write-Output $message.PerformanceToOutput()
                        $thresholdLines += 1
                    }
                }
            }
        }
    }
    END{
        if ($analyzedLines -gt 0){
            if ($summary){
                Write-Output "Summary of total $analyzedLines analyzed lines:"
                $percentile = [Config]::Load().percentile

                Write-Output ([StringHelper]::groupValueByBlocks($threshold, $intervalBlock, $percentageThreshold, $percentile, $true))

                $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."
        }
    }
}