System Center 2019+ Virtual Machine Manager Host CPU Utilization

Microsoft.SystemCenter.VirtualMachineManager.HostCPUUtilizationMonitor (UnitMonitor)

Monitors the host CPU utilization

Knowledge Base article:

Summary

This monitor tracks the CPU performance of the host. The CPU usage has exceeded the threshold.

Causes

The virtual machines running on the host are consuming critical levels of the CPU resources on the host.

Resolutions

To free CPU resources, migrate a virtual machine to another host. You may also have Virtual Machine Manager automatically optimize host clusters by enabling dynamic optimization. For information about dynamic optimization, see the Virtual Machine Manager documentation.

Element properties:

TargetMicrosoft.SystemCenter.VirtualMachineManager.Discovery.HyperVHost
Parent MonitorSystem.Health.AvailabilityState
CategoryAvailabilityHealth
EnabledTrue
Alert GenerateTrue
Alert SeverityMatchMonitorHealth
Alert PriorityNormal
Alert Auto ResolveTrue
Monitor TypeMicrosoft.SystemCenter.VirtualMachineManager.Performance.PowershellBasedConsecutiveSamplesTwoThresholdsMonitorType
RemotableTrue
AccessibilityPublic
Alert Message
Host CPU Utilization high
The host CPU utilization is {1} and has exceeded the warning or critical levels for {0}
RunAsDefault

Source Code:

<UnitMonitor ID="Microsoft.SystemCenter.VirtualMachineManager.HostCPUUtilizationMonitor" Accessibility="Public" Target="VMMDiscovery!Microsoft.SystemCenter.VirtualMachineManager.Discovery.HyperVHost" ParentMonitorID="SystemHealth!System.Health.AvailabilityState" Remotable="true" TypeID="Microsoft.SystemCenter.VirtualMachineManager.Performance.PowershellBasedConsecutiveSamplesTwoThresholdsMonitorType">
<Category>AvailabilityHealth</Category>
<AlertSettings AlertMessage="Microsoft.SystemCenter.VirtualMachineManager.HostCPUUtilizationMonitor.AlertMessage">
<AlertOnState>Warning</AlertOnState>
<AutoResolve>true</AutoResolve>
<AlertPriority>Normal</AlertPriority>
<AlertSeverity>MatchMonitorHealth</AlertSeverity>
<AlertParameters>
<AlertParameter1>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</AlertParameter1>
<AlertParameter2>$Data/Context/SampleValue$</AlertParameter2>
</AlertParameters>
</AlertSettings>
<OperationalStates>
<OperationalState ID="HostCPUUtilizationReachedWarning" MonitorTypeStateID="ConditionWarn" HealthState="Warning"/>
<OperationalState ID="HostCPUUtilizationReachedError" MonitorTypeStateID="ConditionError" HealthState="Error"/>
<OperationalState ID="HostCPUUtilizationIsSuccess" MonitorTypeStateID="ConditionSuccess" HealthState="Success"/>
</OperationalStates>
<Configuration>
<IntervalSeconds>180</IntervalSeconds>
<TimeoutSeconds>180</TimeoutSeconds>
<WarningThreshold>90</WarningThreshold>
<CriticalThreshold>95</CriticalThreshold>
<NumSamples>3</NumSamples>
<hostComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</hostComputerName>
<ScriptBody><Script>#This Script is used to check the Host CPU utilization
# which includes parent partition and CPU utilizations caused by the vms
# Alert when the utilization of this partition is high:
# Warning: WarningThreshold%, like 80%
# Critical: CriticalThreshold, like 90%
#SetLocale("en-us")
#Please check this link to get understanding http://blogs.msdn.com/b/tvoellm/archive/2008/07/14/how-to-get-processor-utilization-for-hyper-v-via-wmi.aspx

$momApi = new-Object -comObject "Mom.ScriptAPI"
$momBag = $momApi.CreatePropertyBag()
$timePeriodSeconds = 10
#$strLPTotalQuery = "SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor where Name='_Total'"
#$strLPCountQuery = "SELECT * FROM Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor"
$logicalProcessorStats = Get-CimInstance -ClassName "Win32_PerfRawData_HvStats_HyperVHypervisor" -Namespace "root\cimv2"
$logicalProcessorStatsCount = $logicalProcessorStats.LogicalProcessors
if($logicalProcessorStatsCount -lt 1)
{
exit
}
$totalLogicalProcessorStats=Get-CimInstance -ClassName "Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor" -Namespace "root\cimv2" -Filter "Name='_Total'"
ForEach ($item in $totalLogicalProcessorStats)
{
$percentTotalRunTime_First= $item.PercentTotalRunTime
$timestamp_PerfTime_First = $item.Timestamp_PerfTime
}

Start-Sleep $timePeriodSeconds

$totalLogicalProcessorStats=Get-CimInstance -ClassName "Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor" -Namespace "root\cimv2" -Filter "Name='_Total'"
ForEach ($item in $totalLogicalProcessorStats)
{
$frequency_PerfTime = $item.Frequency_PerfTime
$percentTotalRunTime_Second= $item.PercentTotalRunTime
$timestamp_PerfTime_Second = $item.Timestamp_PerfTime
}

if($timestamp_PerfTime_Second - $timestamp_PerfTime_First -eq 0)
{
$momApi.LogScriptEvent("HostCPUUtilizationProvider.ps1", 101, 0, "The readings were not taken properly and hence the script could not be executed.")
exit 1
}

#Calculate CPU readings with formula
$CPU = ( $percentTotalRunTime_Second - $percentTotalRunTime_First)/($timestamp_PerfTime_Second - $timestamp_PerfTime_First)
$CPU = ($frequency_PerfTime * $CPU) / $logicalProcessorStatsCount
$CPU = [int]($CPU / 100000)

if( $CPU -gt 100)
{
$CPU = 100
}
if( $CPU -lt 0)
{
$CPU = 0
}

$CPU = [int]($CPU)
$momBag.AddValue("Utilization", $CPU)
$momBag

</Script></ScriptBody>
<ObjectName>Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor</ObjectName>
<CounterName>PercentTotalRunTime</CounterName>
<InstanceName>_Total</InstanceName>
<Value>$Data/Property[@Name='Utilization']$</Value>
</Configuration>
</UnitMonitor>