VMware Cloud Community
Rajeev_S
Expert
Expert
Jump to solution

get-stat monthly report

Hi,

I'm trying to script the stats on a monthly basis. I'm using the below script,

Get-Stat -Entity (Get-Cluster -Name x) -start (get-date).AddDays(-30) -Finish (Get-Date) -MaxSamples 1000 -stat cpu.usagemhz.average | Export-Csv -Path c:\test.csv

It outputs based on time with 30 min interval.

Is it possible to get it as a single value for a month as it shows in VC ??

Also can we get the Max value reached in the cluster for the particular month.

Hope my question is clear!!!!!

Thanks

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

This should do what you want.

$allclust = @()
$clust = Get-Cluster

foreach($clu in $clust){
  $clusstat = "" | Select ClusterName, MemMax, MemAvg, CPUMax, CPUAvg
  $clusstat.ClusterName = $clu.name
  
  $statcpu = Get-Stat -Entity ($clu) `
           -start (get-date).AddDays(-30) `
           -Finish (Get-Date) `
	       -MaxSamples 10000 `
		   -stat cpu.usagemhz.average
  $statmem = Get-Stat -Entity ($clu) `
           -start (get-date).AddDays(-30) `
           -Finish (Get-Date) `
	       -MaxSamples 10000 `
		   -stat mem.usage.average

  $cpu = $statcpu | Measure-Object -Property value -Average -Maximum
  $mem = $statmem | Measure-Object -Property value -Average -Maximum
  
  $clusstat.CPUMax = $cpu.Maximum
  $clusstat.CPUAvg = $cpu.Average
  $clusstat.MemMax = $mem.Maximum
  $clusstat.MemAvg = $mem.Average
  
  $allclust += $clusstat
}

$allclust | `
  select ClusterName, MemMax, MemAvg, CPUMax, CPUAvg | `
  Export-Csv "c:\g.csv" -noTypeInformation


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

View solution in original post

Reply
0 Kudos
33 Replies
LucD
Leadership
Leadership
Jump to solution

Sure, you can use the Measure-Object cmdlet for that.

This will give you the maximum value for the period you are measuring

