Public/Get-FlightRecorderDump.ps1
|
# Copyright (c) 2026 Jeffrey Snover. All rights reserved. # Licensed under the MIT License. See LICENSE file in the project root. function Get-FlightRecorderDump { <# .SYNOPSIS Lists or retrieves flight recorder dump files from the Taxonomy Editor. .DESCRIPTION Scans the Taxonomy Editor's userData directory for flight recorder dump files (.jsonl). Returns file info objects that can be piped to Show-FlightRecorder for viewing. .PARAMETER Last Return only the N most recent dump files. Default: returns all. .PARAMETER DumpDir Override the default dump directory. Default: auto-detected from Electron userData path. .EXAMPLE # List all dump files Get-FlightRecorderDump .EXAMPLE # Get the most recent dump Get-FlightRecorderDump -Last 1 .EXAMPLE # Get last 5 dumps and show details Get-FlightRecorderDump -Last 5 | Format-Table Name, Length, LastWriteTime .EXAMPLE # Open the most recent dump in the viewer Get-FlightRecorderDump -Last 1 | Show-FlightRecorder #> [CmdletBinding()] param( [Parameter()] [int]$Last, [Parameter()] [string]$DumpDir ) if (-not $DumpDir) { # Auto-detect Electron userData path if ($IsMacOS) { $DumpDir = Join-Path $HOME 'Library/Application Support/taxonomy-editor/flight-recorder' } elseif ($IsWindows) { $DumpDir = Join-Path $env:APPDATA 'taxonomy-editor/flight-recorder' } else { $DumpDir = Join-Path $HOME '.config/taxonomy-editor/flight-recorder' } } if (-not (Test-Path $DumpDir)) { Write-Warning "Flight recorder dump directory not found: $DumpDir" Write-Warning "Run the Taxonomy Editor and click 'Dump Log' to create a dump." return } $files = Get-ChildItem -Path $DumpDir -Filter 'flight-recorder-*.jsonl' | Sort-Object LastWriteTime -Descending if ($files.Count -eq 0) { Write-Warning "No flight recorder dump files found in: $DumpDir" return } if ($Last -gt 0) { $files = $files | Select-Object -First $Last } # Add parsed summary info to each file foreach ($file in $files) { $summary = @{ EventCount = 0 ErrorCount = 0 TriggerType = $null AppVersion = $null DebateId = $null } # Parse first few lines for header/trigger info $lines = Get-Content $file.FullName -TotalCount 5 foreach ($line in $lines) { try { $obj = $line | ConvertFrom-Json if ($obj._type -eq 'header') { $summary.EventCount = $obj.ring_buffer_events_retained $summary.AppVersion = $obj.app_version $summary.DebateId = $obj.active_debate_id } if ($obj._type -eq 'trigger') { $summary.TriggerType = $obj.trigger_type } } catch { } } # Count errors by scanning event lines $errorMatches = Select-String -Path $file.FullName -Pattern '"level"\s*:\s*"(error|fatal)"' -AllMatches $errorCount = if ($errorMatches) { @($errorMatches.Matches).Count } else { 0 } $file | Add-Member -NotePropertyName Events -NotePropertyValue $summary.EventCount -Force $file | Add-Member -NotePropertyName Errors -NotePropertyValue $errorCount -Force $file | Add-Member -NotePropertyName Trigger -NotePropertyValue $summary.TriggerType -Force $file | Add-Member -NotePropertyName AppVersion -NotePropertyValue $summary.AppVersion -Force $file | Add-Member -NotePropertyName DebateId -NotePropertyValue $summary.DebateId -Force $file } } |