Public/Get-CitrixAppUsagePeak.ps1

<#
.SYNOPSIS
Retrieves peak application usage data from a Citrix Delivery Controller using the OData API.
 
.DESCRIPTION
The Get-CitrixAppUsagePeak function queries application activity data from a specified Citrix Delivery Controller. It analyzes the peak concurrent usage per application within a defined date range and returns the highest usage count along with the corresponding date.
 
The function uses Citrix Monitor OData endpoints for `ApplicationActivitySummaries` and `Applications`, and maps application IDs to their published names. The results are grouped, analyzed, and returned sorted by peak usage in descending order.
 
.PARAMETER DeliveryController
The name or FQDN of the Citrix Delivery Controller to query. This parameter is mandatory.
 
.PARAMETER StartDate
The beginning date of the range to analyze application activity. Defaults to 30 days prior to today.
 
.PARAMETER EndDate
The end date of the range to analyze application activity. Defaults to today.
 
.EXAMPLE
# Run a default usage analysis for the past 30 days
Get-CitrixAppUsagePeak -DeliveryController "ddc001"
 
.EXAMPLE
# Analyze usage data for a specific month
Get-CitrixAppUsagePeak -DeliveryController "ddc001" -StartDate "2025-03-01" -EndDate "2025-03-31"
 
.NOTES
Requires access to the Citrix Monitor OData v3 API with appropriate permissions. Uses default credentials for authentication.
#>



function Get-CitrixAppUsagePeak {
    [CmdletBinding()]
    [OutputType('PSCustomObject')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]$DeliveryController,

        [Parameter()]
        [DateTime]$StartDate = (Get-Date).AddDays(-30).Date,

        [Parameter()]
        [DateTime]$EndDate = (Get-Date).Date
    )

    # Helper function for REST queries
    function Invoke-CitrixODataQuery {
        param ($Uri)
        try {
            return Invoke-RestMethod -Uri $Uri -UseDefaultCredentials -ErrorAction Stop
        } catch {
            Write-LogEntry -Message "Failed to retrieve: $Uri"
            return $null
        }
    }

    $baseUri = "http://$DeliveryController/Citrix/Monitor/OData/v3/Data"

    $dateFilter = "`$filter=(SummaryDate ge DateTime'$($StartDate.ToString("s"))') and (SummaryDate le DateTime'$($EndDate.ToString("s"))')"

    # REST URIs
    $activityUri = "$baseUri/ApplicationActivitySummaries?`$format=json&$dateFilter"
    $appsUri = "$baseUri/Applications?`$format=json&`$select=Id,PublishedName"

    # Fetch data
    $activityData = Invoke-CitrixODataQuery -Uri $activityUri
    $appsData = Invoke-CitrixODataQuery -Uri $appsUri

    if (-not $activityData -or -not $appsData) {
        Write-LogEntry -Message "No data retrieved from $DeliveryController"
        return
    }

    # Map ApplicationId -> PublishedName using a hashtable for fast lookup
    $appLookup = @{}
    foreach ($app in $appsData.value) {
        $appLookup[$app.Id] = $app.PublishedName
    }

    $deployedState = if ($DeliveryController -match "VAUS") { "DR" } else { "Prod" }

    # Process and group results
    $result = $activityData.value | ForEach-Object {
        [PSCustomObject]@{
            AppName                    = $appLookup[$_.ApplicationId]
            ModifiedDate               = (Get-Date $_.ModifiedDate -Format 'MM/dd/yyyy')
            PeakConcurrentInstanceCount = $_.PeakConcurrentInstanceCount
        }
    } | Group-Object AppName | ForEach-Object {
        $maxPeak = ($_.Group | Measure-Object -Property PeakConcurrentInstanceCount -Maximum).Maximum
        $maxDate = ($_.Group | Where-Object { $_.PeakConcurrentInstanceCount -eq $maxPeak } | Select-Object -ExpandProperty ModifiedDate -First 1)

        [PSCustomObject]@{
            AppName                 = $_.Name
            MaxPeakConcurrent      = $maxPeak
            DateForMaxPeakConcurrent = $maxDate
            Deployed               = $deployedState
        }
    }

    return $result | Sort-Object -Property MaxPeakConcurrent -Descending
}