question

NewDBA-9798 avatar image
0 Votes"
NewDBA-9798 asked NewDBA-9798 commented

Instant accurate CPU watch using Windows Powershell

I am using below Powershell code to check the instant CPU utilization in my Windows Server (SQL Server Database boxes).

What I am trying to do get the accurate results of CPU utilization . But the below code does seems to be helping , could anyone aware of this please help. Even using the counter values doesn't give me the accurate values , please help.


 Function Get-Cpu {
    
 [CmdletBinding()]
    
     Param (
    
         [parameter(Mandatory, ValueFromPipeline)]
    
         [String[]]$ServerInstance,
    
         [parameter(Mandatory = $true)] $NumOfSessions
    
     )
    
 foreach($i in $ServerInstance){
    
 Get-Counter -ComputerName $i -Counter "\Process(*)\% Processor Time" -ErrorAction SilentlyContinue `
    
   | select -ExpandProperty CounterSamples `
    
   | where {$_.Status -eq 0  } `
    
   | sort CookedValue -Descending `
    
   | select @{N = "SQLInstance";e={$i}} , TimeStamp,
    
     @{N="Name";E={
    
         $friendlyName = $_.InstanceName
    
         try {
    
             $procId = [System.Diagnostics.Process]::GetProcessesByName($_.InstanceName)[0].Id
    
             $proc = Get-WmiObject -Query "SELECT ProcessId, ExecutablePath FROM Win32_Process WHERE ProcessId=$procId"
    
             $procPath = ($proc | where { $_.ExecutablePath } | select -First 1).ExecutablePath
    
             $friendlyName = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($procPath).FileDescription
    
         } catch { }
    
         $friendlyName
    
     }},
    
     @{N="CPU";E={(($_.CookedValue/100/$env:NUMBER_OF_PROCESSORS)/100).ToString("P")}}  -First $NumOfSessions |Format-Table -AutoSize
    
     
    
  }
    
  }
    
  Get-Cpu


windows-serverwindows-server-powershell
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered

On line 19, why have you used "ExpandProperty"? That will produce a string, not an object that has property names. That means, for example, line 21 probably doesn't get you the value of the "Status" property as you expect.

I'd replace lines 25 - 51 with a "ForEach-Object" and build an [ordered] hash with the key names and values you want, and then use that has to produce PSCustomObject(s) that are emitted from the function. It'd be a lot easier to understand than your attempt to use Select-Object.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered NewDBA-9798 commented

I straightened out your code and ran it (I don't have SQL, though). I'm not sure what result you're trying to achieve, though. I get the "accurate results of CPU utilization" part, but not whether you're after only certain processes, or the total CPU for all processes, or something else. Right now the result are only the CPU consumption of the top "X" number processes regardless of what they are. Furthermore, it's only the top "X" results of each individual set of CounterSamples.

This is how I reformatted your code. I think it's more understandable. I hope you do, too:

 Function Get-Cpu {
     [CmdletBinding()]
     Param (
         [parameter(Mandatory, ValueFromPipeline)]
         [String[]]$ServerInstance,
         [parameter(Mandatory = $true)] $NumOfSessions
     )
        
     $template = [ordered]@{
         SQLInstance = ""
         TimeStamp = ""
         Name = ""
         CPU = ""
     }
    
     foreach ($i in $ServerInstance) {
         Get-Counter -ComputerName $i -Counter "\Process(*)\% Processor Time" -ErrorAction SilentlyContinue |    # gets all processes
             Select-Object -ExpandProperty CounterSamples |
                 Where-Object { $_.Status -eq 0 } |
                     Sort-Object CookedValue -Descending |
                         Select-Object -First $NumOfSessions |   # get only the top X number of CounterSamples
                             ForEach-Object{
                                 $template.SQLInstance = $i
                                 $template.TimeStamp = $_.TimeStamp
                                 $template.Name = Try{
                                                         $procId = [System.Diagnostics.Process]::GetProcessesByName($_.InstanceName)[0].Id
                                                         $proc = Get-WmiObject -Query "SELECT ProcessId, ExecutablePath FROM Win32_Process WHERE ProcessId=$procId" -ErrorAction STOP
                                                         $procPath = (   $proc | 
                                                                             Where-Object { $_.ExecutablePath } | 
                                                                                 Select-Object -First 1).ExecutablePath
                                                         $friendlyName = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($procPath).FileDescription
                                                         $friendlyName
                                                     }
                                                     Catch{
                                                         $i      # in case of failure use the server instance
                                                     }
                                 $template.CPU = "{0:P}" -f (($_.CookedValue / 100 / $env:NUMBER_OF_PROCESSORS) / 100)   # express result as percentage
                                 [PSCustomObject]$template
                             }
     }
 }
    
     Get-Cpu ws06 3

I left the "$friendlyName" variable in the code but it's not necessary. You can remove the "$friendlyName =" and keep the "[System.Diagnostics.FileVersionInfo]::GetVersionInfo($procPath).FileDescription". If you do, remove the "$friendlyName" right below that.

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thank you it helped me .

0 Votes 0 ·