Get-Stat -Entity (Get-Cluster -Name x) -start (get-date).AddDays(-30) -Finish (Get-Date) -MaxSamples 1000 -stat cpu.usagemhz.average | `
Measure-Object -property Value  -maximum | select Maximum | Out-Default

With the Measure-Object you can get the maximum, minimum, average and the sum.


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

Rajeev_S
Expert
Expert
Jump to solution

Thanks LucD. That helped. I'm trying to put it in a proper format for all the cluster in my environment,

$clust = Get-Cluster

foreach($clu in $clust)

{Get-Stat -Entity ($clu) -start (get-date).AddDays(-30) -Finish (Get-Date) -MaxSamples 10000 -stat cpu.usagemhz.average | Measure-Object -Property value -Average -Maximum | select $clu.name, average, maximum | Out-File -Append c:\g.csv}

out-file doesnt format that correctly.. I'm not sure how to use export-csv cmdlet in this scenario.

Also can i add the memory avg & max value along with CPU values in the same report. My report should look like

ClusterName Memory Max Avg CPU Max Avg

Could anyone guide me to do that.

Thanks

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

This should do what you want.

$allclust = @()
$clust = Get-Cluster

foreach($clu in $clust){
  $clusstat = "" | Select ClusterName, MemMax, MemAvg, CPUMax, CPUAvg
  $clusstat.ClusterName = $clu.name
  
  $statcpu = Get-Stat -Entity ($clu) `
           -start (get-date).AddDays(-30) `
           -Finish (Get-Date) `
	       -MaxSamples 10000 `
		   -stat cpu.usagemhz.average
  $statmem = Get-Stat -Entity ($clu) `
           -start (get-date).AddDays(-30) `
           -Finish (Get-Date) `
	       -MaxSamples 10000 `
		   -stat mem.usage.average

  $cpu = $statcpu | Measure-Object -Property value -Average -Maximum
  $mem = $statmem | Measure-Object -Property value -Average -Maximum
  
  $clusstat.CPUMax = $cpu.Maximum
  $clusstat.CPUAvg = $cpu.Average
  $clusstat.MemMax = $mem.Maximum
  $clusstat.MemAvg = $mem.Average
  
  $allclust += $clusstat
}

$allclust | `
  select ClusterName, MemMax, MemAvg, CPUMax, CPUAvg | `
  Export-Csv "c:\g.csv" -noTypeInformation


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

Reply
0 Kudos
Rajeev_S
Expert
Expert
Jump to solution

Thanks LucD. You got me exactly what i was looking for. Amazing

Reply
0 Kudos
grog
Contributor
Contributor
Jump to solution

Luc,

Is there a way to make this report work for vms instead of the cluster? I am looking to report on average CPU and Memory utilization for vms over a month period. I would like to output to either csv or html. Any ideas?

Thanks,

Marc

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Sure, shouldn't be too hard.

Try something like this

$allvms = @()
$vms = Get-Vm

foreach($vm in $vms){
  $vmstat = "" | Select VmName, MemMax, MemAvg, CPUMax, CPUAvg
  $vmstat.VmName = $vm.name
  
  $statcpu = Get-Stat -Entity ($vm) `
           -start (get-date).AddDays(-30) `
           -Finish (Get-Date) `
	       -MaxSamples 10000 `
		   -stat cpu.usagemhz.average
  $statmem = Get-Stat -Entity ($vm) `
           -start (get-date).AddDays(-30) `
           -Finish (Get-Date) `
	       -MaxSamples 10000 `
		   -stat mem.usage.average

  $cpu = $statcpu | Measure-Object -Property value -Average -Maximum
  $mem = $statmem | Measure-Object -Property value -Average -Maximum
  
  $vmstat.CPUMax = $cpu.Maximum
  $vmstat.CPUAvg = $cpu.Average
  $vmstat.MemMax = $mem.Maximum
  $vmstat.MemAvg = $mem.Average
  
  $allvms += $vmstat
}

$allvms | `
  select VmName, MemMax, MemAvg, CPUMax, CPUAvg | `
  Export-Csv "c:\VMs.csv" -noTypeInformation


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

Reply
0 Kudos
grog
Contributor
Contributor
Jump to solution

Thanks LucD! Huge help! One more question for you? Is there anyway to gather this data for work hours only? Say 9am-5pm? I think the 24 hour period may skew the data a bit being that most of the vms are sitting idle over night. I would love to pinpoint this data to work hours.

Thanks,

Marc

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I'm afraid that is not possible with the Get-Stat cmdlet itself, nor with the underlying QueryPerf method from the SDK.

You could get all your statistical data and then use a Select-Object or an If-Then-Else construct on the Timestamp property to filter out the data you want.


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

Reply
0 Kudos
admin
Immortal
Immortal
Jump to solution

Luc.. that was superb!

Question:

How do I change the syntax for the date period?

This subroutine:

-start (get-date).AddDays(-30) `
-Finish (Get-Date) `

My intent is to go back 30 days at a time.. If I can go perhaps start and finish dates per calender 30 days..

aug, july, june etc.

As is it runs date executed script minus 30 days.

Merci! Thanks!

-Vuong

p.s. also I guess it is one vcenter at a time. I tried to connect-viserver to multiple vcenters, but the ouput wasn't there.

I assume it was the output file doesn't append.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

With a bit of conversion you could use the actual calendar months.

The following script shows you the last 12 calendar months.

$thisMonth = [datetime](Get-Date -Format "y")
12..1 | %{
	$from = $thisMonth.AddMonths(- $_)
	$to = $thisMonth.AddMonths(- $_ + 1).AddDays(-1)
	
}

If you use the $from in the -Start parameter and the $to in the -Finish parameter you can pull reports over the last 12 calendar months.


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

Reply
0 Kudos
admin
Immortal
Immortal
Jump to solution

Hmm

I tried (still learning) to modify the code:

$allclust = @()

$clust = Get-Cluster

foreach($clu in $clust){

$clusstat = "" | Select ClusterName, MemMax, MemAvg, CPUMax, CPUAvg

$clusstat.ClusterName = $clu.name

$thisMonth = datetime(Get-Date -Format "y")

12..1 | %{

$from = $thisMonth.AddMonths( - $_)

$to = $thisMonth.AddMonths( - $_ + 1).AddDays(-1)

}

$statcpu = Get-Stat -Entity ($clu) `

