VMware Cloud Community
benso37
Contributor
Contributor

How to generate specific performance report with Powercli

I've looked around and found scripts here and there that can do some of what I need but nothing that can do exactly what I want. Unfortunately, I'm new to Powercli/Powershell so I don't know what I'm doing.

I need a script that can generate CPU and Memory utilization for specific dates and time. For example. 12PM to 5PM on the December 17th. Is this possible and can someone point me to a sample script I can modify?

Thanks in advance.

35 Replies
LucD
Leadership
Leadership

Perhaps try the following, define a longer period, let's say 7 days.

And then check if any data is returned. Once you have the data, you should have a look at the Timestamp in the returned counters.

$dayEnd = Get-Date

$dayStart = $dayEnd.AddDays(-7)


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
benso37
Contributor
Contributor

I get the following error after adding your last mod.

Get-Stat : Cannot validate argument on parameter 'Finish'. The argument is null

or empty. Supply an argument that is not null or empty and then try the comman

d again.

At C:\Windows\System32\WindowsPowerShell\v1.0\VMwareReportscripts7.ps1:11 char:

67

+ $stats = Get-Stat -Entity $vm -Stat $stat -Start $dayStart -Finish <<<<  $day

End

    + CategoryInfo          : InvalidData: (:) [Get-Stat], ParameterBindingVal

   idationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutom

   ation.ViCore.Cmdlets.Commands.GetViStats

-----------------------------------------------

This is what my current script looks like. First line deleted...

$vm = Get-VM | where {$_.PowerState -eq "PoweredOn"}

Write-Output "VMs found $($vm.Count)"

$dayStart = Get-Date

$dayEnd = $dayEnd.AddDays(-7)

Write-Output "From $dayStart"

Write-Output "To $dayEnd"

$stat = 'cpu.usage.average','mem.usage.average'

$stats = Get-Stat -Entity $vm -Stat $stat -Start $dayStart -Finish $dayEnd

$report = $stats | Group-Object -Property {$_.Entity.Name} | %{

    New-Object PSObject -Property @{

        VM = $_.Name

        ESX = $_.Group[0].Entity.Name

        Cluster = Get-Cluster -VM $_.Group[0].Entity | Select -ExpandProperty Name

        CPUavg = $_.Group | Where {$_.MetricID -eq 'cpu.usage.average'} | Measure-Object -Property Value -Average | Select -ExpandProperty Average

        Memavg = $_.Group | Where {$_.MetricID -eq 'mem.usage.average'} | Measure-Object -Property Value -Average | Select -ExpandProperty Average

    }

}

$report | Select VM,CPUavg,Memavg |

Export-Csv "C:\report.csv" -NoTypeInformation -UseCulture

0 Kudos
LucD
Leadership
Leadership

You swapped the calculation of the values around, Start should be before Finish in time.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
esxi1979
Expert
Expert

------------------------ ****** ---------------------------------------- ****** -------------------------------

wrt

Try like this

$stat = 'cpu.usage.average','mem.usage.average'

$stats = Get-Stat -Entity $vm -Stat $stat -Start $dayStart -Finish $dayEnd

$report = $stats | Group-Object -Property {$_.Entity.Name} | %{

    New-Object PSObject -Property @{

        VM = $_.Name

        ESX = $_.Group[0].Entity.Name

        Cluster = Get-Cluster -VM $_.Group[0].Entity | Select -ExpandProperty Name

        CPUavg = $_.Group | Where {$_.MetricID -eq 'cpu.usage.average'} | Measure-Object -Property Value -Average | Select -ExpandProperty Average

        Memavg = $_.Group | Where {$_.MetricID -eq 'mem.usage.average'} | Measure-Object -Property Value -Average | Select -ExpandProperty Average

    }

}

------------------------ ****** ---------------------------------------- ****** -------------------------------

ESX = $_.Group[0].Entity.Name

returned the vm name  itself

ESX =  $_.Group[0].Entity.vmhost | Select -ExpandProperty Name


will do ?

0 Kudos
benso37
Contributor
Contributor

