Skip to content

Add Add-SentryEventProcessor cmdlet and migrate internal processors#130

Draft
jamescrosswell wants to merge 3 commits into
mainfrom
event-processor-cmdlet
Draft

Add Add-SentryEventProcessor cmdlet and migrate internal processors#130
jamescrosswell wants to merge 3 commits into
mainfrom
event-processor-cmdlet

Conversation

@jamescrosswell
Copy link
Copy Markdown
Collaborator

Closes #124.

Replaces the PowerShell class : SentryEventProcessor pattern (which fails parse-time base-type resolution on module import) with a single C# wrapper class plus a script-block-based public cmdlet. The same mechanism is then used internally for the two existing built-in processors, so the PowerShell class files can be deleted entirely.

Three commits, reviewable separately or together:

1. Add Add-SentryEventProcessor cmdlet

User-facing cmdlet that registers a global event processor. The script block receives the event via $_ (matching Edit-SentryScope), returns the event to send it, or $null to drop it.

Add-SentryEventProcessor { $_.SetTag('host', $env:COMPUTERNAME); $_ }

Add-SentryEventProcessor {
    if ($_.Message -match 'secret') { return $null }
    $_
}

Under the hood, a new C# ScriptBlockEventProcessor implements ISentryEventProcessor directly. Doing the interface implementation in C# (instead of via a PowerShell class deriving from it) sidesteps PowerShell's parse-time base-type resolution. Includes a test suite.

2. Migrate EventUpdater to ScriptBlockEventProcessor

Replaces the class EventUpdater : SentryEventProcessor definition with an inline script block registered through the same ScriptBlockEventProcessor. Behavior is unchanged (sets Platform = 'powershell', clears the bogus pwsh-versioned Release set by the .NET SDK). Deletes EventUpdater.ps1.

3. Migrate StackTraceProcessor to ScriptBlockEventProcessor

The big one. ~250-line class StackTraceProcessor becomes New-StackTraceEventProcessor, a factory function that captures the per-event state (SentryException, StackTraceFrames, StackTraceString, InvocationInfo, ModulePaths, PwshModules, Logger) via closure and returns a ScriptBlockEventProcessor. All the previous instance methods are defined as inline functions inside the returned script block.

Out-Sentry is updated to gather state into local variables and call the factory immediately before CaptureEvent, replacing the previous mutate-the-processor-instance pattern.

With no remaining PS class : SentryEventProcessor subclasses, the C# base SentryEventProcessor_ (which only existed to host the Process_ / DoProcess workaround for the Process keyword conflict) is also removed.

Devil in the details

A few things to verify carefully in review and CI:

  • Closure semantics for helper functions. The factory captures state with .GetNewClosure(), then the returned script block defines all helpers as inline function declarations at its top. Helpers reference $s (alias for $state) which is captured via closure. I believe this works, but PS class semantics are a more familiar pattern — first CI run will tell us if anything misbehaves.
  • Process method invocation in tests. The migrated stacktrace-processor.tests.ps1 now calls \$sut.Process(\$event_) (capital P, the C# method) rather than \$sut.process(\$event_).
  • Local testing blocked by Silence Add-Type CS1701 System.Runtime version warnings #123. On pwsh 7.6 / .NET 10, the CS1701 System.Runtime version mismatch turns into a fatal Add-Type failure, which means I can't run the test suite end-to-end locally. CI uses older pwsh where CS1701 stays a warning and Add-Type succeeds. Tests therefore need a green CI run before I'd consider this PR truly verified.
  • Out-Sentry refactor. The Out-Sentry body was restructured so state is gathered into locals (\$sentryException, \$stackTraceString, \$invocationInfo, \$stackTraceFrames) and the processor is constructed at the end. Functionally equivalent but the diff is non-trivial.

jamescrosswell and others added 3 commits May 22, 2026 14:39
Public cmdlet that registers a global event processor backed by a
PowerShell script block. The block receives the event via the
automatic $_ variable (matching Edit-SentryScope), returns the event
to send it, or $null to drop it.

Internally the block is wrapped by a new C# ScriptBlockEventProcessor
that implements ISentryEventProcessor directly. Implementing the
interface in C# (rather than via a PowerShell class deriving from it)
sidesteps PowerShell's parse-time base-type resolution, which is the
root cause of the noisy 'Unable to find type [SentryEventProcessor]'
errors on module import.

Subsequent commits migrate the internal EventUpdater and
StackTraceProcessor onto this same mechanism so the PowerShell class
files can be removed entirely.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace the PowerShell class-based EventUpdater with an equivalent
script block registered through ScriptBlockEventProcessor. Behavior
is unchanged: the event Platform is set to 'powershell' and a bogus
pwsh-versioned Release set by the .NET SDK is cleared.

This eliminates one of the three PowerShell class-based event
processors. StackTraceProcessor follows in the next commit; the
parse-time errors won't disappear until that one is migrated too.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace the PowerShell class-based StackTraceProcessor with a factory
function New-StackTraceEventProcessor that captures per-event state
via closure and returns a ScriptBlockEventProcessor. Behavior is
intended to match the previous class exactly; all helper methods are
defined inline inside the returned script block.

Out-Sentry is updated to gather state into local variables and call
the factory immediately before CaptureEvent, replacing the previous
mutate-the-processor-instance pattern.

With this commit the module no longer defines any PowerShell
`class : SentryEventProcessor` subclasses, so the C# base
SentryEventProcessor_ (which existed only to host the Process_ /
DoProcess workaround) is also removed. The 'Unable to find type
[SentryEventProcessor]' parse errors on module import should be gone.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

Fails
🚫 Please consider adding a changelog entry for the next release.
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Instructions and example for changelog

Please add an entry to CHANGELOG.md to the "Unreleased" section. Make sure the entry includes this PR's number.

Example:

## Unreleased

### Features

- Add Add-SentryEventProcessor cmdlet and migrate internal processors ([#130](https://github.com/getsentry/sentry-powershell/pull/130))

If none of the above apply, you can opt out of this check by adding #skip-changelog to the PR description or adding a skip-changelog label.

Generated by 🚫 dangerJS against dcc6d7e

# Behavior is intended to match the previous class exactly; the per-event state
# that used to live on instance fields is now captured by closure inside the
# returned ScriptBlockEventProcessor.
function New-StackTraceEventProcessor {
SetContextLinesFromArray $sentryFrame $lines
} catch {
Write-Warning "Failed to read context lines for $($sentryFrame.AbsolutePath): $_"
if ($global:SentryPowershellRethrowErrors -eq $true) { throw }
SetContextLinesFromArray $sentryFrame $lines
} catch {
Write-Warning "Failed to read context lines for frame with function '$($sentryFrame.Function)': $_"
if ($global:SentryPowershellRethrowErrors -eq $true) { throw }
@@ -0,0 +1,54 @@
BeforeAll {
. "$PSScriptRoot/utils.ps1"
$global:SentryPowershellRethrowErrors = $true
}

AfterAll {
$global:SentryPowershellRethrowErrors = $false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ParserError noise from EventProcessor warnings

2 participants