Public/Get-LatestFlightRecorderDump.ps1
|
# Copyright (c) 2026 Jeffrey Snover. All rights reserved. # Licensed under the MIT License. See LICENSE file in the project root. function Get-LatestFlightRecorderDump { <# .SYNOPSIS Returns the path of the most recent non-stub flight recorder dump. .DESCRIPTION Finds the newest meaningful flight recorder dump so a triage caller does not accidentally pick up a stub. When the Taxonomy Editor writes a dump on startup/shutdown it can emit a tiny stub (ring_buffer_capacity=1, 0 events, ~500 bytes) that is more recent than the real 1.5MB dump recorded earlier — passing the literal "latest" file then yields nothing to triage (the failure this cmdlet exists to prevent, t/1712). Scans the flight-recorder directory ($env:APPDATA\taxonomy-editor\ flight-recorder on Windows, the platform equivalent otherwise, or -Path), keeps only .jsonl files larger than -MinSizeKB (default 10 KB; stubs are always <=1 KB), and returns the most recent survivor's full path. -All returns every survivor newest-first; -MinEvents additionally filters on the header's ring_buffer_events_total. Returns nothing (with a warning) when the directory is missing or holds no non-stub dumps — an empty result is a valid answer, not an error. .PARAMETER Path Flight-recorder directory to scan. Default: the current-OS Electron userData flight-recorder path (see Get-FlightRecorderDir). .PARAMETER All Return the full path of every non-stub dump, sorted newest-first, instead of just the most recent. .PARAMETER MinEvents Additionally require the dump header's ring_buffer_events_total to be at least this value. Dumps whose first line is not a parseable header count as 0 events and are excluded. .PARAMETER MinSizeKB Minimum file size (KB) for a dump to count as non-stub. Default: 10. .EXAMPLE # Path of the most recent meaningful dump — ready to triage Get-LatestFlightRecorderDump .EXAMPLE # Triage the most recent real dump directly Get-LatestFlightRecorderDump | Get-FlightRecorderReport -Detailed .EXAMPLE # All non-stub dumps, newest first Get-LatestFlightRecorderDump -All .EXAMPLE # Most recent dump carrying at least 100 recorded events Get-LatestFlightRecorderDump -MinEvents 100 .LINK Show-AITriadHelp .LINK Get-FlightRecorderDump .LINK Get-FlightRecorderReport .LINK Show-FlightRecorder .LINK Merge-FlightRecorderDumps #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Position = 0)] [string]$Path, [Parameter()] [switch]$All, [Parameter()] [ValidateRange(0, [int]::MaxValue)] [int]$MinEvents, [Parameter()] [ValidateRange(1, 1048576)] [int]$MinSizeKB = 10 ) # Header event-total reader (nested — self-contained to this cmdlet). # A stub / headerless / corrupt first line counts as 0 events. function Get-DumpEventTotal([string]$DumpPath) { $FirstLine = Get-Content -Path $DumpPath -TotalCount 1 -ErrorAction SilentlyContinue if (-not $FirstLine) { return 0 } try { $Header = $FirstLine | ConvertFrom-Json } catch { return 0 } if ($Header.PSObject.Properties['_type'] -and $Header._type -eq 'header' -and $Header.PSObject.Properties['ring_buffer_events_total']) { return [int]$Header.ring_buffer_events_total } return 0 } if (-not $Path) { $Path = Get-FlightRecorderDir } if (-not (Test-Path -Path $Path)) { Write-Warning "Flight recorder dump directory not found: $Path" return } $MinBytes = $MinSizeKB * 1024 $Candidates = @( Get-ChildItem -Path $Path -Filter '*.jsonl' -File | Where-Object { $_.Length -gt $MinBytes } | Sort-Object -Property LastWriteTime -Descending ) if ($PSBoundParameters.ContainsKey('MinEvents')) { $Candidates = @($Candidates | Where-Object { (Get-DumpEventTotal $_.FullName) -ge $MinEvents }) } if ($Candidates.Count -eq 0) { $EventClause = if ($PSBoundParameters.ContainsKey('MinEvents')) { ", >= $MinEvents events" } else { '' } Write-Warning "No non-stub flight recorder dumps (> ${MinSizeKB}KB${EventClause}) found in: $Path" return } if ($All) { foreach ($Dump in $Candidates) { $Dump.FullName } return } $Candidates[0].FullName } |