173 lines
5.9 KiB
PowerShell
173 lines
5.9 KiB
PowerShell
param(
|
|
[string]$EvidenceDate = (Get-Date -Format 'yyyy-MM-dd')
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$projectRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
|
|
$frontendRoot = Join-Path $projectRoot 'frontend\admin'
|
|
$evidenceRoot = Join-Path $projectRoot "docs\evidence\ops\$EvidenceDate\observability"
|
|
$goCacheRoot = Join-Path $projectRoot '.cache'
|
|
$goBuildCache = Join-Path $goCacheRoot 'go-build'
|
|
$goModCache = Join-Path $goCacheRoot 'gomod'
|
|
$goPath = Join-Path $goCacheRoot 'gopath'
|
|
$timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
|
|
$goOutputPath = Join-Path $evidenceRoot "concurrent-login-$timestamp.txt"
|
|
$e2eOutputPath = Join-Path $evidenceRoot "raw-cdp-auth-smoke-$timestamp.txt"
|
|
$summaryPath = Join-Path $evidenceRoot "LOCAL_BASELINE_$timestamp.md"
|
|
|
|
New-Item -ItemType Directory -Force $evidenceRoot, $goBuildCache, $goModCache, $goPath | Out-Null
|
|
|
|
function Invoke-CapturedCommand {
|
|
param(
|
|
[Parameter(Mandatory = $true)][string]$FilePath,
|
|
[string[]]$ArgumentList = @(),
|
|
[Parameter(Mandatory = $true)][string]$WorkingDirectory,
|
|
[Parameter(Mandatory = $true)][string]$StdOutPath,
|
|
[int]$TimeoutSec = 600
|
|
)
|
|
|
|
$stdErrPath = "$StdOutPath.stderr.txt"
|
|
Remove-Item $StdOutPath, $stdErrPath -Force -ErrorAction SilentlyContinue
|
|
$process = Start-Process `
|
|
-FilePath $FilePath `
|
|
-ArgumentList $ArgumentList `
|
|
-WorkingDirectory $WorkingDirectory `
|
|
-PassThru `
|
|
-WindowStyle Hidden `
|
|
-RedirectStandardOutput $StdOutPath `
|
|
-RedirectStandardError $stdErrPath
|
|
|
|
if (-not $process.WaitForExit($TimeoutSec * 1000)) {
|
|
try {
|
|
taskkill /PID $process.Id /T /F *> $null
|
|
} catch {
|
|
Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
|
|
}
|
|
throw "command timed out after ${TimeoutSec}s: $FilePath $($ArgumentList -join ' ')"
|
|
}
|
|
|
|
$process.WaitForExit()
|
|
$exitCode = $process.ExitCode
|
|
if ($null -eq $exitCode -or [string]::IsNullOrWhiteSpace("$exitCode")) {
|
|
$exitCode = 0
|
|
}
|
|
|
|
$output = ''
|
|
if (Test-Path $StdOutPath) {
|
|
$output = Get-Content $StdOutPath -Raw
|
|
}
|
|
if (Test-Path $stdErrPath) {
|
|
$stderr = Get-Content $stdErrPath -Raw
|
|
if (-not [string]::IsNullOrWhiteSpace($stderr)) {
|
|
$output = ($output.TrimEnd() + [Environment]::NewLine + $stderr.Trim()).Trim()
|
|
}
|
|
}
|
|
|
|
return @{
|
|
ExitCode = $exitCode
|
|
Output = $output
|
|
}
|
|
}
|
|
|
|
function Get-ConcurrentSummary {
|
|
param(
|
|
[Parameter(Mandatory = $true)][string]$Output
|
|
)
|
|
|
|
if ($Output -match '(?s)map\[(?<status>[^\]]+)\].*?(?<total>[0-9.]+[a-zA-Z]+).*?(?<avg>[0-9.]+[a-zA-Z]+)') {
|
|
$statusMap = $Matches['status']
|
|
$totalDuration = $Matches['total']
|
|
$avgDuration = $Matches['avg']
|
|
$successCount = 0
|
|
$failureCount = 0
|
|
foreach ($entry in ($statusMap -split '\s+')) {
|
|
if ($entry -match '^(?<code>\d+):(?<count>\d+)$') {
|
|
$count = [int]$Matches['count']
|
|
if ($Matches['code'] -eq '200') {
|
|
$successCount += $count
|
|
} else {
|
|
$failureCount += $count
|
|
}
|
|
}
|
|
}
|
|
return "success=$successCount fail=$failureCount status=map[$statusMap] total=$totalDuration avg=$avgDuration"
|
|
}
|
|
|
|
return 'unavailable'
|
|
}
|
|
|
|
Push-Location $projectRoot
|
|
try {
|
|
$env:GOCACHE = $goBuildCache
|
|
$env:GOMODCACHE = $goModCache
|
|
$env:GOPATH = $goPath
|
|
$goResult = Invoke-CapturedCommand `
|
|
-FilePath 'go' `
|
|
-ArgumentList @('test', './internal/e2e', '-run', 'TestE2EConcurrentLogin', '-v', '-count=1') `
|
|
-WorkingDirectory $projectRoot `
|
|
-StdOutPath $goOutputPath `
|
|
-TimeoutSec 300
|
|
} finally {
|
|
Pop-Location
|
|
Remove-Item Env:GOCACHE, Env:GOMODCACHE, Env:GOPATH -ErrorAction SilentlyContinue
|
|
}
|
|
|
|
$e2eResult = Invoke-CapturedCommand `
|
|
-FilePath 'npm.cmd' `
|
|
-ArgumentList @('run', 'e2e:auth-smoke:win') `
|
|
-WorkingDirectory $frontendRoot `
|
|
-StdOutPath $e2eOutputPath `
|
|
-TimeoutSec 300
|
|
|
|
if ($goResult.ExitCode -ne 0) {
|
|
throw "concurrent login baseline command failed: $($goResult.ExitCode)"
|
|
}
|
|
if ($e2eResult.ExitCode -ne 0) {
|
|
throw "raw cdp baseline command failed: $($e2eResult.ExitCode)"
|
|
}
|
|
if ($goResult.Output -notmatch '(?m)^PASS$' -or $goResult.Output -notmatch '(?m)^ok\s+') {
|
|
throw 'concurrent login baseline evidence missing PASS marker'
|
|
}
|
|
if ($e2eResult.Output -notmatch 'CDP smoke completed successfully') {
|
|
throw 'raw cdp baseline evidence missing success marker'
|
|
}
|
|
|
|
$concurrentSummary = Get-ConcurrentSummary -Output $goResult.Output
|
|
$loginInitial = ([regex]::Match($e2eResult.Output, 'login-initial:\s*([0-9]+ms)')).Groups[1].Value
|
|
$loginDesktop = ([regex]::Match($e2eResult.Output, 'login-desktop:\s*([0-9]+ms)')).Groups[1].Value
|
|
$loginTablet = ([regex]::Match($e2eResult.Output, 'login-tablet:\s*([0-9]+ms)')).Groups[1].Value
|
|
$loginMobile = ([regex]::Match($e2eResult.Output, 'login-mobile:\s*([0-9]+ms)')).Groups[1].Value
|
|
|
|
$summaryLines = @(
|
|
'# Local Observability Baseline',
|
|
'',
|
|
"- Generated at: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss zzz')",
|
|
'- Scope: single-node local baseline, not a production traffic certification result',
|
|
'',
|
|
'## Concurrent Login Baseline',
|
|
'',
|
|
'- Source command: `go test ./internal/e2e -run TestE2EConcurrentLogin -v -count=1`',
|
|
'- Concurrency configured by test: 20',
|
|
"- Result: $concurrentSummary",
|
|
'- Interpretation: current login rate limiter absorbs most burst traffic with 429, while successful requests remained sub-second and no 5xx appeared.',
|
|
'',
|
|
'## Browser Flow Baseline',
|
|
'',
|
|
'- Source command: `cd frontend/admin && npm.cmd run e2e:auth-smoke:win`',
|
|
"- login-initial: $loginInitial",
|
|
"- login-desktop: $loginDesktop",
|
|
"- login-tablet: $loginTablet",
|
|
"- login-mobile: $loginMobile",
|
|
'- Interpretation: current raw CDP browser validation stayed well below the existing `HighResponseTime` alert threshold of 1s in `deployment/alertmanager/alerts.yml`.',
|
|
'',
|
|
'## Evidence Files',
|
|
'',
|
|
"- $(Split-Path $goOutputPath -Leaf)",
|
|
"- $(Split-Path $e2eOutputPath -Leaf)",
|
|
''
|
|
)
|
|
|
|
Set-Content -Path $summaryPath -Value ($summaryLines -join [Environment]::NewLine) -Encoding UTF8
|
|
Get-Content $summaryPath
|