param( [string]$ArtifactDir = "", [int]$Limit = 20, [string]$OutputPath = "" ) Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" $repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..\..")).ProviderPath if ($ArtifactDir.Trim() -eq "") { $ArtifactDir = Join-Path $repoRoot "artifacts\fabric-loadtest" } if ($OutputPath.Trim() -eq "") { $OutputPath = Join-Path $ArtifactDir ("fabric-acceptance-summary-" + (Get-Date -Format "yyyyMMdd-HHmmss") + ".json") } function Get-PropertyValue { param([object]$Item, [string]$Name, $Default = $null) if ($null -eq $Item -or -not ($Item.PSObject.Properties.Name -contains $Name)) { return $Default } return $Item.$Name } function Convert-RouteModes { param([object]$TargetStats) $modes = [ordered]@{} if ($null -eq $TargetStats) { return $modes } foreach ($targetName in $TargetStats.PSObject.Properties.Name) { $stats = $TargetStats.$targetName $routeModes = Get-PropertyValue -Item $stats -Name "route_modes" if ($null -eq $routeModes) { continue } foreach ($mode in $routeModes.PSObject.Properties.Name) { if (-not $modes.Contains($mode)) { $modes[$mode] = 0 } $modes[$mode] += [int]$routeModes.$mode } } return $modes } function Convert-TargetDistribution { param([object]$TargetStreams) $out = [ordered]@{} if ($null -eq $TargetStreams) { return $out } foreach ($name in $TargetStreams.PSObject.Properties.Name) { $out[$name] = [int]$TargetStreams.$name } return $out } $files = @(Get-ChildItem -LiteralPath $ArtifactDir -Filter "*-summary.json" -File | Sort-Object LastWriteTime -Descending | Select-Object -First $Limit) $runs = @() foreach ($file in $files) { try { $summary = Get-Content -LiteralPath $file.FullName -Raw | ConvertFrom-Json } catch { continue } $runs += [pscustomobject]@{ run_id = Get-PropertyValue -Item $summary -Name "run_id" -Default $file.BaseName verdict = Get-PropertyValue -Item $summary -Name "verdict" verdict_reasons = Get-PropertyValue -Item $summary -Name "verdict_reasons" docker_context = Get-PropertyValue -Item $summary -Name "docker_context" topology_profile = Get-PropertyValue -Item $summary -Name "topology_profile" soak = [bool](Get-PropertyValue -Item $summary -Name "soak" -Default $false) total_streams = [int64](Get-PropertyValue -Item $summary -Name "total_streams" -Default 0) successful_streams = [int64](Get-PropertyValue -Item $summary -Name "successful_streams" -Default 0) failed_streams = [int64](Get-PropertyValue -Item $summary -Name "failed_streams" -Default 0) failover_events = [int64](Get-PropertyValue -Item $summary -Name "failover_events" -Default 0) migration_events = [int64](Get-PropertyValue -Item $summary -Name "migration_events" -Default 0) channel_opens = [int64](Get-PropertyValue -Item $summary -Name "channel_opens" -Default 0) channel_closes = [int64](Get-PropertyValue -Item $summary -Name "channel_closes" -Default 0) channel_leaks = [int64](Get-PropertyValue -Item $summary -Name "channel_leaks" -Default 0) throughput_bps = [int64](Get-PropertyValue -Item $summary -Name "throughput_bps" -Default 0) channel_churn_per_sec = [int64](Get-PropertyValue -Item $summary -Name "channel_churn_per_sec" -Default 0) ack_p95_ms = [int64](Get-PropertyValue -Item $summary -Name "ack_p95_ms" -Default 0) ack_p99_ms = [int64](Get-PropertyValue -Item $summary -Name "ack_p99_ms" -Default 0) setup_latency_p95_ms = [int64](Get-PropertyValue -Item $summary -Name "setup_latency_p95_ms" -Default 0) reroute_latency_p95_ms = [int64](Get-PropertyValue -Item $summary -Name "reroute_latency_p95_ms" -Default 0) route_modes = Convert-RouteModes -TargetStats (Get-PropertyValue -Item $summary -Name "target_stats") target_streams = Convert-TargetDistribution -TargetStreams (Get-PropertyValue -Item $summary -Name "target_streams") container_stats_samples_count = [int](Get-PropertyValue -Item $summary -Name "container_stats_samples_count" -Default 0) summary_path = $file.FullName } } $failed = @($runs | Where-Object { $_.verdict -ne "pass" }) $report = [pscustomobject]@{ schema_version = "rap.fabric_acceptance_summary.v1" generated_at = (Get-Date).ToUniversalTime().ToString("o") artifact_dir = (Resolve-Path $ArtifactDir).ProviderPath runs_considered = $runs.Count pass_count = @($runs | Where-Object { $_.verdict -eq "pass" }).Count fail_count = $failed.Count all_considered_runs_passed = ($failed.Count -eq 0 -and $runs.Count -gt 0) runs = $runs } New-Item -ItemType Directory -Force -Path (Split-Path -Parent $OutputPath) | Out-Null $json = $report | ConvertTo-Json -Depth 30 Set-Content -LiteralPath $OutputPath -Value $json -Encoding UTF8 $json