Public/Get-CitrixUserSessionLatency.ps1

<#
.SYNOPSIS
    Retrieves latency information for sessions in a specified Citrix environment.
 
.DESCRIPTION
    This function connects to a specified computer to retrieve latency metrics for Citrix sessions.
    It can filter by computer name and optionally by user name, providing detailed latency statistics
    and session information including the client IP address.
 
.PARAMETER AdminAddress
    The address of the Citrix Administration server.
 
.PARAMETER ComputerName
    The name of the computer from which to retrieve latency data. Defaults to the local computer.
 
.PARAMETER UserName
    The username to filter the latency data. If not specified, data for all users will be retrieved.
 
.EXAMPLE
    Get-CitrixUserSessionLatency -AdminAddress "citrixserver.local" -ComputerName "VDIHost01" -UserName "Domain\JohnDoe"
    Retrieves latency information for sessions belonging to JohnDoe on the computer VDIHost01 managed by citrixserver.local.
 
.NOTES
    This script requires Citrix XenDesktop SDK and permissions to query Citrix and system performance data.
#>


Function Get-CitrixUserSessionLatency {
    [CmdletBinding()]
    [OutputType([System.Management.Automation.PSCustomObject])]
    Param (
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [string]$AdminAddress,

        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [string]$ComputerName = $env:COMPUTERNAME,

        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [string]$UserName
    )

    Process {
        try {
            if (-not (Test-Connection -ComputerName $ComputerName -Count 1 -Quiet)) {
                Write-Warning "Connection to $ComputerName failed."
                return
            }

            $osInfo = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $ComputerName
            $isServerOS = $osInfo.ProductType -ne 1

            $counters = "\ICA Session(*)\Latency - Last Recorded"
            [int]$MStoBeConsideredLatent = 300
            $metrics = Get-Counter -ComputerName $ComputerName -Counter $counters -ErrorAction Stop

            foreach ($metric in $metrics.CounterSamples) {
                $newName = $metric.InstanceName -replace '.*\(', '' -replace '\)', ''
                $sessionCriteria = if ($isServerOS) {"Active|Disconnected|Application"} else {"Active|Disconnected|Desktop"}

                $xdsessions = Get-BrokerSession -AdminAddress $AdminAddress -MaxRecordCount ([Int32]::MaxValue) |
                              Where-Object {
                                  $_.HostedMachineName -eq $ComputerName -and
                                  $_.SessionState -match $sessionCriteria -and
                                  (!$UserName -or $_.UserName -eq $UserName)
                              }

                foreach ($xdsession in $xdsessions) {
                    [PSCustomObject]@{
                        LatencyinMS = $metric.CookedValue
                        DateTime    = $metric.Timestamp
                        User        = $newName
                        Computer    = $ComputerName
                        ClientIP    = $xdsession.ClientAddress
                    } | ForEach-Object {
                        if ($_.LatencyinMS -ge 10 -and $_.LatencyinMS -lt $MStoBeConsideredLatent) {
                            Write-Verbose "Current Latency is significant but below the critical threshold."
                            $_
                        }
                        elseif ($_.LatencyinMS -ge $MStoBeConsideredLatent) {
                            Write-Output "Critical latency detected: Current Latency is greater than $MStoBeConsideredLatent ms."
                            $_
                        }
                    }
                }
            }
        } catch {
            Write-Error "An error occurred while retrieving latency data: $_"
        }
    }
}