Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions diagnostics/collect-wsl-logs.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ Param (

Set-StrictMode -Version Latest

# Make wsl.exe emit UTF-8 (instead of UTF-16) and have the console decode it as
# such, so output captured from wsl.exe below is saved to log files readably.
$env:WSL_UTF8 = "1"
try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch {}

function Test-WslApplication {
param (
$Name
Expand Down Expand Up @@ -124,6 +129,20 @@ else
}
}

# Record how these logs were collected so that whoever analyzes the archive
# knows which profile was used (a networking-only capture, for example, will not
# contain the WSL core trace providers).
$logProfileDisplay = if ($LogProfile -eq $null) { "default" } else { $LogProfile }
$wprpProfileDisplay = if ($wprpProfile -ne $null) { $wprpProfile } else { "(default profile in $wprpFile)" }
@"
LogProfile : $logProfileDisplay
WPRP profile : $wprpProfileDisplay
WPRP file : $wprpFile
Dump : $Dump
RestartWslReproMode : $RestartWslReproMode
Collected : $(Get-Date -Format "yyyy-MM-dd HH:mm:ss K")
"@ | Out-File -FilePath "$folder/collection-info.txt" -Encoding utf8

# Networking-specific setup
if ($LogProfile -eq "networking")
{
Expand Down Expand Up @@ -369,10 +388,96 @@ if ($Dump)
if (-not $Result)
{
Write-Host "Failed to write dump for: $($dumpFile)"
# Remove the empty file so the archive isn't littered with 0-byte
# dumps that look like real (but truncated) captures.
Remove-Item $dumpFile -ErrorAction Ignore
}
}
}

# ---------------------------------------------------------------------------
# Write a machine-readable summary and a human/agent-readable index so that
# whoever (or whatever) analyzes the archive has an immediate overview without
# having to run tools or infer state from the individual artifacts.
# ---------------------------------------------------------------------------
function Get-Prop
{
param ($Object, $Name)
if ($Object -ne $null -And ($Object.PSObject.Properties.Name -contains $Name))
{
return $Object.$Name
}
return $null
}

# Inventory the dumps that were actually written (empty ones were removed above).
$dumps = @()
$dumpFolder = Join-Path $folder "dumps"
if (Test-Path $dumpFolder)
{
foreach ($dump in (Get-ChildItem $dumpFolder -Filter *.dmp -ErrorAction Ignore))
{
$dumps += [ordered]@{ name = $dump.Name; sizeBytes = $dump.Length }
}
}

$appx = Get-AppxPackage MicrosoftCorporationII.WindowsSubsystemforLinux -ErrorAction Ignore | Select-Object -First 1
$winCV = Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -ErrorAction Ignore

# Keep this summary basic: profile, versions and the dump inventory. State that
# can be readily derived from the rest of the archive (the installed
# distributions in HKCU.txt, the networking mode in .wslconfig) is intentionally
# not duplicated here.
$summary = [ordered]@{
collectedAt = (Get-Date -Format "o")
logProfile = $logProfileDisplay
wprpProfile = $wprpProfileDisplay
dump = [bool]$Dump
restartWslReproMode = [bool]$RestartWslReproMode
wslVersion = (Get-Prop $appx "Version")
windows = [ordered]@{
build = "$(Get-Prop $winCV 'CurrentBuild').$(Get-Prop $winCV 'UBR')"
displayVersion = Get-Prop $winCV "DisplayVersion"
edition = Get-Prop $winCV "EditionID"
}
wslConfigPresent = [bool](Test-Path $wslconfig)
dumps = $dumps
}
Comment on lines +427 to +445
$summary | ConvertTo-Json -Depth 5 | Out-File -FilePath "$folder/summary.json" -Encoding utf8

# Human/agent-readable index of the archive contents.
@"
Comment thread
benhillis marked this conversation as resolved.
# WSL log collection

Start with ``summary.json`` (machine-readable overview) and
``collection-info.txt`` (how these logs were captured).

> NOTE: ``logs.etl`` is a binary ETW trace. The WSL trace providers are
> TraceLogging (self-describing); decode it with WPA or PerfView for full
> payloads (``tracerpt logs.etl -o logs.csv -of CSV`` works for a quick text
> dump but renders some TraceLogging payloads as raw bytes). If the relevant
> WSL providers are missing, the capture likely used a non-default
> ``-LogProfile`` (see ``collection-info.txt``).

## Key files

| File | What it is |
|------|------------|
| summary.json | Machine-readable overview: profile, versions, dumps. |
| collection-info.txt | Which WPR profile / switches were used for this capture. |
| logs.etl | ETW trace captured during the repro (binary; see note above). |
| dumps/ | Process minidumps (only present with ``-Dump``; empty dumps are removed). |
| HKCU.txt / HKLM.txt | Lxss registry state (distributions, NAT config). |
| windows-version.txt | Windows build / edition. |
| .wslconfig | User's WSL configuration (only if present). |
| wsl-install-log*.txt / wsl-install-logs.txt | Install logs (only if present). |
| wpr.txt | Output from the WPR start/stop commands. |

Networking-profile captures additionally contain ``tcpdump.log``,
``pktmon.etl``, ``wfpdiag.cab``, ``hns_events.log`` and various
``*_before_repro`` / ``*_after_repro`` network state logs.
"@ | Out-File -FilePath "$folder/README.md" -Encoding utf8

$logArchive = "$(Resolve-Path $folder).tar.gz"
tar.exe -czf $logArchive $folder
if ($LASTEXITCODE -eq 0)
Expand Down