Skip to content

Commit a1c976d

Browse files
author
vp
committed
Refactor flame, CPU, and GC trace commands for improved duration selection and speedscope handling
1 parent bc250e5 commit a1c976d

1 file changed

Lines changed: 45 additions & 90 deletions

File tree

.vscode/tasks-diagnostics.ps1

Lines changed: 45 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -100,136 +100,91 @@ switch($Command.ToLowerInvariant()){
100100
'trace-flame' {
101101
Ensure-Tool 'dotnet-counters' 'dotnet-counters'
102102
Ensure-Tool 'dotnet-trace' 'dotnet-trace'
103-
$script:DotNetOnly = $true
104-
# Duration selection (interactive)
105-
$durationsMap = [ordered]@{ '10 sec'='00:00:10'; '30 sec'='00:00:30'; '1 min'='00:01:00'; '5 min'='00:05:00' }
106-
$duration = $durationsMap['10 sec']
107-
try {
108-
Import-Module PwshSpectreConsole -ErrorAction Stop
109-
$choice = Read-SpectreSelection -Title 'Select flame trace duration' -Choices ($durationsMap.Keys + 'Cancel') -EnableSearch -PageSize 10
110-
if($choice -and $choice -ne 'Cancel'){ $duration = $durationsMap[$choice] }
111-
if($choice -eq 'Cancel'){ Write-Host 'Flame trace cancelled.' -ForegroundColor Yellow; break }
112-
} catch { Write-Host 'Spectre selection unavailable; using default 10 sec.' -ForegroundColor Yellow }
113-
$procId = Select-Pid 'Select process to trace (flame)'
114-
if(-not $procId){ Write-Host 'No PID selected.' -ForegroundColor Yellow; break }
103+
$script:DotNetOnly = $true
104+
$durationsMap = [ordered]@{ '10 sec'='00:00:10'; '30 sec'='00:00:30'; '1 min'='00:01:00'; '5 min'='00:05:00' }
105+
$duration = $durationsMap['10 sec']
106+
try { Import-Module PwshSpectreConsole -ErrorAction Stop; $choice = Read-SpectreSelection -Title 'Select flame trace duration' -Choices ($durationsMap.Keys + 'Cancel') -EnableSearch -PageSize 10; if($choice -and $choice -ne 'Cancel'){ $duration = $durationsMap[$choice] }; if($choice -eq 'Cancel'){ Write-Host 'Flame trace cancelled.' -ForegroundColor Yellow; break } } catch { Write-Host 'Spectre selection unavailable; using default 10 sec.' -ForegroundColor Yellow }
107+
$procId = Select-Pid 'Select process to trace (flame)'
108+
if(-not $procId){ Write-Host 'No PID selected.' -ForegroundColor Yellow; break }
115109
$outDir = Join-Path $PSScriptRoot '..' '.tmp' 'diagnostics'
116110
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
117-
$fileBase = "trace_${procId}_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
118-
$traceFile = Join-Path $outDir "$fileBase.nettrace"
119-
$speedFile = Join-Path $outDir "$fileBase"
120-
Write-Host "Collecting flame trace (SampleProfiler, $duration) for PID $procId ..." -ForegroundColor Cyan
121-
& dotnet-trace collect --process-id $procId --providers Microsoft-DotNETCore-SampleProfiler:1 --duration $duration -o $traceFile
122-
if($LASTEXITCODE -ne 0){
123-
Write-Host 'SampleProfiler provider failed, retrying with default trace config (cpu+gc)...' -ForegroundColor Yellow
124-
& dotnet-trace collect --process-id $procId --duration $duration -o $traceFile
125-
if($LASTEXITCODE -ne 0){ throw 'Trace collection failed (fallback also failed)' }
126-
}
111+
$fileBase = "trace_${procId}_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
112+
$traceFile = Join-Path $outDir "$fileBase.nettrace"
113+
$speedBase = Join-Path $outDir $fileBase
114+
try { Import-Module PwshSpectreConsole -ErrorAction Stop; @( 'Flame Trace','PID: ' + $procId,'Duration: ' + $duration,'Providers: SampleProfiler','Artifacts Base: ' + $fileBase ) | Format-SpectreRows | Format-SpectrePanel -Expand } catch {}
115+
Write-Host "Collecting flame trace (SampleProfiler, $duration) for PID $procId ..." -ForegroundColor Cyan
116+
& dotnet-trace collect --process-id $procId --providers Microsoft-DotNETCore-SampleProfiler:1 --duration $duration -o $traceFile
117+
if($LASTEXITCODE -ne 0){ Write-Host 'SampleProfiler provider failed, retrying with default trace config (cpu+gc)...' -ForegroundColor Yellow; & dotnet-trace collect --process-id $procId --duration $duration -o $traceFile; if($LASTEXITCODE -ne 0){ throw 'Trace collection failed (fallback also failed)' } }
127118
Write-Host 'Converting to speedscope...' -ForegroundColor Cyan
128-
& dotnet-trace convert --format SpeedScope $traceFile -o $speedFile
119+
& dotnet-trace convert --format SpeedScope $traceFile -o $speedBase
129120
if($LASTEXITCODE -ne 0){ throw 'Trace conversion failed' }
130-
Write-Host "Trace complete: $traceFile" -ForegroundColor Green
131-
Write-Host "Speedscope file: $speedFile" -ForegroundColor Green
132-
# Auto-open speedscope view
133-
try {
134-
$speedFile = $speedFile + '.speedscope.json'
135-
$resolvedSpeed = (Resolve-Path $speedFile).Path
136-
if(-not (Test-Path $resolvedSpeed)) { throw "Speedscope file not found: $resolvedSpeed" }
137-
if(Get-Command npx -ErrorAction SilentlyContinue){
138-
Write-Host "Opening speedscope (npx) -> $resolvedSpeed" -ForegroundColor Cyan
139-
& npx speedscope "$resolvedSpeed"
140-
if($LASTEXITCODE -ne 0){ Write-Host 'npx speedscope returned non-zero; fallback to browser.' -ForegroundColor Yellow; Start-Process 'https://www.speedscope.app'; Start-Process explorer.exe (Split-Path $resolvedSpeed -Parent) }
141-
} else {
142-
Write-Host 'npx not available; opening speedscope.app and folder.' -ForegroundColor Yellow
143-
Start-Process 'https://www.speedscope.app'
144-
Start-Process explorer.exe (Split-Path $resolvedSpeed -Parent)
145-
}
146-
} catch { Write-Host "Speedscope auto-open failed: $($_.Exception.Message)" -ForegroundColor Yellow }
121+
Write-Host "Trace complete: $traceFile" -ForegroundColor Green
122+
$speedFile = $speedBase + '.speedscope.json'
123+
if(Test-Path "$speedFile.speedscope.json"){ Move-Item -Force "$speedFile.speedscope.json" $speedFile }
124+
Write-Host "Speedscope file: $speedFile" -ForegroundColor Green
125+
if(-not $env:TRACE_NO_VIEW){
126+
try { $resolvedSpeed = (Resolve-Path $speedFile).Path; if(-not (Test-Path $resolvedSpeed)){ throw "Speedscope file not found: $resolvedSpeed" }; if(Get-Command npx -ErrorAction SilentlyContinue){ Write-Host "Opening speedscope (npx) -> $resolvedSpeed" -ForegroundColor Cyan; & npx speedscope "$resolvedSpeed"; if($LASTEXITCODE -ne 0){ Write-Host 'npx speedscope returned non-zero; fallback to browser.' -ForegroundColor Yellow; Start-Process 'https://www.speedscope.app'; Start-Process explorer.exe (Split-Path $resolvedSpeed -Parent) } } else { Write-Host 'npx not available; opening speedscope.app and folder.' -ForegroundColor Yellow; Start-Process 'https://www.speedscope.app'; Start-Process explorer.exe (Split-Path $resolvedSpeed -Parent) } } catch { Write-Host "Speedscope auto-open failed: $($_.Exception.Message)" -ForegroundColor Yellow }
127+
} else { Write-Host 'TRACE_NO_VIEW set; skipping auto-open.' -ForegroundColor DarkYellow }
147128
}
148129
'trace-cpu' {
149130
Ensure-Tool 'dotnet-trace' 'dotnet-trace'
150131
$script:DotNetOnly = $true
151-
# Duration selection (interactive)
152132
$durationsMap = [ordered]@{ '10 sec'='00:00:10'; '30 sec'='00:00:30'; '1 min'='00:01:00'; '5 min'='00:05:00' }
153133
$duration = $durationsMap['10 sec']
154-
try {
155-
Import-Module PwshSpectreConsole -ErrorAction Stop
156-
$choice = Read-SpectreSelection -Title 'Select trace duration' -Choices ($durationsMap.Keys + 'Cancel') -EnableSearch -PageSize 10
157-
if($choice -and $choice -ne 'Cancel'){ $duration = $durationsMap[$choice] }
158-
if($choice -eq 'Cancel'){ Write-Host 'CPU trace cancelled.' -ForegroundColor Yellow; break }
159-
} catch { Write-Host 'Spectre selection unavailable; using default 10 sec.' -ForegroundColor Yellow }
134+
try { Import-Module PwshSpectreConsole -ErrorAction Stop; $choice = Read-SpectreSelection -Title 'Select trace duration' -Choices ($durationsMap.Keys + 'Cancel') -EnableSearch -PageSize 10; if($choice -and $choice -ne 'Cancel'){ $duration = $durationsMap[$choice] }; if($choice -eq 'Cancel'){ Write-Host 'CPU trace cancelled.' -ForegroundColor Yellow; break } } catch { Write-Host 'Spectre selection unavailable; using default 10 sec.' -ForegroundColor Yellow }
160135
$procId = Select-Pid 'Select process for CPU trace'
161136
if(-not $procId){ Write-Host 'No PID selected.' -ForegroundColor Yellow; break }
162137
$outDir = Join-Path $PSScriptRoot '..' '.tmp' 'diagnostics'
163138
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
164139
$fileBase = "cpu_${procId}_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
165140
$traceFile = Join-Path $outDir "$fileBase.nettrace"
166-
$speedFile = Join-Path $outDir "$fileBase"
167-
Write-Host "Collecting CPU trace (SampleProfiler, $duration) for PID $procId ..." -ForegroundColor Cyan
168-
& dotnet-trace collect --process-id $procId --providers Microsoft-DotNETCore-SampleProfiler:1 --duration $duration -o $traceFile
141+
$speedBase = Join-Path $outDir $fileBase
142+
$extended = $false
143+
try { Import-Module PwshSpectreConsole -ErrorAction Stop; $provChoice = Read-SpectreSelection -Title 'Include extended runtime providers?' -Choices @('No','Yes','Cancel') -EnableSearch -PageSize 5; if($provChoice -eq 'Cancel'){ Write-Host 'CPU trace cancelled.' -ForegroundColor Yellow; break }; if($provChoice -eq 'Yes'){ $extended = $true } } catch { Write-Host 'Provider selection skipped (Spectre unavailable).' -ForegroundColor Yellow }
144+
$providers = 'Microsoft-DotNETCore-SampleProfiler:1,System.Runtime:4'
145+
if($extended){ $providers += ',Microsoft-DotNETCore-EventSource:5' }
146+
try { Import-Module PwshSpectreConsole -ErrorAction Stop; @( 'CPU Trace','PID: ' + $procId,'Duration: ' + $duration,'Providers: ' + $providers,'Extended: ' + $extended,'Artifacts Base: ' + $fileBase ) | Format-SpectreRows | Format-SpectrePanel -Expand } catch {}
147+
Write-Host "Collecting CPU trace ($providers, $duration) for PID $procId ..." -ForegroundColor Cyan
148+
& dotnet-trace collect --process-id $procId --providers $providers --duration $duration -o $traceFile
169149
if($LASTEXITCODE -ne 0){ throw 'CPU trace collection failed' }
170150
Write-Host 'Converting to speedscope...' -ForegroundColor Cyan
171-
& dotnet-trace convert --format SpeedScope $traceFile -o $speedFile
151+
& dotnet-trace convert --format SpeedScope $traceFile -o $speedBase
172152
if($LASTEXITCODE -ne 0){ throw 'CPU trace conversion failed' }
173153
Write-Host "CPU trace complete: $traceFile" -ForegroundColor Green
154+
$speedFile = $speedBase + '.speedscope.json'
155+
if(Test-Path "$speedFile.speedscope.json"){ Move-Item -Force "$speedFile.speedscope.json" $speedFile }
174156
Write-Host "Speedscope file: $speedFile" -ForegroundColor Green
175-
# Auto-open speedscope view
176-
try {
177-
$speedFile = $speedFile + '.speedscope.json'
178-
$resolvedSpeed = (Resolve-Path $speedFile).Path
179-
if(-not (Test-Path $resolvedSpeed)) { throw "Speedscope file not found: $resolvedSpeed" }
180-
if(Get-Command npx -ErrorAction SilentlyContinue){
181-
Write-Host "Opening speedscope (npx) -> $resolvedSpeed" -ForegroundColor Cyan
182-
& npx speedscope "$resolvedSpeed"
183-
if($LASTEXITCODE -ne 0){ Write-Host 'npx speedscope returned non-zero; fallback to browser.' -ForegroundColor Yellow; Start-Process 'https://www.speedscope.app'; Start-Process explorer.exe (Split-Path $resolvedSpeed -Parent) }
184-
} else {
185-
Write-Host 'npx not available; opening speedscope.app and folder.' -ForegroundColor Yellow
186-
Start-Process 'https://www.speedscope.app'
187-
Start-Process explorer.exe (Split-Path $resolvedSpeed -Parent)
188-
}
189-
} catch { Write-Host "Speedscope auto-open failed: $($_.Exception.Message)" -ForegroundColor Yellow }
157+
if(-not $env:TRACE_NO_VIEW){
158+
try { $resolvedSpeed = (Resolve-Path $speedFile).Path; if(-not (Test-Path $resolvedSpeed)){ throw "Speedscope file not found: $resolvedSpeed" }; if(Get-Command npx -ErrorAction SilentlyContinue){ Write-Host "Opening speedscope (npx) -> $resolvedSpeed" -ForegroundColor Cyan; & npx speedscope "$resolvedSpeed"; if($LASTEXITCODE -ne 0){ Write-Host 'npx speedscope returned non-zero; fallback to browser.' -ForegroundColor Yellow; Start-Process 'https://www.speedscope.app'; Start-Process explorer.exe (Split-Path $resolvedSpeed -Parent) } } else { Write-Host 'npx not available; opening speedscope.app and folder.' -ForegroundColor Yellow; Start-Process 'https://www.speedscope.app'; Start-Process explorer.exe (Split-Path $resolvedSpeed -Parent) } } catch { Write-Host "Speedscope auto-open failed: $($_.Exception.Message)" -ForegroundColor Yellow }
159+
} else { Write-Host 'TRACE_NO_VIEW set; skipping auto-open.' -ForegroundColor DarkYellow }
190160
}
191161
'trace-gc' {
192162
Ensure-Tool 'dotnet-trace' 'dotnet-trace'
193163
$script:DotNetOnly = $true
194-
# Duration selection (interactive)
195164
$durationsMap = [ordered]@{ '10 sec'='00:00:10'; '30 sec'='00:00:30'; '1 min'='00:01:00'; '5 min'='00:05:00' }
196165
$duration = $durationsMap['10 sec']
197-
try {
198-
Import-Module PwshSpectreConsole -ErrorAction Stop
199-
$choice = Read-SpectreSelection -Title 'Select GC trace duration' -Choices ($durationsMap.Keys + 'Cancel') -EnableSearch -PageSize 10
200-
if($choice -and $choice -ne 'Cancel'){ $duration = $durationsMap[$choice] }
201-
if($choice -eq 'Cancel'){ Write-Host 'GC trace cancelled.' -ForegroundColor Yellow; break }
202-
} catch { Write-Host 'Spectre selection unavailable; using default 10 sec.' -ForegroundColor Yellow }
166+
try { Import-Module PwshSpectreConsole -ErrorAction Stop; $choice = Read-SpectreSelection -Title 'Select GC trace duration' -Choices ($durationsMap.Keys + 'Cancel') -EnableSearch -PageSize 10; if($choice -and $choice -ne 'Cancel'){ $duration = $durationsMap[$choice] }; if($choice -eq 'Cancel'){ Write-Host 'GC trace cancelled.' -ForegroundColor Yellow; break } } catch { Write-Host 'Spectre selection unavailable; using default 10 sec.' -ForegroundColor Yellow }
203167
$procId = Select-Pid 'Select process for GC-focused trace'
204168
if(-not $procId){ Write-Host 'No PID selected.' -ForegroundColor Yellow; break }
205169
$outDir = Join-Path $PSScriptRoot '..' '.tmp' 'diagnostics'
206170
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
207171
$fileBase = "gc_${procId}_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
208172
$traceFile = Join-Path $outDir "$fileBase.nettrace"
209-
$speedFile = Join-Path $outDir "$fileBase"
173+
$speedBase = Join-Path $outDir $fileBase
174+
try { Import-Module PwshSpectreConsole -ErrorAction Stop; @( 'GC Trace','PID: ' + $procId,'Duration: ' + $duration,'Providers: SampleProfiler + System.Runtime','Artifacts Base: ' + $fileBase ) | Format-SpectreRows | Format-SpectrePanel -Expand } catch {}
210175
Write-Host "Collecting GC-focused trace (SampleProfiler + System.Runtime, $duration) for PID $procId ..." -ForegroundColor Cyan
211176
& dotnet-trace collect --process-id $procId --providers Microsoft-DotNETCore-SampleProfiler:1,System.Runtime:4 --duration $duration -o $traceFile
212177
if($LASTEXITCODE -ne 0){ throw 'GC trace collection failed' }
213178
Write-Host 'Converting to speedscope...' -ForegroundColor Cyan
214-
& dotnet-trace convert --format SpeedScope $traceFile -o $speedFile
179+
& dotnet-trace convert --format SpeedScope $traceFile -o $speedBase
215180
if($LASTEXITCODE -ne 0){ throw 'GC trace conversion failed' }
216181
Write-Host "GC trace complete: $traceFile" -ForegroundColor Green
182+
$speedFile = $speedBase + '.speedscope.json'
183+
if(Test-Path "$speedFile.speedscope.json"){ Move-Item -Force "$speedFile.speedscope.json" $speedFile }
217184
Write-Host "Speedscope file: $speedFile" -ForegroundColor Green
218-
# Auto-open speedscope view
219-
try {
220-
$speedFile = $speedFile + '.speedscope.json'
221-
$resolvedSpeed = (Resolve-Path $speedFile).Path
222-
if(-not (Test-Path $resolvedSpeed)) { throw "Speedscope file not found: $resolvedSpeed" }
223-
if(Get-Command npx -ErrorAction SilentlyContinue){
224-
Write-Host "Opening speedscope (npx) -> $resolvedSpeed" -ForegroundColor Cyan
225-
& npx speedscope "$resolvedSpeed"
226-
if($LASTEXITCODE -ne 0){ Write-Host 'npx speedscope returned non-zero; fallback to browser.' -ForegroundColor Yellow; Start-Process 'https://www.speedscope.app'; Start-Process explorer.exe (Split-Path $resolvedSpeed -Parent) }
227-
} else {
228-
Write-Host 'npx not available; opening speedscope.app and folder.' -ForegroundColor Yellow
229-
Start-Process 'https://www.speedscope.app'
230-
Start-Process explorer.exe (Split-Path $resolvedSpeed -Parent)
231-
}
232-
} catch { Write-Host "Speedscope auto-open failed: $($_.Exception.Message)" -ForegroundColor Yellow }
185+
if(-not $env:TRACE_NO_VIEW){
186+
try { $resolvedSpeed = (Resolve-Path $speedFile).Path; if(-not (Test-Path $resolvedSpeed)){ throw "Speedscope file not found: $resolvedSpeed" }; if(Get-Command npx -ErrorAction SilentlyContinue){ Write-Host "Opening speedscope (npx) -> $resolvedSpeed" -ForegroundColor Cyan; & npx speedscope "$resolvedSpeed"; if($LASTEXITCODE -ne 0){ Write-Host 'npx speedscope returned non-zero; fallback to browser.' -ForegroundColor Yellow; Start-Process 'https://www.speedscope.app'; Start-Process explorer.exe (Split-Path $resolvedSpeed -Parent) } } else { Write-Host 'npx not available; opening speedscope.app and folder.' -ForegroundColor Yellow; Start-Process 'https://www.speedscope.app'; Start-Process explorer.exe (Split-Path $resolvedSpeed -Parent) } } catch { Write-Host "Speedscope auto-open failed: $($_.Exception.Message)" -ForegroundColor Yellow }
187+
} else { Write-Host 'TRACE_NO_VIEW set; skipping auto-open.' -ForegroundColor DarkYellow }
233188
}
234189
'speedscope-view' {
235190
# Select a speedscope json file and open visualization

0 commit comments

Comments
 (0)