public/Out-Sentry.ps1
. "$privateDir/StackTraceProcessor.ps1" . "$privateDir/Get-CurrentOptions.ps1" function Out-Sentry { [OutputType([Sentry.SentryId])] [CmdletBinding(DefaultParameterSetName = 'ErrorRecord')] param( [Parameter(ValueFromPipeline = $true, ParameterSetName = 'ErrorRecord')] [System.Management.Automation.ErrorRecord] $ErrorRecord, [Parameter(ValueFromPipeline = $true, ParameterSetName = 'Exception')] [System.Exception] $Exception, [Parameter(ValueFromPipeline = $true, ParameterSetName = 'Message')] [string] $Message, [Parameter(ParameterSetName = 'ErrorRecord')] [Parameter(ParameterSetName = 'Exception')] [Parameter(ParameterSetName = 'Message')] [scriptblock] $EditScope ) begin {} process { if (-not [Sentry.SentrySdk]::IsEnabled) { return } $options = Get-CurrentOptions [Sentry.SentryEvent]$event_ = $null $processor = [StackTraceProcessor]::new() if ($ErrorRecord -ne $null) { $event_ = [Sentry.SentryEvent]::new($ErrorRecord.Exception) $processor.SentryException = [Sentry.Protocol.SentryException]::new() if ($($ErrorRecord.CategoryInfo.Activity) -eq 'Write-Error') { # FullyQualifiedErrorId would be "Microsoft.PowerShell.Commands.WriteErrorException,funcB" $processor.SentryException.Type = 'Write-Error' } else { $processor.SentryException.Type = $ErrorRecord.FullyQualifiedErrorId } if (($details = $ErrorRecord.ErrorDetails) -and $null -ne $details.Message) { $processor.SentryException.Value = $details.Message } else { $processor.SentryException.Value = $ErrorRecord.Exception.Message } if ($options.AttachStackTrace) { # Note: we use ScriptStackTrace even though we need to parse it, becaause it contains actual stack trace # to the throw, not just the trace to the call to this function. $processor.StackTraceString = $ErrorRecord.ScriptStackTrace -split "[`r`n]+" | Where-Object { $_ -ne 'at <ScriptBlock>, <No file>: line 1' } $processor.InvocationInfo = $ErrorRecord.InvocationInfo } } elseif ($Exception -ne $null) { $event_ = [Sentry.SentryEvent]::new($Exception) $processor.SentryException = [Sentry.Protocol.SentryException]::new() $processor.SentryException.Type = $Exception.GetType().FullName $processor.SentryException.Value = $Exception.Message } elseif ($Message -ne $null) { $event_ = [Sentry.SentryEvent]::new() $event_.Message = $Message $event_.Level = [Sentry.SentryLevel]::Info } else { Write-Warning 'Out-Sentry: No argument matched, nothing to do' return } if ($null -eq $event_) { Write-Debug 'Out-Sentry: Nothing to capture' return } if ($options.AttachStackTrace -and $null -eq $processor.StackTraceFrames -and $null -eq $processor.StackTraceString) { $processor.StackTraceFrames = Get-PSCallStack | Select-Object -Skip 1 } return [Sentry.SentrySdk]::CaptureEvent($event_, [System.Action[Sentry.Scope]] { param([Sentry.Scope]$scope) $scope.AddEventProcessor($processor) # Execute the script block in the caller's scope (nothing to do $scope) & set the automatic $_ variable to the $scope object. $scope | ForEach-Object $EditScope }) } } |