I had to step away from this for a couple of days to work on something else but I'm back to work on it again. I noticed that the initial request wasn't very clear. The current script gives me the average CPU and Memory for a set time frame. For example, 12PM to 3PM I get a table like the following.

                     

VMCPUavgMemavg
MyVM123.43534512.656534
MyVM243.55433234.464545
MyVM354.56455165.234232

Is it possible to have the script do something like the following: If there's a way to generate against the VM Hos or cluster that will be great, If not, I don't mind generating on each VM.

TimeMemAvgUsageCPUAvgUsage
12/9/2014 11:05:0030.996.01
12/9/2014 11:10:0029.995.8
12/9/2014 11:15:00254.69
12/9/2014 11:20:0025.994.99
12/9/2014 11:25:0025.995.41
12/9/2014 11:30:0027.995.38
0 Kudos
LucD
Leadership
Leadership

You mean like this ?

$vm = Get-VM | where {$_.PowerState -eq "PoweredOn"}

Write-Output "VMs found $($vm.Count)"

$dayEnd = Get-Date

$dayStart = $dayEnd.AddDays(-1)

Write-Output "From $dayStart"

Write-Output "To $dayEnd"

$stat = 'cpu.usage.average','mem.usage.average'

$stats = Get-Stat -Entity $vm -Stat $stat -Start $dayStart -Finish $dayEnd

$report = $stats | Group-Object -Property {$_.Entity.Name},Timestamp | %{

    New-Object PSObject -Property @{

        VM = $_.Name

        ESX = $_.Group[0].Entity.Name

        Cluster = Get-Cluster -VM $_.Group[0].Entity | Select -ExpandProperty Name

        Timestamp = $_.Group[0].Timestamp

        CPUavg = $_.Group | Where {$_.MetricID -eq 'cpu.usage.average'} | Select -ExpandProperty Value

        Memavg = $_.Group | Where {$_.MetricID -eq 'mem.usage.average'} | Select -ExpandProperty Value

    }

}

$report | Select VM,CPUavg,Memavg |

Export-Csv "C:\report.csv" -NoTypeInformation -UseCulture


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
benso37
Contributor
Contributor

Thank you LucD.

That will work for me. I tried to add networking to the script but it returns system.object[] in the Netavg column. Do you know what I'm doing wrong?

$vm = Get-VM | where {$_.PowerState -eq "PoweredOn"}

Write-Output "VMs found $($vm.Count)"

$dayEnd = Get-Date

$dayStart = $dayEnd.AddDays(-1)

Write-Output "From $dayStart"

Write-Output "To $dayEnd"

$stat = 'cpu.usage.average','mem.usage.average','net.usage.average'

$stats = Get-Stat -Entity $vm -Stat $stat -Start $dayStart -Finish $dayEnd

$report = $stats | Group-Object -Property {$_.Entity.Name},Timestamp | %{

    New-Object PSObject -Property @{

        VM = $_.Name

        ESX = $_.Group[0].Entity.Name

        Cluster = Get-Cluster -VM $_.Group[0].Entity | Select -ExpandProperty Name

        Timestamp = $_.Group[0].Timestamp

        CPUavg = $_.Group | Where {$_.MetricID -eq 'cpu.usage.average'} | Select -ExpandProperty Value

        Memavg = $_.Group | Where {$_.MetricID -eq 'mem.usage.average'} | Select -ExpandProperty Value

        Netavg = $_.Group | Where {$_.MetricID -eq 'net.usage.average'} | Select -ExpandProperty Value

    }

}

$report

$report | Select VM,CPUavg,Memavg,Netavg |

Export-Csv "C:\VMreports.csv" -NoTypeInformation -UseCulture

0 Kudos
LucD
Leadership
Leadership

For the network counter there are multiple instances, you can select the 'average' instance.

Netavg = $_.Group | Where {$_.MetricID -eq 'net.usage.average' -and $_.Instance -eq ''} | Select -ExpandProperty Value


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
benso37
Contributor
Contributor

I modified the following line as suggested but the Netavg column doesn't generate any output. It comes back blank. I wonder if it's because I have multiple Network interfaces for each VM.



