diff --git a/ScheduledTasks/DailySupportCheck/Invoke-DailySupportCheck.ps1 b/ScheduledTasks/DailySupportCheck/Invoke-DailySupportCheck.ps1
index 45b88e8..41f444c 100644
--- a/ScheduledTasks/DailySupportCheck/Invoke-DailySupportCheck.ps1
+++ b/ScheduledTasks/DailySupportCheck/Invoke-DailySupportCheck.ps1
@@ -393,7 +393,22 @@ function Test-HealthMonitoring {
$provider = $Context.HealthMonitoringProvider
}
- $services = @(& $provider $uri $timeoutSeconds)
+ $services = @((& $provider $uri $timeoutSeconds))
+ $serviceIdValue = if ($services.Count -eq 1 -and $services[0].PSObject.Properties['ServiceId']) { $services[0].ServiceId }
+ $isServiceCollection = $serviceIdValue -is [System.Collections.IEnumerable] -and $serviceIdValue -isnot [string]
+ if ($services.Count -eq 1 -and $isServiceCollection) {
+ $wrappedServices = $services[0]
+ $serviceCount = @($serviceIdValue).Count
+ $services = for ($index = 0; $index -lt $serviceCount; $index++) {
+ $service = [ordered]@{}
+ foreach ($property in $wrappedServices.PSObject.Properties) {
+ $value = $property.Value
+ $isCollection = $value -is [System.Collections.IEnumerable] -and $value -isnot [string]
+ $service[$property.Name] = if ($isCollection -and @($value).Count -eq $serviceCount) { @($value)[$index] } else { $value }
+ }
+ [pscustomobject] $service
+ }
+ }
if ($services.Count -eq 0) {
return Get-CheckResult -Name 'HealthMonitoring' -Status Warning -Summary 'HealthMonitoring returned no monitored services.' -Details @()
}
@@ -403,6 +418,13 @@ function Test-HealthMonitoring {
if ([string]::IsNullOrWhiteSpace($status)) {
$status = 'Unknown'
}
+ $status = switch ($status) {
+ '0' { 'Unknown' }
+ '1' { 'Healthy' }
+ '2' { 'Degraded' }
+ '3' { 'Unhealthy' }
+ default { $status }
+ }
$status = (Get-Culture).TextInfo.ToTitleCase($status.ToLowerInvariant())
[pscustomobject]@{
ServiceId = [string] $service.ServiceId
@@ -980,17 +1002,44 @@ function Write-SupportReports {
[void] $subscriptionDetails.AppendLine('')
}
+ $healthMonitoringDetails = [System.Text.StringBuilder]::new()
+ $healthMonitoringCheck = @($Report.Checks | Where-Object Name -eq 'HealthMonitoring') | Select-Object -First 1
+ $healthMonitoringItems = if ($null -ne $healthMonitoringCheck) {
+ @($healthMonitoringCheck.Details | Where-Object { $_.PSObject.Properties['ServiceId'] })
+ }
+ $healthMonitoringItems = @($healthMonitoringItems)
+ if ($healthMonitoringItems.Count -gt 0) {
+ [void] $healthMonitoringDetails.AppendLine('
HealthMonitoring details
')
+ [void] $healthMonitoringDetails.AppendLine('')
+ }
+
$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))
$subscriptionDetails
+$healthMonitoringDetails
"@
$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 c0445ec..42c67ce 100644
--- a/ScheduledTasks/DailySupportCheck/Tests/Invoke-DailySupportCheck.Tests.ps1
+++ b/ScheduledTasks/DailySupportCheck/Tests/Invoke-DailySupportCheck.Tests.ps1
@@ -163,6 +163,42 @@ Describe 'Daily support check' {
$html | Should -Match 'Main & Ordered'
}
+ It 'renders health-monitoring service details beneath the check summary in the HTML report' {
+ $outputPath = Join-Path $testOutputRoot 'health-monitoring-details'
+ $details = @(
+ [pscustomobject]@{
+ ServiceId = 'orders'
+ Name = 'Orders & Payments'
+ Status = 'Healthy'
+ LastObservedAtUtc = '2026-10-01T15:00:00Z'
+ LastError = $null
+ }
+ [pscustomobject]@{
+ ServiceId = 'payments'
+ Name = 'Payments'
+ Status = 'Unhealthy'
+ LastObservedAtUtc = '2026-10-01T14:59:00Z'
+ LastError = 'Health endpoint unavailable'
+ }
+ )
+ $check = Get-CheckResult -Name 'HealthMonitoring' -Status Failed -Summary '1 monitored service(s) are unhealthy or unknown.' -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 'HealthMonitoring details'
+ $html | Should -Match 'Service ID | Name | Status | '
+ $html | Should -Match 'orders'
+ $html | Should -Match 'Orders & Payments'
+ $html | Should -Match 'Health endpoint unavailable'
+ $html | Should -Match 'status-Healthy'
+ $html | Should -Match 'status-Unhealthy'
+ $html | Should -Match '🔴 Unhealthy'
+ $html | Should -Match '\.status-Passed,.status-Healthy\{background:#e4f4e4\}'
+ $html | Should -Match '\.status-Failed,.status-Unhealthy\{background:#fde2e2\}'
+ }
+
It 'removes matching reports older than the configured retention period' {
$outputPath = Join-Path $testOutputRoot 'retention'
New-Item -ItemType Directory -Path $outputPath -Force | Out-Null
@@ -456,6 +492,65 @@ Describe 'Daily support check' {
$result.Summary | Should -Match '2 monitored service'
}
+ It 'expands wrapped enumerable health-monitoring services returned by the API' {
+ $context = [pscustomobject]@{
+ Configuration = [pscustomobject]@{
+ HealthMonitoring = [pscustomobject]@{
+ Enabled = $true
+ BaseUrl = 'http://health-monitoring'
+ ServicesPath = '/api/services'
+ TimeoutSeconds = 10
+ }
+ }
+ HealthMonitoringProvider = {
+ [pscustomobject]@{
+ ServiceId = [System.Collections.ArrayList]::new(@('orders', 'payments'))
+ Name = [System.Collections.ArrayList]::new(@('Orders', 'Payments'))
+ Status = [System.Collections.ArrayList]::new(@(1, 1))
+ LastObservedAtUtc = $null
+ LastError = $null
+ }
+ }
+ }
+
+ $result = Test-HealthMonitoring -Context $context
+
+ $result.Status | Should -Be 'Passed'
+ $result.Details.Count | Should -Be 2
+ $result.Details[0].ServiceId | Should -Be 'orders'
+ $result.Details[0].Name | Should -Be 'Orders'
+ $result.Details[0].Status | Should -Be 'Healthy'
+ $result.Details[1].ServiceId | Should -Be 'payments'
+ $result.Details[1].Name | Should -Be 'Payments'
+ $result.Details[1].Status | Should -Be 'Healthy'
+ }
+
+ It 'unwraps an array returned as one health-monitoring provider result' {
+ $context = [pscustomobject]@{
+ Configuration = [pscustomobject]@{
+ HealthMonitoring = [pscustomobject]@{
+ Enabled = $true
+ BaseUrl = 'http://health-monitoring'
+ ServicesPath = '/api/services'
+ TimeoutSeconds = 10
+ }
+ }
+ HealthMonitoringProvider = {
+ $apiResponse = @(
+ [pscustomobject]@{ ServiceId = 'orders'; Name = 'Orders'; Status = 1 }
+ [pscustomobject]@{ ServiceId = 'payments'; Name = 'Payments'; Status = 1 }
+ )
+ ,$apiResponse
+ }
+ }
+
+ $result = Test-HealthMonitoring -Context $context
+
+ $result.Status | Should -Be 'Passed'
+ $result.Details.Count | Should -Be 2
+ $result.Details.ServiceId | Should -Be @('orders', 'payments')
+ }
+
It 'returns Warning for degraded services and Failed for unhealthy services' {
$configuration = [pscustomobject]@{
HealthMonitoring = [pscustomobject]@{