Private/Export-HtmlReport.ps1
|
function Export-HtmlReport { [CmdletBinding()] param( [Parameter(Mandatory)] $Counters, [Parameter(Mandatory)] [string] $ConfigName, [Parameter(Mandatory)] [string] $HtmlFilePath, [Parameter(Mandatory)] [DateTime] $StartTime, [Parameter(Mandatory)] [int] $SampleCount, [Parameter(Mandatory)] [int] $UpdateInterval, [ValidateSet('Counter', 'Host')] [string] $GroupBy = 'Counter' ) if (-not (Get-Module -Name PSWriteHTML -ListAvailable)) { throw "PSWriteHTML module is required for HTML export. Install it with: Install-Module PSWriteHTML" } Import-Module PSWriteHTML -ErrorAction Stop # ── Pre-compute all data before entering New-HTML ───────────────────────── # PSWriteHTML invokes scriptblocks in module scope, so all data must be in $script: $script:psTPC_html_colors = @('#007acc', '#ff6b35', '#4caf50', '#ff9800', '#9c27b0', '#e91e63', '#00bcd4', '#795548') $script:psTPC_html_active = @($Counters | Where-Object { $_.IsAvailable -and $_.HistoricalData.Count -gt 0 }) $script:psTPC_html_configName = $ConfigName $script:psTPC_html_startTime = $StartTime $script:psTPC_html_sample = $SampleCount $script:psTPC_html_interval = $UpdateInterval $script:psTPC_html_lastUpdate = Get-Date -Format 'HH:mm:ss' # Overview table — same columns as TUI table $script:psTPC_html_overview = foreach ($c in $script:psTPC_html_active) { $stats = $c.Statistics [PSCustomObject]@{ 'Computer' = $c.ComputerName 'Counter' = $c.Title 'Unit' = $c.Unit 'Current' = if ($stats.ContainsKey('Current')) { $stats['Current'] } else { '-' } 'Min' = if ($stats.ContainsKey('Minimum')) { $stats['Minimum'] } else { '-' } 'Max' = if ($stats.ContainsKey('Maximum')) { $stats['Maximum'] } else { '-' } 'Avg' = if ($stats.ContainsKey('Average')) { $stats['Average'] } else { '-' } 'ExecTime' = if ($null -ne $c.LastUpdate) { $c.LastUpdate.ToString('HH:mm:ss') } else { '-' } 'Dur.ms' = if ($null -ne $c.ExecutionDuration) { $c.ExecutionDuration } else { '-' } 'Samples' = $c.HistoricalData.Count } } # Combined chart — all counters, all hosts $script:psTPC_html_allLabels = @() $script:psTPC_html_allSeries = @() if ($script:psTPC_html_active.Count -gt 0) { $script:psTPC_html_allLabels = @($script:psTPC_html_active[0].HistoricalData | ForEach-Object { $_.Timestamp.ToString('HH:mm:ss') }) $ci = 0 $script:psTPC_html_allSeries = @(foreach ($c in $script:psTPC_html_active) { [PSCustomObject]@{ Name = "$($c.ComputerName) - $($c.Title) ($($c.Unit))" Values = @($c.HistoricalData | ForEach-Object { $_.Value }) Color = $script:psTPC_html_colors[$ci % $script:psTPC_html_colors.Count] } $ci++ }) } # Grouped chart data # GroupBy=Counter → one tab per counter type, series = one per host # GroupBy=Host → one tab per host, series = one per counter $grouping = if ($GroupBy -eq 'Counter') { $script:psTPC_html_active | Group-Object -Property Title } else { $script:psTPC_html_active | Group-Object -Property ComputerName } $script:psTPC_html_groups = @(foreach ($g in $grouping) { $gCounters = @($g.Group) $gLabels = @($gCounters[0].HistoricalData | ForEach-Object { $_.Timestamp.ToString('HH:mm:ss') }) $ci2 = 0 $gSeries = @(foreach ($gc in $gCounters) { $sName = if ($GroupBy -eq 'Counter') { $gc.ComputerName } else { "$($gc.Title) ($($gc.Unit))" } [PSCustomObject]@{ Name = $sName Values = @($gc.HistoricalData | ForEach-Object { $_.Value }) Color = $script:psTPC_html_colors[$ci2 % $script:psTPC_html_colors.Count] } $ci2++ }) [PSCustomObject]@{ Name = $g.Name Labels = $gLabels Series = $gSeries } }) # ── HTML ────────────────────────────────────────────────────────────────── New-HTML -TitleText "psTerminalPerfCounter - $script:psTPC_html_configName" -FilePath $HtmlFilePath -ShowHTML:$false { New-HTMLSection -HeaderText "Session: $script:psTPC_html_configName" -HeaderBackGroundColor DarkSlateGray { New-HTMLPanel { New-HTMLText -Text @( "Started: $($script:psTPC_html_startTime.ToString('dd.MM.yyyy HH:mm:ss'))" "Sample: $script:psTPC_html_sample" "Interval: $($script:psTPC_html_interval)s" "Last Update: $script:psTPC_html_lastUpdate" ) -FontSize 14 -Color White -LineBreak } } New-HTMLTabPanel { # ── Tab: Overview table ─────────────────────────────────────────── New-HTMLTab -Name "Overview" -IconSolid "table" { New-HTMLSection -HeaderText "Counter Overview" { New-HTMLTable -DataTable $script:psTPC_html_overview -HideFooter -ScrollX { New-TableCondition -Name 'Samples' -ComparisonType number -Operator lt -Value 5 ` -BackgroundColor Orange -Color White } } } # ── Tab: All counters combined ──────────────────────────────────── New-HTMLTab -Name "All Counters" -IconSolid "chart-line" { New-HTMLSection -HeaderText "All Counters" { New-HTMLChart { New-ChartAxisX -Name $script:psTPC_html_allLabels foreach ($s in $script:psTPC_html_allSeries) { New-ChartLine -Name $s.Name -Value $s.Values -Color $s.Color } } } } # ── Tab per group (Counter or Host) ─────────────────────────────── # PSWriteHTML executes scriptblocks synchronously (builder pattern), # so $script:psTPC_html_gd is captured correctly each iteration. for ($script:psTPC_html_gi = 0; $script:psTPC_html_gi -lt $script:psTPC_html_groups.Count; $script:psTPC_html_gi++) { $script:psTPC_html_gd = $script:psTPC_html_groups[$script:psTPC_html_gi] New-HTMLTab -Name $script:psTPC_html_gd.Name { New-HTMLSection -HeaderText $script:psTPC_html_gd.Name { New-HTMLChart { New-ChartAxisX -Name $script:psTPC_html_gd.Labels foreach ($s in $script:psTPC_html_gd.Series) { New-ChartLine -Name $s.Name -Value $s.Values -Color $s.Color } } } } } } } -Online } |