Private/Invoke-InfraPulseMemoryCheck.ps1
|
function Invoke-InfraPulseMemoryCheck { [CmdletBinding()] param( [Parameter(Mandatory)] [psobject]$Context, [Parameter(Mandatory)] [System.Collections.IDictionary]$Settings ) $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() $scriptBlock = { if ($env:OS -ne 'Windows_NT') { throw 'The Memory check requires a Windows target.' } if (Get-Command -Name Get-CimInstance -ErrorAction SilentlyContinue) { $operatingSystem = Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction Stop } else { $operatingSystem = Get-WmiObject -Class Win32_OperatingSystem -ErrorAction Stop } $totalBytes = [double]$operatingSystem.TotalVisibleMemorySize * 1KB $availableBytes = [double]$operatingSystem.FreePhysicalMemory * 1KB $availablePercent = if ($totalBytes -gt 0) { ($availableBytes / $totalBytes) * 100 } else { 0 } # Commit charge: a host can suffocate at its commit limit while # physical memory still looks fine. $commitLimitBytes = [double]$operatingSystem.TotalVirtualMemorySize * 1KB $commitFreeBytes = [double]$operatingSystem.FreeVirtualMemory * 1KB $commitUsedPercent = if ($commitLimitBytes -gt 0) { (($commitLimitBytes - $commitFreeBytes) / $commitLimitBytes) * 100 } else { $null } $pageFileAllocatedMB = $null $pageFileUsedMB = $null try { $pageFiles = if (Get-Command -Name Get-CimInstance -ErrorAction SilentlyContinue) { @(Get-CimInstance -ClassName Win32_PageFileUsage -ErrorAction Stop) } else { @(Get-WmiObject -Class Win32_PageFileUsage -ErrorAction Stop) } if ($pageFiles.Count -gt 0) { $pageFileAllocatedMB = [double](@($pageFiles | Measure-Object -Property AllocatedBaseSize -Sum).Sum) $pageFileUsedMB = [double](@($pageFiles | Measure-Object -Property CurrentUsage -Sum).Sum) } } catch { $pageFileAllocatedMB = $null $pageFileUsedMB = $null } [pscustomobject]@{ TotalBytes = [math]::Round($totalBytes, 0) AvailableBytes = [math]::Round($availableBytes, 0) TotalGB = [math]::Round($totalBytes / 1GB, 2) AvailableGB = [math]::Round($availableBytes / 1GB, 2) AvailablePercent = [math]::Round($availablePercent, 2) CommitLimitGB = [math]::Round($commitLimitBytes / 1GB, 2) CommitUsedGB = [math]::Round(($commitLimitBytes - $commitFreeBytes) / 1GB, 2) CommitUsedPercent = if ($null -ne $commitUsedPercent) { [math]::Round($commitUsedPercent, 2) } else { $null } PageFileAllocatedMB = $pageFileAllocatedMB PageFileUsedMB = $pageFileUsedMB } } $memory = Invoke-InfraPulseCommand -Context $Context -ScriptBlock $scriptBlock $stopwatch.Stop() $availableSeverity = 0 if ([double]$memory.AvailablePercent -le [double]$Settings.CriticalAvailablePercent) { $availableSeverity = 2 } elseif ([double]$memory.AvailablePercent -le [double]$Settings.WarningAvailablePercent) { $availableSeverity = 1 } # Older or mocked records may not carry the commit fields. $commitUsedPercent = $null $commitProperty = $memory.PSObject.Properties['CommitUsedPercent'] if ($null -ne $commitProperty -and $null -ne $commitProperty.Value) { $commitUsedPercent = [double]$commitProperty.Value } $commitSeverity = 0 if ($null -ne $commitUsedPercent) { if ($commitUsedPercent -ge [double]$Settings.CriticalCommitPercent) { $commitSeverity = 2 } elseif ($commitUsedPercent -ge [double]$Settings.WarningCommitPercent) { $commitSeverity = 1 } } $severity = [math]::Max($availableSeverity, $commitSeverity) $status = switch ($severity) { 2 { 'Critical' } 1 { 'Warning' } default { 'Healthy' } } $recommendation = if ($severity -eq 0) { '' } elseif ($commitSeverity -gt $availableSeverity) { 'Commit charge approaches the limit; grow the page file, add memory, or reduce the committed workload before allocations start failing.' } elseif ($severity -eq 2) { 'Identify memory pressure, runaway processes, or an undersized workload and restore operating headroom.' } else { 'Review sustained memory consumption and confirm that paging and workload sizing are acceptable.' } $message = '{0:N2} GB available ({1:N2}%) of {2:N2} GB physical memory.' -f [double]$memory.AvailableGB, [double]$memory.AvailablePercent, [double]$memory.TotalGB if ($null -ne $commitUsedPercent -and $commitSeverity -gt 0) { $message += ' Commit charge at {0:N2}% of the limit.' -f $commitUsedPercent } $evidence = [ordered]@{ TotalBytes = [double]$memory.TotalBytes AvailableBytes = [double]$memory.AvailableBytes TotalGB = [double]$memory.TotalGB AvailableGB = [double]$memory.AvailableGB AvailablePercent = [double]$memory.AvailablePercent } foreach ($commitField in @('CommitLimitGB', 'CommitUsedGB', 'CommitUsedPercent', 'PageFileAllocatedMB', 'PageFileUsedMB')) { $fieldProperty = $memory.PSObject.Properties[$commitField] if ($null -ne $fieldProperty) { $evidence[$commitField] = $fieldProperty.Value } } return New-InfraPulseResult -Status $status -CheckName 'Memory' -Category 'Capacity' -ComputerName $Context.ComputerName -Target 'Physical memory' -Message $message -ObservedValue ("{0:N2}%" -f [double]$memory.AvailablePercent) -WarningThreshold ("<= {0}% available or >= {1}% commit" -f $Settings.WarningAvailablePercent, $Settings.WarningCommitPercent) -CriticalThreshold ("<= {0}% available or >= {1}% commit" -f $Settings.CriticalAvailablePercent, $Settings.CriticalCommitPercent) -Recommendation $recommendation -Evidence $evidence -DurationMs $stopwatch.Elapsed.TotalMilliseconds } |