Currently, powershell is used in the production environment for performance monitoring. However, get-counter is used to obtain the \ Web Service (_ total) of IIS) \ Total method requests/sec often gets a value of 0, but the actual number of IIS requests is not 0 (this can be done by opening the windows performance counter for comparison ). I believe that many people have encountered such a situation and we have consulted Microsoft on this issue. Microsoft replied that the performance counters are only partially opened by default, the total method requests/sec of IIS is disabled by default. When we take the initiative to obtain it, the value of this performance counter is that it is meeting to open for data collection, and this collection process takes a short time to take effect (time is not fixed, however, from experience, it may take 1 to 2 seconds, sometimes less than 1 second ). Because the get-counter acquisition time is very short, after the get-counter is executed, the performance counter is turned on and collected, however, get-counter has returned this value before the underlying performance counters are collected, so this value is often 0.
To solve this problem, we can use get-counter's-maxsamples and-sampleinterval to solve the problem. The method is as follows:
Get-Counter "\Web Service(_total)\Total Method Requests/sec" -MaxSamples 3 -SampleInterval 2
Maxsamples: continuous collection multiple times
Sampleinterval: Collection interval (seconds)
In fact, it is enough to use-maxsamples. sampleinterval is used to prevent the collection of underlying data from being slower than 1 second.
Using the preceding statement, we can see that the first returned result is often 0, and subsequent data is normal. We may want to filter out the data of this 0 value:
Get-Counter "\Web Service(_total)\Total Method Requests/sec" -MaxSamples 3 -SampleInterval 2 | Where-Object {$_.CookedValue -gt 0}
The steps for collecting data are as follows:
$counterResult = Invoke-Command -Session $session -ScriptBlock { param($args) $result = Get-Counter -Counter $args -SampleInterval 2 $result.Timestamp $result.CounterSamples} -ArgumentList ("","\Web Service(_total)\Total Method Requests/sec", "\Processor(_total)\% Processor Time")
This script Collects performance counters, collects only one record at a time, and inserts it into the database for analysis after subsequent processing. When maxsamples is added, multiple datasets are returned. This is very difficult for subsequent processing. We hope that the returned dataset will still be a record of each performance counter, in addition, it is necessary to exclude 0 cases and calculate the average value during multiple collections. (A CPU performance counter is added here for testing)
Therefore, we need to transform the above script as follows:
$counterResult = Invoke-Command -Session $session -ScriptBlock {param($args);$result = Get-Counter -Counter $args -MaxSamples 3;($result | Sort-Object Timestamp -Descending | Select-Object -First 1).Timestamp;$result | ForEach-Object { $_.CounterSamples } | Where-Object {$_.CookedValue -gt 0} | Group-Object Path, InstanceName ` | %{ New-Object PSObject -Property @{ Path = ($_.Group | Select-Object -First 1).Path InstanceName = ($_.Group | Select-Object -First 1).InstanceName CookedValue = ($_.Group | Measure-Object CookedValue -Average).Average } };} -ArgumentList ("","\Web Service(_total)\Total Method Requests/sec", "\Processor(_total)\% Processor Time")
The transformed code is a bit complicated. Let's take a look at the tests before implementing this Code:
# First, connect to the server and run get-counter $ result = Get-counter ("\ Web Service (_ total) \ Total method requests/sec ", "\ processor (_ total) \ % processor time")-maxsamples 3 $ result # The returned result is as follows: timestamp countersamples ------------------ 19:44:48 \ w-7087-sns \ Web Service (_ total) \ Total method requests/sec: 0 \ w-7087-sns \ processor (_ total) \ % processor time: 3.46108853061208 19:44:49 \ w-7087 -SNS \ Web Service (_ total) \ Total method requests/sec: 220.905233511705 \ w-7087-sns \ processor (_ total) \ % processor time: 1.92261018891783 19:44:50 \ w-7087-sns \ Web Service (_ total) \ Total method requests/sec: 211.058777806759 \ w-7087-sns \ processor (_ total) \ % processor time: 4.61494249812969 # exclusion time, we processed the data in countersamples and used where-object to exclude the records whose cookedvalue is 0 $ result | foreach-object {$ _. count Ersamples} | where-object {$ _. cookedvalue-GT 0} # result: path InstanceName cookedvalue ---- ----------------- \ w-7087-sns \ processor (_ total) \ % pro... _ total 7.3072651350323 \ w-7087-sns \ Web Service (_ total) \ tot... _ total 254.469941283377 \ w-7087-sns \ processor (_ total) \ % pro... _ total 1.73030281901895 \ w-7087-sns \ Web Service (_ total) \ tot... _ total 203.141900641814 # We will group this result. Here we can get the grouped data $ result | Foreach-object {$ _. countersamples} | where-object {$ _. cookedvalue-GT 0} | group-Object Path, InstanceName # result: Count name group ----- ---- 2 \ w-7087-sns \ processor... {Microsoft. powershell. commands. getcounter. performancecountersample, Microsoft. powers... 2 \ w-7087-sns \ Web servi... {Microsoft. powershell. commands. getcounter. performancecountersample, Microsoft. powers... # Here, the grouping condition will change to name. The name in is composed of path + InstanceName, counter is the number of records of the group, and the Group stores the original data before the group, this is exactly the data we need # Let's take a look at the data in the group $ result | foreach-object {$ _. countersamples} | where-object {$ _. cookedvalue-GT 0} | group-Object Path, InstanceName | foreach-object {$ _. group; "---------"} # result: path InstanceName cookedvalue ---- ----------------- \ w-7087-sns \ processor (_ total) \ % pro... _ total 7.3072651350323 \ w-7087-sns \ P Rocessor (_ total) \ % pro... _ total 1.73030281901895 --------- \ w-7087-sns \ Web Service (_ total) \ tot... _ total 254.469941283377 \ w-7087-sns \ Web Service (_ total) \ tot... _ total 203.141900641814 --------- # We can see that our data has been distinguished by our grouping conditions, and we will calculate it. # Here we will first introduce the settlement function measure-object. The above data will demonstrate the calculation function $ result in powershell | foreach-object {$ _. countersamples} | where-object {$ _. cookedvalue-GT 0} | measure-object cookedvalue-average-maximum-sum-Minimum # The result is as follows: Count: 4 Average: 116.662352469811sum: 466.649409879243 maximum: 254.469941283377 minimum: 1.73030281901895 property: cookedvalue # The preceding figure shows how to use measure-object to perform-average (average)-maximu on cookedvalue. M (maximum)-sum (total)-minimum (minimum) Calculation Result # If we only need a value: ($ result | foreach-object {$ _. countersamples} | where-object {$ _. cookedvalue-GT 0} | measure-object cookedvalue-average-maximum-sum-minimum ). average # because only the result set is left after the dataset is calculated by measure-object, we need to process the result. Here % {} is used {}, in fact, % {} is basically equivalent to foreach-object {}, here they can replace each other # After the result set is grouped by group-object, we can re-combine the result set (for the data after group-object, see the previous section) # % {} execute new-object to create a psobject type object, which contains prop Erty (attribute, that is, the field in the dataset) # The path field takes the first path of the group field in group-object, this is also true for InstanceName # cookedvalue is the average value after performing the measure-object Calculation for each dataset in the group field $ result | foreach-object {$ _. countersamples} | where-object {$ _. cookedvalue-GT 0} | group-Object Path, InstanceName '| % {New-object psobject-property @ {Path = ($ _. group | select-object-first 1 ). path InstanceName = ($ _. group | select-object-first 1 ). instanceName C Ookedvalue = ($ _. group | measure-object cookedvalue-average ). average }}# result: cookedvalue InstanceName path ----------- ------------ ---- 4.51878397702563 _ total \ w-7087-sns \ processor (_ total) \ % pro... 228.805920962596 _ total \ w-7087-sns \ Web Service (_ total) \ tot... # We can see that this result is the data we want. After assembling the above Code, we will get the transformed code segment.
All the tests have been completed here. I believe how did the transformed code segment come from above.
I hope this article will help you.
Reference: http://stackoverflow.com/questions/5999930/powershell-how-to-sum-multiple-items-in-an-object