Netavg = $_.Group | Where {$_.MetricID -eq 'net.usage.average' -and $_Instance -eq 'average'} | Select -ExpandProperty Value

0 Kudos
LucD
Leadership
Leadership

The Instance value should not be 'average' but an empty string (as in my example).

The average value has an Instance value of ''


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
benso37
Contributor
Contributor

That's how I did it the first time but that didn't work.

0 Kudos
LucD
Leadership
Leadership

Can you try running with the following line, I would like to check which instances you get.

Netavg = [string]::Join('|',($_.Group | Where {$_.MetricID -eq 'net.usage.average'} | Select -ExpandProperty Instance))


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
benso37
Contributor
Contributor

VM

CPUavgMemavgNetavg
MyVm001, 12/11/2014 13:23:2013.6914.994000|vmnic0|vmnic2|vmnic1|vmnic4|vmnic3|vmnic5|

That's what the report looks like.

0 Kudos
LucD
Leadership
Leadership

That last vertical bar indicates that there is an instance with a blank value.

So the Where-clause I gave earlier should work.

Perhaps you could attach the complete script you are using, there might be a typo perhaps ?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
benso37
Contributor
Contributor

Here's my script.

$vm = Get-VM | where {$_.PowerState -eq "PoweredOn"}

Write-Output "VMs found $($vm.Count)"

$dayEnd = Get-Date

$dayStart = $dayEnd.AddDays(-1)

Write-Output "From $dayStart"

Write-Output "To $dayEnd"

$stat = 'cpu.usage.average','mem.usage.average','net.usage.average'

$stats = Get-Stat -Entity $vm -Stat $stat -Start $dayStart -Finish $dayEnd

$report = $stats | Group-Object -Property {$_.Entity.Name},Timestamp | %{

    New-Object PSObject -Property @{

        VM = $_.Name

        ESX = $_.Group[0].Entity.Name

        Cluster = Get-Cluster -VM $_.Group[0].Entity | Select -ExpandProperty Name

        Timestamp = $_.Group[0].Timestamp

        CPUavg = $_.Group | Where {$_.MetricID -eq 'cpu.usage.average'} | Select -ExpandProperty Value

        Memavg = $_.Group | Where {$_.MetricID -eq 'mem.usage.average'} | Select -ExpandProperty Value

        Netavg = [string]::join('|',($_.Group | Where {$_.MetricID -eq 'net.usage.average'} | Select -ExpandProperty Instance))

    }

}

$report | Select VM,CPUavg,Memavg,Netavg | Sort-Object VM | Export-Csv "C:\temp\VMreports.csv" -NoTypeInformation -UseCulture

0 Kudos
LucD
Leadership
Leadership

Try like this

$vm = Get-VM | where {$_.PowerState -eq "PoweredOn"}

Write-Output "VMs found $($vm.Count)"

$dayEnd = Get-Date

$dayStart = $dayEnd.AddDays(-1)

Write-Output "From $dayStart"

Write-Output "To $dayEnd"

$stat = 'cpu.usage.average','mem.usage.average','net.usage.average'

$stats = Get-Stat -Entity $vm -Stat $stat -Start $dayStart -Finish $dayEnd

$report = $stats | Group-Object -Property {$_.Entity.Name},Timestamp | %{

    New-Object PSObject -Property @{

        VM = $_.Name

        ESX = $_.Group[0].Entity.Name

        Cluster = Get-Cluster -VM $_.Group[0].Entity | Select -ExpandProperty Name

        Timestamp = $_.Group[0].Timestamp

        CPUavg = $_.Group | Where {$_.MetricID -eq 'cpu.usage.average'} | Select -ExpandProperty Value

        Memavg = $_.Group | Where {$_.MetricID -eq 'mem.usage.average'} | Select -ExpandProperty Value

        Netavg = $_.Group | Where {$_.MetricID -eq 'net.usage.average' -and $_.Instance -eq ''} | Select -ExpandProperty Value

    }

}

$report | Select VM,CPUavg,Memavg,Netavg | Sort-Object VM |

Export-Csv "C:\temp\VMreports.csv" -NoTypeInformation -UseCulture


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference