From 1c939cb8c9676212c36da60320a5fe6ffa0f2a9d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Sep 2025 17:30:15 +0000 Subject: [PATCH 1/2] Initial plan From b0b82390645462cf5948d27ea995862d27529a88 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Sep 2025 17:36:43 +0000 Subject: [PATCH 2/2] Fix reflection issues in SynchronousTransport and SynchronousWorker classes Co-authored-by: vaind <6349682+vaind@users.noreply.github.com> --- .../Sentry/private/SynchronousTransport.ps1 | 122 +++++++++++++----- modules/Sentry/private/SynchronousWorker.ps1 | 41 +++++- 2 files changed, 124 insertions(+), 39 deletions(-) diff --git a/modules/Sentry/private/SynchronousTransport.ps1 b/modules/Sentry/private/SynchronousTransport.ps1 index c5f19c5..40f2371 100644 --- a/modules/Sentry/private/SynchronousTransport.ps1 +++ b/modules/Sentry/private/SynchronousTransport.ps1 @@ -17,54 +17,108 @@ class SynchronousTransport : Sentry.Http.HttpTransportBase, Sentry.Extensibility } # These are internal methods, so we need to use reflection to access them. - $instanceMethod = [System.Reflection.BindingFlags]::Instance + [System.Reflection.BindingFlags]::NonPublic + [System.Reflection.BindingFlags]::Public; - $this.ProcessEnvelope = [Sentry.Http.HttpTransportBase].GetMethod('ProcessEnvelope', $instanceMethod) - $this.CreateRequest = [Sentry.Http.HttpTransportBase].GetMethod('CreateRequest', $instanceMethod) - $EnvelopeHttpContentType = [Sentry.SentrySdk].Assembly.GetType('Sentry.Internal.Http.EnvelopeHttpContent') - $this.SerializeToStream = $EnvelopeHttpContentType.GetMethod('SerializeToStream', $instanceMethod) - } - - [System.Threading.Tasks.Task] SendEnvelopeAsync([Sentry.Protocol.Envelopes.Envelope] $envelope, [System.Threading.CancellationToken]$cancellationToken = [System.Threading.CancellationToken]::None) - { - $processedEnvelope = $this.ProcessEnvelope.Invoke($this, @($envelope)) - if ($processedEnvelope.Items.count -gt 0) + try { - $request = $this.CreateRequest.Invoke($this, @($processedEnvelope)) + $instanceMethod = [System.Reflection.BindingFlags]::Instance + [System.Reflection.BindingFlags]::NonPublic + [System.Reflection.BindingFlags]::Public; + + # Try to get the ProcessEnvelope method + $this.ProcessEnvelope = [Sentry.Http.HttpTransportBase].GetMethod('ProcessEnvelope', $instanceMethod) + if ($null -eq $this.ProcessEnvelope) + { + throw "ProcessEnvelope method not found on HttpTransportBase" + } - $headers = @{} - foreach ($header in $request.Headers) + # Try to get the CreateRequest method + $this.CreateRequest = [Sentry.Http.HttpTransportBase].GetMethod('CreateRequest', $instanceMethod) + if ($null -eq $this.CreateRequest) { - $Key = $header.Key - $Value = $header.Value.Trim() -join ', ' - $headers[$Key] = $Value + throw "CreateRequest method not found on HttpTransportBase" } - $memoryStream = [System.IO.MemoryStream]::new() - $this.SerializeToStream.Invoke($request.Content, @($memoryStream, $null, $cancellationToken)) - $memoryStream.Position = 0 + # Try to get the EnvelopeHttpContent type and SerializeToStream method + $EnvelopeHttpContentType = [Sentry.SentrySdk].Assembly.GetType('Sentry.Internal.Http.EnvelopeHttpContent') + if ($null -eq $EnvelopeHttpContentType) + { + throw "EnvelopeHttpContent type not found" + } + # Look for SerializeToStream with correct parameters + $streamType = [System.IO.Stream] + $transportContextType = [System.Net.TransportContext] + $cancellationTokenType = [System.Threading.CancellationToken] + + # Try to find the synchronous version: SerializeToStream(Stream, TransportContext, CancellationToken) + $parameterTypes = @($streamType, $transportContextType, $cancellationTokenType) + $this.SerializeToStream = $EnvelopeHttpContentType.GetMethod('SerializeToStream', $instanceMethod, $null, $parameterTypes, $null) + + if ($null -eq $this.SerializeToStream) + { + throw "SerializeToStream method not found on EnvelopeHttpContent" + } + } + catch + { if ($null -ne $this.logger) { - $this.logger.Log([Sentry.SentryLevel]::Debug, 'Sending content synchronously, Content-Length: {0}', $null, $memoryStream.Length) + $this.logger.Log([Sentry.SentryLevel]::Warning, 'Failed to initialize reflection methods for SynchronousTransport: {0}', $_.Exception, @()) } + throw + } + } - $ProgressPreference = 'SilentlyContinue' - $psResponse = Invoke-WebRequest -Uri $request.RequestUri -Method $request.Method.Method -Headers $headers -Body $memoryStream -UseBasicParsing - - $response = [System.Net.Http.HttpResponseMessage]::new($psResponse.StatusCode) - $contentType = $psResponse.Headers['Content-Type'] - if ($null -eq $contentType) + [System.Threading.Tasks.Task] SendEnvelopeAsync([Sentry.Protocol.Envelopes.Envelope] $envelope, [System.Threading.CancellationToken]$cancellationToken = [System.Threading.CancellationToken]::None) + { + try + { + $processedEnvelope = $this.ProcessEnvelope.Invoke($this, @($envelope)) + if ($processedEnvelope.Items.count -gt 0) { - $contentType = 'application/json' - } - $response.Content = [System.Net.Http.StringContent]::new($psResponse.Content, [System.Text.Encoding]::UTF8, $contentType) + $request = $this.CreateRequest.Invoke($this, @($processedEnvelope)) + + $headers = @{} + foreach ($header in $request.Headers) + { + $Key = $header.Key + $Value = $header.Value.Trim() -join ', ' + $headers[$Key] = $Value + } + + $memoryStream = [System.IO.MemoryStream]::new() + # Call SerializeToStream with the correct parameters: (Stream, TransportContext, CancellationToken) + $this.SerializeToStream.Invoke($request.Content, @($memoryStream, $null, $cancellationToken)) + $memoryStream.Position = 0 + + if ($null -ne $this.logger) + { + $this.logger.Log([Sentry.SentryLevel]::Debug, 'Sending content synchronously, Content-Length: {0}', $null, $memoryStream.Length) + } + + $ProgressPreference = 'SilentlyContinue' + $psResponse = Invoke-WebRequest -Uri $request.RequestUri -Method $request.Method.Method -Headers $headers -Body $memoryStream -UseBasicParsing - foreach ($header in $psResponse.Headers.GetEnumerator()) + $response = [System.Net.Http.HttpResponseMessage]::new($psResponse.StatusCode) + $contentType = $psResponse.Headers['Content-Type'] + if ($null -eq $contentType) + { + $contentType = 'application/json' + } + $response.Content = [System.Net.Http.StringContent]::new($psResponse.Content, [System.Text.Encoding]::UTF8, $contentType) + + foreach ($header in $psResponse.Headers.GetEnumerator()) + { + $response.Headers.TryAddWithoutValidation($header.Key, $header.Value) + } + + $this.HandleResponse($response, $processedEnvelope) + } + } + catch + { + if ($null -ne $this.logger) { - $response.Headers.TryAddWithoutValidation($header.Key, $header.Value) + $this.logger.Log([Sentry.SentryLevel]::Error, 'Failed to send envelope: {0}', $_.Exception, @()) } - - $this.HandleResponse($response, $processedEnvelope) + throw } return [System.Threading.Tasks.Task]::CompletedTask diff --git a/modules/Sentry/private/SynchronousWorker.ps1 b/modules/Sentry/private/SynchronousWorker.ps1 index 2938cf3..a82442f 100644 --- a/modules/Sentry/private/SynchronousWorker.ps1 +++ b/modules/Sentry/private/SynchronousWorker.ps1 @@ -14,18 +14,49 @@ class SynchronousWorker : Sentry.Extensibility.IBackgroundWorker $this.transport = $options.Transport; if ($null -eq $this.transport) { - $this.transport = New-HttpTransport($options) + try + { + $this.transport = New-HttpTransport($options) + } + catch + { + if ($null -ne $options.DiagnosticLogger) + { + $options.DiagnosticLogger.Log([Sentry.SentryLevel]::Warning, 'Failed to create HTTP transport in SynchronousWorker: {0}', $_.Exception, @()) + } + throw + } } } [bool] EnqueueEnvelope([Sentry.Protocol.Envelopes.Envelope] $envelope) { - $task = $this.transport.SendEnvelopeAsync($envelope, [System.Threading.CancellationToken]::None) - if (-not $task.Wait($this.options.FlushTimeout)) + try { - $this.unfinishedTasks.Add($task) + if ($null -eq $this.transport) + { + if ($null -ne $this.options.DiagnosticLogger) + { + $this.options.DiagnosticLogger.Log([Sentry.SentryLevel]::Warning, 'Transport is null, cannot enqueue envelope', $null, @()) + } + return $false + } + + $task = $this.transport.SendEnvelopeAsync($envelope, [System.Threading.CancellationToken]::None) + if (-not $task.Wait($this.options.FlushTimeout)) + { + $this.unfinishedTasks.Add($task) + } + return $true + } + catch + { + if ($null -ne $this.options.DiagnosticLogger) + { + $this.options.DiagnosticLogger.Log([Sentry.SentryLevel]::Error, 'Failed to enqueue envelope: {0}', $_.Exception, @()) + } + return $false } - return $true } [System.Threading.Tasks.Task] FlushAsync([System.TimeSpan] $timeout)