Skip to content

Commit 638d83a

Browse files
authored
fix: Stacktrace parsing for WindowsPowershell 5.1 (#50)
* prepare tests before the fix * fixup * fixup CI * fix windows powershell * chore: update changelog * more path validation
1 parent e8a6619 commit 638d83a

File tree

5 files changed

+50
-11
lines changed

5 files changed

+50
-11
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Fixes
6+
7+
- StackTrace parsing on Windows Powershell 5.1 ([#50](https://github.com/getsentry/sentry-powershell/pull/50))
8+
39
## 0.1.0
410

511
### Features

modules/Sentry/private/StackTraceProcessor.ps1

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class StackTraceProcessor : SentryEventProcessor
120120
{
121121
$sentryFrames.Capacity = $this.StackTraceFrames.Count + 1
122122
}
123-
else
123+
elseif ($null -ne $this.StackTraceString)
124124
{
125125
$sentryFrames.Capacity = $this.StackTraceString.Count + 1
126126
}
@@ -139,7 +139,7 @@ class StackTraceProcessor : SentryEventProcessor
139139
$sentryFrames.Add($this.CreateFrame($frame))
140140
}
141141
}
142-
else
142+
elseif ($null -ne $this.StackTraceString)
143143
{
144144
# Note: if InvocationInfo is present, use it to update:
145145
# - the first frame (in case of `$_ | Out-Sentry` in a catch clause).
@@ -177,7 +177,7 @@ class StackTraceProcessor : SentryEventProcessor
177177
{
178178
# Update module info
179179
$this.SetModule($sentryFrame)
180-
$sentryFrame.InApp = $null -eq $sentryFrame.Module
180+
$sentryFrame.InApp = [string]::IsNullOrEmpty($sentryFrame.Module)
181181
$this.SetContextLines($sentryFrame)
182182
}
183183

@@ -210,7 +210,7 @@ class StackTraceProcessor : SentryEventProcessor
210210
{
211211
$sentryFrame = [Sentry.SentryStackFrame]::new()
212212
# at funcB, C:\dev\sentry-powershell\tests\capture.tests.ps1: line 363
213-
$regex = 'at (?<Function>[^,]+), (?<AbsolutePath>.+): line (?<LineNumber>\d+)'
213+
$regex = 'at (?<Function>[^,]*), (?<AbsolutePath>.*): line (?<LineNumber>\d*)'
214214
if ($frame -match $regex)
215215
{
216216
$sentryFrame.AbsolutePath = $Matches.AbsolutePath
@@ -226,12 +226,12 @@ class StackTraceProcessor : SentryEventProcessor
226226

227227
hidden SetScriptInfo([Sentry.SentryStackFrame] $sentryFrame, [System.Management.Automation.CallStackFrame] $frame)
228228
{
229-
if ($null -ne $frame.ScriptName)
229+
if (![string]::IsNullOrEmpty($frame.ScriptName))
230230
{
231231
$sentryFrame.AbsolutePath = $frame.ScriptName
232232
$sentryFrame.LineNumber = $frame.ScriptLineNumber
233233
}
234-
elseif ($null -ne $frame.Position -and $null -ne $frame.Position.File)
234+
elseif (![string]::IsNullOrEmpty($frame.Position) -and ![string]::IsNullOrEmpty($frame.Position.File))
235235
{
236236
$sentryFrame.AbsolutePath = $frame.Position.File
237237
$sentryFrame.LineNumber = $frame.Position.StartLineNumber
@@ -241,7 +241,7 @@ class StackTraceProcessor : SentryEventProcessor
241241

242242
hidden SetModule([Sentry.SentryStackFrame] $sentryFrame)
243243
{
244-
if ($null -ne $sentryFrame.AbsolutePath)
244+
if (![string]::IsNullOrEmpty($sentryFrame.AbsolutePath))
245245
{
246246
if ($prefix = $this.modulePaths | Where-Object { $sentryFrame.AbsolutePath.StartsWith($_) })
247247
{
@@ -265,7 +265,7 @@ class StackTraceProcessor : SentryEventProcessor
265265

266266
hidden SetFunction([Sentry.SentryStackFrame] $sentryFrame, [System.Management.Automation.CallStackFrame] $frame)
267267
{
268-
if ($null -eq $sentryFrame.AbsolutePath -and $frame.FunctionName -eq '<ScriptBlock>' -and $null -ne $frame.Position)
268+
if ([string]::IsNullOrEmpty($sentryFrame.AbsolutePath) -and $frame.FunctionName -eq '<ScriptBlock>' -and ![string]::IsNullOrEmpty($frame.Position))
269269
{
270270
$sentryFrame.Function = $frame.Position.Text
271271
}
@@ -277,7 +277,12 @@ class StackTraceProcessor : SentryEventProcessor
277277

278278
hidden SetContextLines([Sentry.SentryStackFrame] $sentryFrame)
279279
{
280-
if ($null -ne $sentryFrame.AbsolutePath -and $sentryFrame.LineNumber -ge 1 -and (Test-Path $sentryFrame.AbsolutePath -PathType Leaf))
280+
if ([string]::IsNullOrEmpty($sentryFrame.AbsolutePath) -or $sentryFrame.LineNumber -lt 1)
281+
{
282+
return
283+
}
284+
285+
if ((Test-Path $sentryFrame.AbsolutePath -IsValid) -and (Test-Path $sentryFrame.AbsolutePath -PathType Leaf))
281286
{
282287
try
283288
{

modules/Sentry/public/Out-Sentry.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function Out-Sentry
6464
{
6565
# Note: we use ScriptStackTrace even though we need to parse it, becaause it contains actual stack trace
6666
# to the throw, not just the trace to the call to this function.
67-
$processor.StackTraceString = $ErrorRecord.ScriptStackTrace -split "[`r`n]+" | Where-Object { $_ -ne 'at <ScriptBlock>, <No file>: line 1' }
67+
$processor.StackTraceString = @($ErrorRecord.ScriptStackTrace -split "[`r`n]+")
6868
$processor.InvocationInfo = $ErrorRecord.InvocationInfo
6969
}
7070

scripts/bump-version.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
set -euxo pipefail
33

44
# Requires powershell: `brew install powershell`
5-
# craft executes this file by convension, passing the new version as the second argument:
5+
# craft executes this file by convention, passing the new version as the second argument:
66
pwsh ./scripts/bump-version.ps1 "$2"

tests/stacktrace-processor.tests.ps1

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
BeforeAll {
2+
. "$PSScriptRoot/../modules/Sentry/private/StackTraceProcessor.ps1"
3+
}
4+
5+
Describe 'StackTraceProcessor' {
6+
It 'Parses stack trace properly' {
7+
$event_ = [Sentry.SentryEvent]::new()
8+
$event_.Message = 'Test'
9+
$event_.Level = [Sentry.SentryLevel]::Info
10+
11+
$sut = [StackTraceProcessor]::new()
12+
$sut.StackTraceString = 'at funcB, C:\dev\sentry-powershell\tests\throwing.ps1: line 17
13+
at <ScriptBlock>, <No file>: line 1
14+
at <ScriptBlock>, : line 3' -split "[`r`n]+"
15+
$sut.process($event_)
16+
17+
$frames = $event_.SentryThreads[0].Stacktrace.Frames
18+
$frames[0].Function | Should -Be '<ScriptBlock>'
19+
$frames[0].AbsolutePath | Should -Be ''
20+
$frames[0].LineNumber | Should -Be 3
21+
$frames[1].Function | Should -Be '<ScriptBlock>'
22+
$frames[1].AbsolutePath | Should -Be '<No file>'
23+
$frames[1].LineNumber | Should -Be 1
24+
$frames[2].Function | Should -Be 'funcB'
25+
$frames[2].AbsolutePath | Should -Be 'C:\dev\sentry-powershell\tests\throwing.ps1'
26+
$frames[2].LineNumber | Should -Be 17
27+
}
28+
}

0 commit comments

Comments
 (0)