From 962346f2fe31f47b1615854643166b003c548448 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Tue, 1 Jul 2025 21:41:30 +1200 Subject: [PATCH 1/6] fix: EventProcessors not running for native crashes on iOS Resolves #3621: - https://github.com/getsentry/sentry-dotnet/issues/3621 --- src/Sentry/Internal/SentryEventHelper.cs | 76 +++++++++++++++++++ src/Sentry/Platforms/Cocoa/SentrySdk.cs | 43 +++++++---- src/Sentry/SentryClient.cs | 65 ++-------------- ...Throws_ErrorToEventBreadcrumb.verified.txt | 2 +- 4 files changed, 114 insertions(+), 72 deletions(-) create mode 100644 src/Sentry/Internal/SentryEventHelper.cs diff --git a/src/Sentry/Internal/SentryEventHelper.cs b/src/Sentry/Internal/SentryEventHelper.cs new file mode 100644 index 0000000000..33e4ee3059 --- /dev/null +++ b/src/Sentry/Internal/SentryEventHelper.cs @@ -0,0 +1,76 @@ +using Sentry.Extensibility; + +namespace Sentry.Internal; + +internal class SentryEventHelper(SentryOptions options) +{ + public SentryEvent? ProcessEvent(SentryEvent? evt, IEnumerable processors, SentryHint? hint) + { + if (evt == null) + { + return evt; + } + + var processedEvent = evt; + var effectiveHint = hint ?? new SentryHint(); + + foreach (var processor in processors) + { + processedEvent = processor.DoProcessEvent(processedEvent, effectiveHint); + if (processedEvent == null) + { + options.ClientReportRecorder.RecordDiscardedEvent(DiscardReason.EventProcessor, DataCategory.Error); + options.LogInfo("Event dropped by processor {0}", processor.GetType().Name); + break; + } + } + return processedEvent; + } + +#if NET6_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026: RequiresUnreferencedCode", Justification = AotHelper.AvoidAtRuntime)] +#endif + public SentryEvent? DoBeforeSend(SentryEvent? @event, SentryHint hint) + { + if (@event is null || options.BeforeSendInternal is null) + { + return @event; + } + + options.LogDebug("Calling the BeforeSend callback"); + try + { + @event = options.BeforeSendInternal?.Invoke(@event, hint); + if (@event == null) // Rejected event + { + options.ClientReportRecorder.RecordDiscardedEvent(DiscardReason.BeforeSend, DataCategory.Error); + options.LogInfo("Event dropped by BeforeSend callback."); + } + } + catch (Exception e) + { + if (!AotHelper.IsTrimmed) + { + // Attempt to demystify exceptions before adding them as breadcrumbs. + e.Demystify(); + } + + options.LogError(e, "The BeforeSend callback threw an exception. It will be added as breadcrumb and continue."); + var data = new Dictionary + { + {"message", e.Message} + }; + if (e.StackTrace is not null) + { + data.Add("stackTrace", e.StackTrace); + } + @event?.AddBreadcrumb( + "BeforeSend callback failed.", + category: "SentryClient", + data: data, + level: BreadcrumbLevel.Error); + } + + return @event; + } +} diff --git a/src/Sentry/Platforms/Cocoa/SentrySdk.cs b/src/Sentry/Platforms/Cocoa/SentrySdk.cs index 5e60eb100d..c6b0f27f3e 100644 --- a/src/Sentry/Platforms/Cocoa/SentrySdk.cs +++ b/src/Sentry/Platforms/Cocoa/SentrySdk.cs @@ -1,6 +1,7 @@ using Sentry.Cocoa; using Sentry.Cocoa.Extensions; using Sentry.Extensibility; +using Sentry.Internal; // ReSharper disable once CheckNamespace namespace Sentry; @@ -224,31 +225,47 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes( } } - // we run our SIGABRT checks first before handing over to user events - // because we delegate to user code, we need to protect anything that could happen in this event - if (options.BeforeSendInternal == null) - return evt; - + // We run our SIGABRT checks first before running managed processors. + // Because we delegate to user code, we need to catch/log exceptions. try { - var sentryEvent = evt.ToSentryEvent(); - if (sentryEvent == null) + // Normally the event processors would be invoked by the SentryClient, but the Cocoa SDK has its own client, + // so we need to manually invoke any managed event processors here in order for them to be applied to Native + // events. + ImmutableArray manualProcessors = default; + ConfigureScope(scope => manualProcessors = [ + ..scope.GetAllEventProcessors() + .Where(p => p is not MainSentryEventProcessor) + ] + ); + if (manualProcessors.Length == 0 && options.BeforeSendInternal is null) + { return evt; + } - var result = options.BeforeSendInternal(sentryEvent, null!); - if (result == null) - return null!; + var sentryEvent = evt.ToSentryEvent(); + var eventHelper = new SentryEventHelper(options); + if (eventHelper.ProcessEvent(sentryEvent, manualProcessors, null) is not { } processedEvent) + { + return null; + } + + processedEvent = eventHelper.DoBeforeSend(processedEvent, new SentryHint()); + if (processedEvent == null) + { + return null; + } // we only support a subset of mutated data to be passed back to the native SDK at this time - result.CopyToCocoaSentryEvent(evt); + processedEvent.CopyToCocoaSentryEvent(evt); - // Note: Nullable result is allowed but delegate is generated incorrectly + // Note: A nullable result is allowed, but delegate is generated incorrectly // See https://github.com/xamarin/xamarin-macios/issues/15299#issuecomment-1201863294 return evt!; } catch (Exception ex) { - options.LogError(ex, "Before Send Error"); + options.LogError(ex, "Error running managed event processors for native event"); return evt; } } diff --git a/src/Sentry/SentryClient.cs b/src/Sentry/SentryClient.cs index 7aef9aa8b5..56fb571f7c 100644 --- a/src/Sentry/SentryClient.cs +++ b/src/Sentry/SentryClient.cs @@ -19,6 +19,7 @@ public class SentryClient : ISentryClient, IDisposable private readonly ISessionManager _sessionManager; private readonly RandomValuesFactory _randomValuesFactory; private readonly Enricher _enricher; + private readonly SentryEventHelper _eventHelper; internal IBackgroundWorker Worker { get; } @@ -47,6 +48,7 @@ internal SentryClient( _randomValuesFactory = randomValuesFactory ?? new SynchronizedRandomValuesFactory(); _sessionManager = sessionManager ?? new GlobalSessionManager(options); _enricher = new Enricher(options); + _eventHelper = new SentryEventHelper(options); options.SetupLogging(); // Only relevant if this client wasn't created as a result of calling Init @@ -348,26 +350,15 @@ private SentryId DoSendEvent(SentryEvent @event, SentryHint? hint, Scope? scope) } } - var processedEvent = @event; - - foreach (var processor in scope.GetAllEventProcessors()) + if (_eventHelper.ProcessEvent(@event, scope.GetAllEventProcessors(), hint) is not { } processedEvent) { - processedEvent = processor.DoProcessEvent(processedEvent, hint); - - if (processedEvent == null) - { - _options.ClientReportRecorder.RecordDiscardedEvent(DiscardReason.EventProcessor, DataCategory.Error); - _options.LogInfo("Event dropped by processor {0}", processor.GetType().Name); - return SentryId.Empty; - } + return SentryId.Empty; // Dropped by an event processor } - processedEvent = BeforeSend(processedEvent, hint); - if (processedEvent == null) // Rejected event + processedEvent = _eventHelper.DoBeforeSend(processedEvent, hint); + if (processedEvent == null) { - _options.ClientReportRecorder.RecordDiscardedEvent(DiscardReason.BeforeSend, DataCategory.Error); - _options.LogInfo("Event dropped by BeforeSend callback."); - return SentryId.Empty; + return SentryId.Empty; // Dropped by BeforeSend callback } var hasTerminalException = processedEvent.HasTerminalException(); @@ -454,48 +445,6 @@ public bool CaptureEnvelope(Envelope envelope) return false; } -#if NET6_0_OR_GREATER - [UnconditionalSuppressMessage("Trimming", "IL2026: RequiresUnreferencedCode", Justification = AotHelper.AvoidAtRuntime)] -#endif - private SentryEvent? BeforeSend(SentryEvent? @event, SentryHint hint) - { - if (_options.BeforeSendInternal == null) - { - return @event; - } - - _options.LogDebug("Calling the BeforeSend callback"); - try - { - @event = _options.BeforeSendInternal?.Invoke(@event!, hint); - } - catch (Exception e) - { - if (!AotHelper.IsTrimmed) - { - // Attempt to demystify exceptions before adding them as breadcrumbs. - e.Demystify(); - } - - _options.LogError(e, "The BeforeSend callback threw an exception. It will be added as breadcrumb and continue."); - var data = new Dictionary - { - {"message", e.Message} - }; - if (e.StackTrace is not null) - { - data.Add("stackTrace", e.StackTrace); - } - @event?.AddBreadcrumb( - "BeforeSend callback failed.", - category: "SentryClient", - data: data, - level: BreadcrumbLevel.Error); - } - - return @event; - } - /// /// Disposes this client /// diff --git a/test/Sentry.Tests/SentryClientTests.CaptureEvent_BeforeEventThrows_ErrorToEventBreadcrumb.verified.txt b/test/Sentry.Tests/SentryClientTests.CaptureEvent_BeforeEventThrows_ErrorToEventBreadcrumb.verified.txt index 6ce33e1e01..97e165f68b 100644 --- a/test/Sentry.Tests/SentryClientTests.CaptureEvent_BeforeEventThrows_ErrorToEventBreadcrumb.verified.txt +++ b/test/Sentry.Tests/SentryClientTests.CaptureEvent_BeforeEventThrows_ErrorToEventBreadcrumb.verified.txt @@ -6,7 +6,7 @@ message: Exception message!, stackTrace: at Task Sentry.Tests.SentryClientTests.CaptureEvent_BeforeEventThrows_ErrorToEventBreadcrumb() -at SentryEvent Sentry.SentryClient.BeforeSend(...) +at SentryEvent Sentry.Internal.SentryEventHelper.DoBeforeSend(...) }, Category: SentryClient, Level: error From e0f5a5e6aeb4cb8f7b4b05649cc6674fcdd15fde Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Wed, 2 Jul 2025 10:14:48 +1200 Subject: [PATCH 2/6] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f325b27ee8..87ea720c4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ - Added StartSpan and GetTransaction methods to the SentrySdk ([#4303](https://github.com/getsentry/sentry-dotnet/pull/4303)) +### Fixes + +- Custom ISentryEventProcessors are now run for native iOS events ([#4318](https://github.com/getsentry/sentry-dotnet/pull/4318)) + ### Dependencies - Bump Native SDK from v0.9.0 to v0.9.1 ([#4309](https://github.com/getsentry/sentry-dotnet/pull/4309)) From 98e89d1205d3b8cfc3605d1e495fb124218bff59 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Wed, 2 Jul 2025 11:16:03 +1200 Subject: [PATCH 3/6] Fixed unit tests --- src/Sentry/Platforms/Cocoa/SentrySdk.cs | 20 ++++++-- test/Sentry.Tests/SentrySdkTests.cs | 66 +++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 7 deletions(-) diff --git a/src/Sentry/Platforms/Cocoa/SentrySdk.cs b/src/Sentry/Platforms/Cocoa/SentrySdk.cs index c6b0f27f3e..71bae2f7b6 100644 --- a/src/Sentry/Platforms/Cocoa/SentrySdk.cs +++ b/src/Sentry/Platforms/Cocoa/SentrySdk.cs @@ -189,8 +189,21 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes( return nativeRanges; } + [DebuggerStepThrough] internal static CocoaSdk.SentryEvent? ProcessOnBeforeSend(SentryOptions options, CocoaSdk.SentryEvent evt) + => ProcessOnBeforeSend(options, evt, CurrentHub); + + /// + /// This overload allows us to inject an IHub for testing. During normal execution, the CurrentHub is used. + /// However, since this class is static, there's no easy alternative way to inject this when executing tests. + /// + internal static CocoaSdk.SentryEvent? ProcessOnBeforeSend(SentryOptions options, CocoaSdk.SentryEvent evt, IHub hub) { + if (hub is DisabledHub) + { + return evt; + } + // When we have an unhandled managed exception, we send that to Sentry twice - once managed and once native. // The managed exception is what a .NET developer would expect, and it is sent by the Sentry.NET SDK // But we also get a native SIGABRT since it crashed the application, which is sent by the Sentry Cocoa SDK. @@ -233,10 +246,9 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes( // so we need to manually invoke any managed event processors here in order for them to be applied to Native // events. ImmutableArray manualProcessors = default; - ConfigureScope(scope => manualProcessors = [ - ..scope.GetAllEventProcessors() - .Where(p => p is not MainSentryEventProcessor) - ] + hub.ConfigureScope(scope => manualProcessors = scope.GetAllEventProcessors() + .Where(p => p is not MainSentryEventProcessor) + .ToImmutableArray() ); if (manualProcessors.Length == 0 && options.BeforeSendInternal is null) { diff --git a/test/Sentry.Tests/SentrySdkTests.cs b/test/Sentry.Tests/SentrySdkTests.cs index 00fcc95b82..e63b97a20b 100644 --- a/test/Sentry.Tests/SentrySdkTests.cs +++ b/test/Sentry.Tests/SentrySdkTests.cs @@ -996,6 +996,7 @@ public void InitHub_DebugEnabled_DebugLogsLogged() [InlineData(false)] public void ProcessOnBeforeSend_NativeErrorSuppression(bool suppressNativeErrors) { + // Arrange var options = new SentryOptions { Dsn = ValidDsn, @@ -1014,11 +1015,20 @@ public void ProcessOnBeforeSend_NativeErrorSuppression(bool suppressNativeErrors called = true; return e; }); + + var scope = new Scope(options); + var hub = Substitute.For(); + hub.When(h => hub.ConfigureScope(Arg.Any>())) + .Do(callback => callback.Arg>().Invoke(scope)); + var evt = new Sentry.CocoaSdk.SentryEvent(); var ex = new Sentry.CocoaSdk.SentryException("Not checked", "EXC_BAD_ACCESS"); evt.Exceptions = [ex]; - var result = SentrySdk.ProcessOnBeforeSend(options, evt); + // Act + var result = SentrySdk.ProcessOnBeforeSend(options, evt, hub); + + // Assert if (suppressNativeErrors) { called.Should().BeFalse(); @@ -1034,6 +1044,7 @@ public void ProcessOnBeforeSend_NativeErrorSuppression(bool suppressNativeErrors [Fact] public void ProcessOnBeforeSend_OptionsBeforeOnSendRuns() { + // Arrange var options = new SentryOptions { Dsn = ValidDsn, @@ -1052,16 +1063,55 @@ public void ProcessOnBeforeSend_OptionsBeforeOnSendRuns() native.ReleaseName = "release name"; native.Environment = "environment"; native.Transaction = "transaction name"; - options.SetBeforeSend(e => { e.TransactionName = "dotnet"; return e; }); - var result = SentrySdk.ProcessOnBeforeSend(options, native); + + var scope = new Scope(options); + var hub = Substitute.For(); + hub.When(h => hub.ConfigureScope(Arg.Any>())) + .Do(callback => callback.Arg>().Invoke(scope)); + + // Act + var result = SentrySdk.ProcessOnBeforeSend(options, native, hub); + + // Assert result.Should().NotBeNull(); result.Transaction.Should().Be("dotnet"); } + + [Fact] + public void ProcessOnBeforeSend_EventProcessorsInvoked() + { + // Arrange + var options = new SentryOptions + { + Dsn = ValidDsn, + DiagnosticLogger = _logger, + IsGlobalModeEnabled = true, + Debug = true, + AutoSessionTracking = false, + BackgroundWorker = Substitute.For(), + InitNativeSdks = false, + }; + var eventProcessor = new TestEventProcessor(); + options.AddEventProcessor(eventProcessor); + + var scope = new Scope(options); + var hub = Substitute.For(); + hub.When(h => hub.ConfigureScope(Arg.Any>())) + .Do(callback => callback.Arg>().Invoke(scope)); + + var native = new Sentry.CocoaSdk.SentryEvent(); + + // Act + SentrySdk.ProcessOnBeforeSend(options, native, hub); + + // Assert + eventProcessor.Invoked.Should().BeTrue(); + } #endif public void Dispose() @@ -1069,3 +1119,13 @@ public void Dispose() SentrySdk.Close(); } } + +file class TestEventProcessor : ISentryEventProcessor +{ + public bool Invoked { get; private set; } + public SentryEvent Process(SentryEvent @event) + { + Invoked = true; + return @event; + } +} From e1dda71cf01bf8d74d710b4cb87fc4cfea54fa49 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Wed, 2 Jul 2025 11:28:22 +1200 Subject: [PATCH 4/6] Avoid allocation --- src/Sentry/Platforms/Cocoa/SentrySdk.cs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Sentry/Platforms/Cocoa/SentrySdk.cs b/src/Sentry/Platforms/Cocoa/SentrySdk.cs index 71bae2f7b6..59ca850184 100644 --- a/src/Sentry/Platforms/Cocoa/SentrySdk.cs +++ b/src/Sentry/Platforms/Cocoa/SentrySdk.cs @@ -243,13 +243,10 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes( try { // Normally the event processors would be invoked by the SentryClient, but the Cocoa SDK has its own client, - // so we need to manually invoke any managed event processors here in order for them to be applied to Native - // events. - ImmutableArray manualProcessors = default; - hub.ConfigureScope(scope => manualProcessors = scope.GetAllEventProcessors() + // so we need to manually invoke any managed event processors here to apply them to Native events. + var manualProcessors = GetEventProcessors() .Where(p => p is not MainSentryEventProcessor) - .ToImmutableArray() - ); + .ToImmutableArray(); if (manualProcessors.Length == 0 && options.BeforeSendInternal is null) { return evt; @@ -280,5 +277,16 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes( options.LogError(ex, "Error running managed event processors for native event"); return evt; } + + IEnumerable GetEventProcessors() + { + if (hub is Hub fullHub) + { + return fullHub.ScopeManager.GetCurrent().Key.GetAllEventProcessors(); + } + IEnumerable? eventProcessors = null; + hub.ConfigureScope(scope => eventProcessors = scope.GetAllEventProcessors()); + return eventProcessors ?? []; + } } } From dda6f0471aa30b8cb76cbca2d53811692ec96419 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 3 Jul 2025 22:18:59 +1200 Subject: [PATCH 5/6] Review feedback --- src/Sentry/Internal/SentryEventHelper.cs | 8 ++++---- src/Sentry/Platforms/Cocoa/SentrySdk.cs | 13 ++++++------- src/Sentry/SentryClient.cs | 6 ++---- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/Sentry/Internal/SentryEventHelper.cs b/src/Sentry/Internal/SentryEventHelper.cs index 33e4ee3059..48a6c1a07f 100644 --- a/src/Sentry/Internal/SentryEventHelper.cs +++ b/src/Sentry/Internal/SentryEventHelper.cs @@ -2,9 +2,9 @@ namespace Sentry.Internal; -internal class SentryEventHelper(SentryOptions options) +internal static class SentryEventHelper { - public SentryEvent? ProcessEvent(SentryEvent? evt, IEnumerable processors, SentryHint? hint) + public static SentryEvent? ProcessEvent(SentryEvent? evt, IEnumerable processors, SentryHint? hint, SentryOptions options) { if (evt == null) { @@ -12,7 +12,7 @@ internal class SentryEventHelper(SentryOptions options) } var processedEvent = evt; - var effectiveHint = hint ?? new SentryHint(); + var effectiveHint = hint ?? new SentryHint(options); foreach (var processor in processors) { @@ -30,7 +30,7 @@ internal class SentryEventHelper(SentryOptions options) #if NET6_0_OR_GREATER [UnconditionalSuppressMessage("Trimming", "IL2026: RequiresUnreferencedCode", Justification = AotHelper.AvoidAtRuntime)] #endif - public SentryEvent? DoBeforeSend(SentryEvent? @event, SentryHint hint) + public static SentryEvent? DoBeforeSend(SentryEvent? @event, SentryHint hint, SentryOptions options) { if (@event is null || options.BeforeSendInternal is null) { diff --git a/src/Sentry/Platforms/Cocoa/SentrySdk.cs b/src/Sentry/Platforms/Cocoa/SentrySdk.cs index 59ca850184..646e5b2c99 100644 --- a/src/Sentry/Platforms/Cocoa/SentrySdk.cs +++ b/src/Sentry/Platforms/Cocoa/SentrySdk.cs @@ -244,22 +244,21 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes( { // Normally the event processors would be invoked by the SentryClient, but the Cocoa SDK has its own client, // so we need to manually invoke any managed event processors here to apply them to Native events. - var manualProcessors = GetEventProcessors() + var manualProcessors = GetEventProcessors(hub) .Where(p => p is not MainSentryEventProcessor) - .ToImmutableArray(); + .ToArray(); if (manualProcessors.Length == 0 && options.BeforeSendInternal is null) { return evt; } var sentryEvent = evt.ToSentryEvent(); - var eventHelper = new SentryEventHelper(options); - if (eventHelper.ProcessEvent(sentryEvent, manualProcessors, null) is not { } processedEvent) + if (SentryEventHelper.ProcessEvent(sentryEvent, manualProcessors, null, options) is not { } processedEvent) { return null; } - processedEvent = eventHelper.DoBeforeSend(processedEvent, new SentryHint()); + processedEvent = SentryEventHelper.DoBeforeSend(processedEvent, new SentryHint(), options); if (processedEvent == null) { return null; @@ -270,7 +269,7 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes( // Note: A nullable result is allowed, but delegate is generated incorrectly // See https://github.com/xamarin/xamarin-macios/issues/15299#issuecomment-1201863294 - return evt!; + return evt; } catch (Exception ex) { @@ -278,7 +277,7 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes( return evt; } - IEnumerable GetEventProcessors() + static IEnumerable GetEventProcessors(IHub hub) { if (hub is Hub fullHub) { diff --git a/src/Sentry/SentryClient.cs b/src/Sentry/SentryClient.cs index 56fb571f7c..5e7ae5cfd1 100644 --- a/src/Sentry/SentryClient.cs +++ b/src/Sentry/SentryClient.cs @@ -19,7 +19,6 @@ public class SentryClient : ISentryClient, IDisposable private readonly ISessionManager _sessionManager; private readonly RandomValuesFactory _randomValuesFactory; private readonly Enricher _enricher; - private readonly SentryEventHelper _eventHelper; internal IBackgroundWorker Worker { get; } @@ -48,7 +47,6 @@ internal SentryClient( _randomValuesFactory = randomValuesFactory ?? new SynchronizedRandomValuesFactory(); _sessionManager = sessionManager ?? new GlobalSessionManager(options); _enricher = new Enricher(options); - _eventHelper = new SentryEventHelper(options); options.SetupLogging(); // Only relevant if this client wasn't created as a result of calling Init @@ -350,12 +348,12 @@ private SentryId DoSendEvent(SentryEvent @event, SentryHint? hint, Scope? scope) } } - if (_eventHelper.ProcessEvent(@event, scope.GetAllEventProcessors(), hint) is not { } processedEvent) + if (SentryEventHelper.ProcessEvent(@event, scope.GetAllEventProcessors(), hint, _options) is not { } processedEvent) { return SentryId.Empty; // Dropped by an event processor } - processedEvent = _eventHelper.DoBeforeSend(processedEvent, hint); + processedEvent = SentryEventHelper.DoBeforeSend(processedEvent, hint, _options); if (processedEvent == null) { return SentryId.Empty; // Dropped by BeforeSend callback From b467b3e528aea6bf4f24eca23f618a129c1074b2 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Thu, 3 Jul 2025 22:21:42 +1200 Subject: [PATCH 6/6] Update SentrySdk.cs --- src/Sentry/Platforms/Cocoa/SentrySdk.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Sentry/Platforms/Cocoa/SentrySdk.cs b/src/Sentry/Platforms/Cocoa/SentrySdk.cs index 646e5b2c99..0b7190a7b4 100644 --- a/src/Sentry/Platforms/Cocoa/SentrySdk.cs +++ b/src/Sentry/Platforms/Cocoa/SentrySdk.cs @@ -267,8 +267,6 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes( // we only support a subset of mutated data to be passed back to the native SDK at this time processedEvent.CopyToCocoaSentryEvent(evt); - // Note: A nullable result is allowed, but delegate is generated incorrectly - // See https://github.com/xamarin/xamarin-macios/issues/15299#issuecomment-1201863294 return evt; } catch (Exception ex)