Assets/Get-OpsJobHistory.ps1
|
<# .SYNOPSIS Gets the history of Ops Jobs based on the NDJSON history logs. .PARAMETER JobName Optional specific job name. Supports wildcards. .PARAMETER Count Number of recent entries to return. #> param ( [string]$JobName = "*", [ValidateRange(1, [int]::MaxValue)] [int]$Count = 10 ) # The Ops root defaults to C:\Ops. OPS_ROOT overrides it for development and # testing, matching the dashboard server's existing convention. $OpsRoot = if ([string]::IsNullOrWhiteSpace($env:OPS_ROOT)) { "C:\Ops" } else { $env:OPS_ROOT } $LogDir = Join-Path $OpsRoot "Logs" if (-not (Test-Path -Path $LogDir)) { return @() } $Files = @(Get-ChildItem -Path $LogDir -Filter "$JobName.history.json" -File -ErrorAction SilentlyContinue) $Results = [System.Collections.Generic.List[object]]::new() foreach ($File in $Files) { # The history file is newline-delimited JSON, not a JSON document. Piping the # whole file into ConvertFrom-Json concatenates the lines and fails outright on # PowerShell 5.1; a single truncated line would also discard the entire file. # Parse line by line and skip anything unreadable. $Entries = [System.Collections.Generic.List[object]]::new() foreach ($Line in (Get-Content -Path $File.FullName -ErrorAction SilentlyContinue)) { if ([string]::IsNullOrWhiteSpace($Line)) { continue } try { $Entries.Add(($Line | ConvertFrom-Json)) } catch { Write-Verbose "Skipping malformed history line in $($File.Name): $Line" } } # '.history' as a -replace pattern is a regex whose dot matches any character. $Name = $File.BaseName -replace '\.history$', '' $RelevantEntries = $Entries | Where-Object { $_.Message -match "Job completed successfully" -or $_.Level -eq "ERROR" } | Sort-Object Timestamp -Descending | Select-Object -First $Count foreach ($Entry in $RelevantEntries) { $Status = "Unknown" if ($Entry.Level -eq "ERROR") { $Status = "Failed" } elseif ($Entry.Message -match "Job completed successfully") { $Status = "Success" } $Results.Add([PSCustomObject]@{ JobName = $Name Timestamp = $Entry.Timestamp Status = $Status Message = $Entry.Message }) } } return $Results | Sort-Object Timestamp -Descending | Select-Object -First $Count |