« Previous 1 2
Retrieving Windows performance data in PowerShell
Taking Precautions
Reading Performance Data
Performance testing only really becomes exciting if you can evaluate the performance data. Windows provides performance logging in the Performance Monitor. The subsystem lets you create individual snippets or longer historical records of the computer's performance. The system uses a variety of indicators that measure and log certain performance components. The known performance counters include CPU usage, free available memory, and the physical hard disk queue and its percent free space (Figure 3).
Anyone who is familiar with the details of performance logging in Windows can familiarize themselves with the Performance Monitor. To access it via the console, type perfmon.msc
. You can enable more performance indicators as needed; they are divided into several categories such as Processor, Memory, or PhysicalDisk. Indicators are freely selectable. After the indicators have been selected, the Performance Monitor displays the collected data as plots on a chart.
All the performance counters found in the Performance Monitor can be queried and reused with PowerShell. If you know the names of the counters, you can query them using the Get-Counter
cmdlet (Listing 8).
Listing 8
Getting a Single Get-Counter Value
# Get-Counter -Counter "\Processor(_Total)\% Processor Time" Timestamp CounterSamples --------- -------------- 16.03.2014 10:58:22 \\helix\processor(_total)\% \ processor time: 24.4764593867485
Querying an indicator once will output the current real-time value for the system. However, because it is only a single value that might be taken when the system is briefly peaking or in a trough, it might have very little validity in terms of the true state of the system. To collect multiple values then, the cmdlet supports two parameters: MaxSamples
and SampleInterval
.
The cmdlet in Listing 9 does not just retrieve the current value, it picks up a total of 10 samples at five-second intervals, or a period of 50 seconds, which you can then reprocess using, for example, Measure-Object
to determine the mean value:
Listing 9
Collecting Multiple System Values
# Get-Counter -Counter "\Processor(_Total)\% Processor Time" \ -SampleInterval 5 -MaxSamples 10 Timestamp CounterSamples --------- -------------- 16.03.2014 11:17:13 AM \\helix\processor(_total)\% \ processor time: 18.6118692812167 16.03.2014 11:17:18 AM \\helix\processor(_total)\% \ processor time: 24.2151756511614 16.03.2014 11:17:23 AM \\helix\processor(_total)\% \ processor time: 23.8306694146364 [...]
# $samples = Get-Counter -Counter "\Processor(_Total)\% Processor Time" \ -SampleInterval 5 -MaxSamples 10 # $samples.CounterSamples.CookedValue | Measure-Object -Average Count: 10 Average: 9.04691386288023 Sum: Maximum: Minimum: Property:
The collected raw data is embedded in CookedValue
and sent through the pipe to Measure-Object
, where it emerges as an average. This basic method can be compiled as a small script that collects performance counters, calculates the means, and then outputs the values.
You can expand the collect-counters.ps1
script (Listing 10) as you like. It collects the data for the selected performance counters and outputs them at the command line after retrieval. A neat progress indicator also appears. The performance counters are stored in an array that can be expanded arbitrarily. The three counters used are only examples. The script is created so that the array can be filled with a few more indicators, which are then automatically scanned one after another.
Listing 10
collect-counters.ps1
##Parameter $NUMBER_OF_SAMPLES = 5; $SAMPLE_INTERVAL_TIME = 1; $counters = @( "\Memory\Available MBytes", "\Processor(_Total)\% Processor Time", "\LogicalDisk(_Total)\% Free Space", "\Network Adapter(NIC TEAM 1)\Bytes Total/sec", "\Objects\Processes" ) ##enter other counter here. ##the values are saved here. $val = @{} $i = 0; foreach($counter in $counters) { Write-Progress -activity "Collecting performance data" -status "Counter data $($i+1) von $($counters.Count): $($counter)" -PercentComplete $(($i+1)/($counters.Count+1)*100) try { $v = Get-Counter -Counter $counter -MaxSamples $NUMBER_OF_SAMPLES -SampleInterval $SAMPLE_ INTERVAL_TIME $val.Add($counter, ($v.CounterSamples.CookedValue | Measure-Object -Average).Average ) } catch { Write-Host "Error: the counter could not be collected. Reason: $($_)" } $i++; } Write-Progress -activity "Collecting performance data" status \ "Releasing results" -PercentComplete 100 Write-Host "Results: " $val
Reviewing Threshold Values
The script only outputs values at the command line, so there is no automatic warning if one of the performance counters reaches a critical value. To do so, the script in Listing 11 breaks the task down into three functions: one each to test for a shortfall or surfeit of the threshold value, and one to collect the data from remote servers.
Listing 11
warn-counters.ps1
##Parameter $NUMBER_OF_SAMPLES = 5; $SAMPLE_INTERVAL_TIME = 1; ###Load server list $serverList = Get-Content -Path C:\temp\server.txt; ##Defining the counter and threshold values ##Each line: Counter, alarm triggers if over/under, threshold value $counters = ( ('\Memory\Available MBytes', 'under', 500), #Alert if under 500 ('\Processor(_Total)\% Processor Time', 'over', 60), #Alert if over 60 ('\LogicalDisk(_Total)\% Free Space', 'under', 10 ) #Alert if under 10 ) #Array end function checkLowerLimit([int]$threshold, [int]$average) { if($average -lt $threshold) { Write-Host "threshold value not reached!" return $false; } return $true; } function checkUpperLimit([int]$threshold, [int]$average) { if($average -gt $threshold) { Write-Host "threshold value exceeded!" return $false; } return $true; } function getPerformanceData([array]$counter, [string]$machine) { try { $v = Get-Counter -Counter $counter -ComputerName $machine \ -MaxSamples $NUMBER_OF_SAMPLES -SampleInterval $SAMPLE_INTERVAL_TIME -ErrorAction SilentlyContinue if($v -eq $null -or $v -eq "") { Write-Host "Counter $($counter) delivered no value." Continue; } $average = ($v.CounterSamples.CookedValue | \ Measure-Object -Average).Average } catch { Write-Host "Error: the counter could not be collected. Reason: $($_)" } ##Bigger or smaller? if($counter[1] -eq "under") { $limit = checkLowerLimit \ $counter[2] $average } else { $limit = checkUpperLimit $counter[2] $average } ##If the test retruns a "$false", the threshold value has been damaged: if(-not $limit) { Write-Host "[$($machine)] Counter \ $($counter[0]) has, with the value $($average), exceed $($counter[2]) not reached $($counter[1]) \ the threshold value." } } ###The script starts here: $c = $serverlist.Count * $counters.Count $i=0; foreach($server in $serverList) { foreach($counter in $counters) { Write-Progress -activity "Collecting performance data" \ -status "Counter data $($i+1) from $($c): $($counter) on $($server)" -PercentComplete $(($i+1)/($c)*100) getPerformanceData $counter $server $i++; } } #End foreach server Write-Host "End of the collection. Threshold limit damages \ are issued on the command line."
The collection script on remote computers is the well-known server.txt
from the first example. The performance counters to be retrieved are in a table (array); each row represents a counter, and the columns represent the name, the check for a shortfall (under
) or excess (over
), and the threshold value itself. For example,
('\Memory\Available MBytes', 'under', 500)
checks to see whether the available memory drops below 500MB.
The script then runs through the freely extensible performance counters by server and checks the results. If a threshold is over- or undershot, it outputs a corresponding message on the command line. The server name is transmitted once again with the ComputerName
parameter.
An extension of the script could dump the results to a text file or even a database, allowing you to evaluate a trend over time. PowerShell professionals could also parallelize the counter queries from several servers to save processing time.
Conclusions
PowerShell quickly and simply lets you keep an eye on the performance parameters of multiple computers from the command line. More complex scripts can be compiled to monitor threshold values.
Infos
- Win32 classes: http://msdn.microsoft.com/en-us/library/aa394084(v=vs.85).aspx
- WMI Code Creator v1.0: http://www.microsoft.com/en-us/download/details.aspx?id=8572
« Previous 1 2
Buy this article as PDF
(incl. VAT)