Export Performance Charts from vCenter for many VMs.

I needed the performance charts for a couple of VMs. It’s an easy task which can be done via the GUI. But I needed the charts for tens of VMs, and needed a faster (and more lazy way), so I write this script that uses the Windows Charting APIs to plot the data from vCenter onto a PNG that I could send to the requester. I though to share the script here so it can help somebody else’s day be a little less grinding. This has been the second time I’ve been asked to deliver this kind of data, see my post from 2014 (which I forgot I made, and assumed I lost the script) So I wrote a new script. So why share it then, because this time it has been written better, and supports two Y-axis. Plotting CPU and RAM values at the same time with the method I used this time wasn’t possible so there you go, more of the same, but different. And you can have may stats plotted, it just dynamically adds data series.

Example chart that this script generates.

Function GenerateChart {
[CmdletBinding()]
param (
    [STRING][Parameter(HelpMessage='Type of chart to generate, see "https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.datavisualization.charting.seriescharttype" Default is "FastLine"')]$ChartType="FastLine",
    [STRING][Parameter(Mandatory,HelpMessage='Please give atleast one VirtualMachine Name')]$VirtualMachine,
    [STRING[]][Parameter(Mandatory,HelpMessage='Please give atleast one statistic, e.g. "cpu.consumed.average"')]$Statistic,
    [STRING][Parameter(HelpMessage='Location the save the generated charts, no need for a trailing "\". Default to TEMP variable')][Alias('Path')]$FilePath=$env:TEMP,
    [INT][Parameter(Mandatory,HelpMessage='Please indicate the timespan in days, for which you need the data')]$Days
)

    $VirtualMachine = Get-VM -Name $VirtualMachine
    $StartDate = (Get-Date).AddDays(-$Days)

    $Statistics = Get-Stat -Entity $VirtualMachine -Stat $Statistic -Start $StartDate | Sort-Object -Property Timestamp,VM | Select-Object @{Name='VirtualMachine';Expression={$_.Entity.Name}},Timestamp,MetricId,Value 

    $Chart = New-Object System.Windows.Forms.DataVisualization.Charting.Chart
    $Chart.Width = 1920
    $Chart.Height = 1080
    $Chart.BackColor = [System.Drawing.Color]::White
             

    [void]$Chart.Titles.Add($Statistics.VirtualMachine[0])
    $Chart.Titles[0].Alignment = "topLeft"
    $ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
    $ChartArea.Name = "ChartArea1"
    $Chart.ChartAreas.Add($ChartArea)
    
    $Statistics | Select-Object -ExpandProperty MetricId | Sort-Object -Unique -Descending | Foreach-Object {
        [STRING]$SeriesName = $_
        
        $SeriesStatistics = $Statistics | Where-Object {$_.MetricId -eq $SeriesName}
        
        [void]$Chart.Series.Add($SeriesName)
        
        $Chart.Series[$SeriesName].ChartType = [System.Windows.Forms.DataVisualization.Charting.SeriesChartType]::$ChartType
        If ($SeriesName -eq "mem.entitlement.average" -or $SeriesName -eq "mem.consumed.average") {
            $ChartArea.AxisY2.Enabled = [System.Windows.Forms.DataVisualization.Charting.AxisEnabled]::True
            $Chart.Series[$SeriesName].YAxisType = [System.Windows.Forms.DataVisualization.Charting.AxisType]::Secondary
        }
        
        $Chart.Series[$SeriesName].Points.DataBindXY($SeriesStatistics.TimeStamp,$SeriesStatistics.Value)
        $Legend = New-Object System.Windows.Forms.DataVisualization.Charting.Legend
        $Legend.IsEquallySpacedItems = $True
        $Legend.Position.Auto = $true
        $Chart.Legends.Add($Legend)
        $ChartArea.RecalculateAxesScale()
    }
    
    $FileName=$FilePath.TrimEnd("\") + "\" + $VirtualMachine + ".png"
    $Chart.SaveImage($FileName,"png")
    Return $FileName
}

[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization") | Out-Null
Import-Module VMware.VimAutomation.Core
Connect-VIServer -Server MyVirtualCenter -User Me -Password MySecr3t!

#Most likely you need information from more than one VM, You could use RegEx, or an inputfile but a single VM is equally possible:
#$VMs = Get-VM | Where-Object {$_.Name -match "(?i)^\D\d{4}srv\D{3}\d{3}"}
#$VMs = Get-Content C:\MyReports\InputList.txt
#$VMs = Import-CSV C:\MyReports\VirtaulMachines.csv -Delimiter ',' | Select-Object $_.VirtualMachineName
$VMs = Get-VM MyVirtualMachine

$Statistic = @(
    "cpu.demand.average",
    "mem.entitlement.average",
    "mem.consumed.average"
)

$VMs | ForEach-Object {
    GenerateChart -ChartType FastLine -VirtualMachine $_ -Statistic "cpu.demand.average","mem.entitlement.average","mem.consumed.average" -Days 7 -FilePath C:\MyReports
}

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.