From fa09c7de440fc059c61827d5d3a70a523a2be4e5 Mon Sep 17 00:00:00 2001 From: StuartFerguson Date: Thu, 1 Oct 2026 13:40:33 +0100 Subject: [PATCH] feat: include subscription details in email report --- .../Invoke-DailySupportCheck.ps1 | 41 ++++++++++++++++++- .../Tests/Invoke-DailySupportCheck.Tests.ps1 | 38 +++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/ScheduledTasks/DailySupportCheck/Invoke-DailySupportCheck.ps1 b/ScheduledTasks/DailySupportCheck/Invoke-DailySupportCheck.ps1 index 5f2f9a2..1188c4f 100644 --- a/ScheduledTasks/DailySupportCheck/Invoke-DailySupportCheck.ps1 +++ b/ScheduledTasks/DailySupportCheck/Invoke-DailySupportCheck.ps1 @@ -916,6 +916,16 @@ function ConvertTo-ReportText { return ($Value | ConvertTo-Json -Depth 8 -Compress) } +function ConvertTo-HtmlEncodedText { + param([object] $Value) + + if ($null -eq $Value -or [string]::IsNullOrWhiteSpace([string] $Value)) { + return '—' + } + + [System.Net.WebUtility]::HtmlEncode([string] $Value) +} + function Write-SupportReports { [CmdletBinding()] param( @@ -954,16 +964,45 @@ function Write-SupportReports { [void] $rows.AppendLine("$name$statusIcon $status$summary") } + $subscriptionDetails = [System.Text.StringBuilder]::new() + $subscriptionCheck = @($Report.Checks | Where-Object Name -eq 'Subscription Service') | Select-Object -First 1 + $subscriptionItems = if ($null -ne $subscriptionCheck) { + @($subscriptionCheck.Details | Where-Object { $_.PSObject.Properties['SubscriptionId'] }) + } + $subscriptionItems = @($subscriptionItems) + if ($subscriptionItems.Count -gt 0) { + [void] $subscriptionDetails.AppendLine('

Subscription Service details

') + [void] $subscriptionDetails.AppendLine('
') + foreach ($subscription in $subscriptionItems) { + $detailStatus = ConvertTo-HtmlEncodedText $subscription.Status + $detailStatusClass = [System.Net.WebUtility]::HtmlEncode("status-$([string] $subscription.Status)") + $detailStatusIcon = switch ([string] $subscription.Status) { + 'Passed' { '🟢' } + 'Warning' { '🟠' } + 'Failed' { '🔴' } + default { '⚪' } + } + $reasonParts = @( + if ($subscription.PSObject.Properties['operationalReason'] -and -not [string]::IsNullOrWhiteSpace([string] $subscription.OperationalReason)) { "Operational: $($subscription.OperationalReason)" } + if ($subscription.PSObject.Properties['runtimeFailureReason'] -and -not [string]::IsNullOrWhiteSpace([string] $subscription.RuntimeFailureReason)) { "Runtime: $($subscription.RuntimeFailureReason)" } + ) + $reason = ConvertTo-HtmlEncodedText ($reasonParts -join '; ') + [void] $subscriptionDetails.AppendLine("") + } + [void] $subscriptionDetails.AppendLine('
SubscriptionTagStatusRunningHealthParkedReason
$(ConvertTo-HtmlEncodedText $subscription.SubscriptionId)$(ConvertTo-HtmlEncodedText $subscription.Tag)$detailStatusIcon $detailStatus$(ConvertTo-HtmlEncodedText $subscription.IsRunning)$(ConvertTo-HtmlEncodedText $subscription.Health)$(ConvertTo-HtmlEncodedText $subscription.ParkedEventCount)$reason
') + } + $overallStatus = [System.Net.WebUtility]::HtmlEncode([string] $Report.OverallStatus) $html = @" Daily Support Check - +

Daily Support Check

Overall status: $overallStatus

Started: $([System.Net.WebUtility]::HtmlEncode([string] $Report.StartedAt))
Completed: $([System.Net.WebUtility]::HtmlEncode([string] $Report.CompletedAt))

$rows
CheckStatusSummary
+$subscriptionDetails "@ $html | Set-Content -LiteralPath $htmlPath -Encoding UTF8 diff --git a/ScheduledTasks/DailySupportCheck/Tests/Invoke-DailySupportCheck.Tests.ps1 b/ScheduledTasks/DailySupportCheck/Tests/Invoke-DailySupportCheck.Tests.ps1 index 177aca6..5a4087b 100644 --- a/ScheduledTasks/DailySupportCheck/Tests/Invoke-DailySupportCheck.Tests.ps1 +++ b/ScheduledTasks/DailySupportCheck/Tests/Invoke-DailySupportCheck.Tests.ps1 @@ -125,6 +125,44 @@ Describe 'Daily support check' { $html | Should -Not -Match 'error <text>' } + It 'renders subscription details beneath the check summary in the HTML report' { + $outputPath = Join-Path $testOutputRoot 'subscription-details' + $details = @( + [pscustomobject]@{ + SubscriptionId = 'subscription-1' + Tag = 'Main & Ordered' + Status = 'Passed' + IsRunning = $true + Health = 'Healthy' + ParkedEventCount = 0 + OperationalReason = $null + RuntimeFailureReason = $null + } + [pscustomobject]@{ + SubscriptionId = 'subscription-2' + Tag = 'Main' + Status = 'Warning' + IsRunning = $true + Health = 'Healthy' + ParkedEventCount = 3 + OperationalReason = 'Parked messages detected' + RuntimeFailureReason = $null + } + ) + $check = Get-CheckResult -Name 'Subscription Service' -Status Warning -Summary '1 subscription(s) have parked messages.' -Details $details + $report = Get-SupportReport -StartedAt ([datetime]::UtcNow) -Results @($check) + + $paths = Write-SupportReports -Report $report -OutputPath $outputPath + $html = Get-Content -Raw -Path $paths.HtmlPath + + $html | Should -Match 'Subscription Service details' + $html | Should -Match 'SubscriptionTagStatus' + $html | Should -Match 'subscription-1' + $html | Should -Match 'subscription-2' + $html | Should -Match 'Parked messages detected' + $html | Should -Match 'Main & Ordered' + } + It 'removes matching reports older than the configured retention period' { $outputPath = Join-Path $testOutputRoot 'retention' New-Item -ItemType Directory -Path $outputPath -Force | Out-Null