-start (get-date).AddDays(-30) `

-Finish (Get-Date) `

-MaxSamples 10000 `

-stat cpu.usagemhz.average

$statmem = Get-Stat -Entity ($clu) `

-start (get-date).AddDays(-30) `

-Finish (Get-Date) `

-MaxSamples 10000 `

-stat mem.usage.average

$cpu = $statcpu | Measure-Object -Property value -Average -Maximum

$mem = $statmem | Measure-Object -Property value -Average -Maximum

$clusstat.CPUMax = $cpu.Maximum

$clusstat.CPUAvg = $cpu.Average

$clusstat.MemMax = $mem.Maximum

$clusstat.MemAvg = $mem.Average

$allclust += $clusstat

}

$allclust | `

select ClusterName, MemMax, MemAvg, CPUMax, CPUAvg | `

Export-Csv "c:\g.csv" -noTypeInformation

But I got a syntax error:

The term 'datetime' is not recognized as a cmdlet, function, operable program, or script fil

again.

At C:\Documents and Settings\phamv\Desktop\clusterstats2.ps1:7 char:22

+ $thisMonth = datetime <<<< (Get-Date -Format "y")

+ CategoryInfo : ObjectNotFound: (datetime:String) [], CommandNotFoundException

+ FullyQualifiedErrorId : CommandNotFoundException

You cannot call a method on a null-valued expression.

At C:\Documents and Settings\phamv\Desktop\clusterstats2.ps1:9 char:30

+ $from = $thisMonth.AddMonths <<<< ( - $_)

+ CategoryInfo : InvalidOperation: (AddMonths:String) [], RuntimeException

+ FullyQualifiedErrorId : InvokeMethodOnNull

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That's a problem of the forum sw that has problems with square brackets.

The line should read: $thisMonth = \[datetime\](Get-Date -Format "y").

But the way you inserted my sample code in the script won't work.

I gave those last lines as an example of how to get the actual start and finish dates for the last 12 calendar months.

Attached (to avoid the square brackets problem) a script that gets the report for the previous calendar month.

I hope this clarifies a bit what I was trying to show.


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

Reply
0 Kudos
admin
Immortal
Immortal
Jump to solution

LucD

sorry to be so dense. I haven't had a chance to visit this topic in a while. I still don't understnad the formating syntax to get the last full 12 calendar months?

Could you explain? Thank you very much.

V

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Sure, I'll give it a try

This was the skeleton code to get the last 12 months

$thisMonth = [datetime](Get-Date -Format "y")
12..1 | %{
	$from = $thisMonth.AddMonths(- $_)
	$to = $thisMonth.AddMonths(- $_ + 1).AddDays(-1)
	
}

The first line uses the Get-Date cmdlet with the Format parameter to get just the Month and the Year ("March 2010").

Unfortunately that output is a string and we want a DateTime value for the rest of the script, so we cast the string to a DateTime object.

And we store that in the $thisMonth variable.

The cast will store the 1st day of the current month in the $thisMonth variable.

Today this would give "Monday 01 March 2010 00:00:00".

Then I start a loop where I count down from 12 to 1.

The ".." operator indicates a range of integers between the two values left and right.

In this case the result is 12 11 10 9 8 7 6 5 4 3 2 1.

The "%" statement is an alias for the Foreach-Object cmdlet.

In the code block that follows (the lines between the curly braces) the $_ variable represents the actual value.

So this variable will get the values 12 11 10 9 8 7 6 5 4 3 2 1 respectively.

We calculate the $from variable.

We subtract a number of months (value in $_) from the DateTime object in $thisMonth. We do this with the AddMonths method that is available on a DateTime object.

Remember the $thisMonth variable contained "Monday 01 March 2010 00:00:00" , so if we subtract 12 months we get "Sunday 01 March 2009 00:00:00".

The $to variable is again calculated from the $thisMonth variable.

We subtract $_ minus 1 month, which gives us "Wednesday 01 April 2009 00:00:00".

But we want the last day of the previous month so we subtract 1 day with the AddDays method.

And this gives us "Tuesday 31 March 2009 00:00:00".

Since we do this for all the values of the range we get 12 start-end dates for the past 12 months.

I hope this cleared it up a bit.

____________

Blog: LucD notes

Twitter: lucd22


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

Reply
0 Kudos
admin
Immortal
Immortal
Jump to solution

That makes sense..except I get and error.. executing

Missing expression after unary operator '-'.

At C:\Documents and Settings\user\Desktop\xxxxx\powercli\scripts\report-last

-2calendar-month.ps1:16 char:3

+ - <<<< start $from

+ CategoryInfo : ParserError: (-:String) [], ParseException

+ FullyQualifiedErrorId : MissingExpressionAfterOperator

====

HUH?

$thisMonth = (Get-Date -Format "y")

12..1 | %{

$from = $thisMonth.AddMonths(- $_ )

$to = $thisMonth.AddMonths(- $_ +1).AddDays(-1)

}

=================

Reply
0 Kudos
admin
Immortal
Immortal
Jump to solution

This is what I running...

Reply
0 Kudos
RvdNieuwendijk
Leadership
Leadership
Jump to solution

Luc,

The typecasting to datetime seems to work only if your computer uses the English language pack. I use Windows 7 Ultimate 64-bits with the Dutch language pack installed. Now I get an error with the typecasting. In English it works fine:

[vSphere PowerCLI] C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI> [datetime] "March 2010"

maandag 1 maart 2010 0:00:00


[vSphere PowerCLI] C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI> 

But if I use your code, I get an error:

[vSphere PowerCLI] C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI> [datetime] (Get-Date -Format "y")
Cannot convert value "maart 2010" to type "System.DateTime". Error: "De tekenreeks is niet herkend als een geldige Date
Time. Index 0 begint met een onbekend woord."
At line:1 char:11
+ [datetime] <<<<  (Get-Date -Format "y")
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

[vSphere PowerCLI] C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI>

I get the same error if I replace (Get-Date -Format "y") by it's value "maart 2010"

vSphere PowerCLI] C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI> [datetime] "maart 2010"
Cannot convert value "maart 2010" to type "System.DateTime". Error: "De tekenreeks is niet herkend als een geldige Date
Time. Index 0 begint met een onbekend woord."
At line:1 char:11
+ [datetime] <<<<  "maart 2010"
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

[vSphere PowerCLI] C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI>

For people who don't understand Dutch, I will give a translation of the Dutch words in English:

maandag = monday

maart = March

De tekenreeks is niet herkend als een geldige Date = The characterstring is not recognized as a valid Date

Index 0 begint met een onbekend woord = Index 0 starts with an unknown word

Luc, do you know if there is a way to use.NET typecasting in Dutch instead of English?

Robert

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

If you want to split up a line over multiple lines in your script, you have to use the back-tick.

Like this

Get-VM `
-Name "MyVM"

Otherwise PowerShell considers the 2nd line as a seperate statement.

That's why you get the "Missing expression after unary operator '-'." message. PowerShell considers the 2nd line "-start $from" as a new statement.

The calls to the Get-Stat cmdlet should be inside the loop over the last 12 months. See the attached script.

Btw there is in this case no need to use the MaxSamples parameter.

____________

Blog: LucD notes

Twitter: lucd22


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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Robert,

That behaviour is, in my opinion, a PowerShell "feature".

The "culture" concept is not implemented in all PowerShell features as thorough as it should be.

Since you're using a Dutch PS version, the DateTime casting operator should be able to read the Dutch-formatted datetime string. But apparently it isn't.

Have a look at Keith Hil's [Windows PowerShell 2.0 String Localization|

http://keithhill.spaces.live.com/blog/cns!5A8D2641E0963A97!7132.entry] post.

It contains an improved Using-Culture function. That could be a bypass for this problem.

____________

Blog: LucD notes

Twitter: lucd22


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

Reply
0 Kudos