From 3400f00aa94ccae17eafebce254ef319e81d7a12 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Mon, 23 Feb 2026 13:32:07 +1300 Subject: [PATCH 1/5] CaptureFeedback now applies event processors fixes #4808 --- src/Sentry/SentryClient.cs | 11 +++++++-- test/Sentry.Tests/SentryClientTests.cs | 31 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/Sentry/SentryClient.cs b/src/Sentry/SentryClient.cs index 905070861e..065ba59c9a 100644 --- a/src/Sentry/SentryClient.cs +++ b/src/Sentry/SentryClient.cs @@ -117,12 +117,19 @@ public SentryId CaptureFeedback(SentryFeedback feedback, out CaptureFeedbackResu evt.Level = scope.Level; } + if (SentryEventHelper.ProcessEvent(evt, scope.GetAllEventProcessors(), hint, _options) is not { } processedEvent) + { + _options.LogWarning("Feedback dropped by event processor"); + result = CaptureFeedbackResult.UnknownError; + return SentryId.Empty; // Dropped by an event processor + } + var attachments = hint.Attachments.ToList(); - var envelope = Envelope.FromFeedback(evt, _options.DiagnosticLogger, attachments, scope.SessionUpdate); + var envelope = Envelope.FromFeedback(processedEvent, _options.DiagnosticLogger, attachments, scope.SessionUpdate); if (CaptureEnvelope(envelope)) { result = CaptureFeedbackResult.Success; - return evt.EventId; + return processedEvent.EventId; } result = CaptureFeedbackResult.UnknownError; return SentryId.Empty; diff --git a/test/Sentry.Tests/SentryClientTests.cs b/test/Sentry.Tests/SentryClientTests.cs index ce7f9c29ba..936d360651 100644 --- a/test/Sentry.Tests/SentryClientTests.cs +++ b/test/Sentry.Tests/SentryClientTests.cs @@ -976,6 +976,37 @@ public void CaptureFeedback_WithScope_ScopeCopiedToEvent() Assert.Equal(scope.Breadcrumbs, @event.Breadcrumbs); } + [Fact] + public void CaptureFeedback_EventProcessorApplied() + { + //Arrange + var feedback = new SentryFeedback("Everything is great!"); + var eventProcessor = Substitute.For(); + eventProcessor.Process(Arg.Any()).Returns(e => { + var evt = (SentryEvent)e[0]; + evt.Environment = "testing 123"; + return evt; + }); + _fixture.SentryOptions.AddEventProcessor(eventProcessor); + var sut = _fixture.GetSut(); + + Envelope envelope = null; + sut.Worker.When(w => w.EnqueueEnvelope(Arg.Any())) + .Do(callback => envelope = callback.Arg()); + + //Act + var result = sut.CaptureFeedback(feedback); + + //Assert + result.Should().NotBe(SentryId.Empty); + _ = sut.Worker.Received(1).EnqueueEnvelope(Arg.Any()); + envelope.Should().NotBeNull(); + envelope.Items.Should().Contain(item => item.TryGetType() == EnvelopeItem.TypeValueFeedback); + var item = envelope.Items.First(x => x.TryGetType() == EnvelopeItem.TypeValueFeedback); + var @event = (SentryEvent)((JsonSerializable)item.Payload).Source; + @event.Environment.Should().Be("testing 123"); + } + [Fact] public void CaptureFeedback_WithHint_HasHintAttachment() { From e36fe48472556e12723b3c0d26ef492d292ead46 Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Mon, 23 Feb 2026 00:48:40 +0000 Subject: [PATCH 2/5] Format code --- test/Sentry.Tests/SentryClientTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Sentry.Tests/SentryClientTests.cs b/test/Sentry.Tests/SentryClientTests.cs index 936d360651..a6ac2fe5dd 100644 --- a/test/Sentry.Tests/SentryClientTests.cs +++ b/test/Sentry.Tests/SentryClientTests.cs @@ -982,7 +982,8 @@ public void CaptureFeedback_EventProcessorApplied() //Arrange var feedback = new SentryFeedback("Everything is great!"); var eventProcessor = Substitute.For(); - eventProcessor.Process(Arg.Any()).Returns(e => { + eventProcessor.Process(Arg.Any()).Returns(e => + { var evt = (SentryEvent)e[0]; evt.Environment = "testing 123"; return evt; From 701429a3dc9610ebd25b80056ae58f221c5b2826 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Tue, 24 Feb 2026 14:19:13 +1300 Subject: [PATCH 3/5] Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f699acc9d5..b3244d5669 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixes - The SDK now logs a `Warning` instead of an `Error` when being ratelimited ([#4927](https://github.com/getsentry/sentry-dotnet/pull/4927)) +- Common tags such as `Environment` and `Release` are now correctly applied to CaptureFeedback events ([#4942](https://github.com/getsentry/sentry-dotnet/pull/4942)) ## 6.2.0-alpha.0 From b2508facb8d540f3609075ccbf4d389483cb6987 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Tue, 24 Feb 2026 14:35:33 +1300 Subject: [PATCH 4/5] Fixed data category on dropped feedback events --- src/Sentry/Internal/DataCategory.cs | 1 + src/Sentry/Internal/SentryEventHelper.cs | 5 +++-- src/Sentry/SentryClient.cs | 6 ++++-- test/Sentry.Tests/SentryClientTests.cs | 19 +++++++++++++++++++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/Sentry/Internal/DataCategory.cs b/src/Sentry/Internal/DataCategory.cs index 5ad06f8363..1b15e2310e 100644 --- a/src/Sentry/Internal/DataCategory.cs +++ b/src/Sentry/Internal/DataCategory.cs @@ -6,6 +6,7 @@ namespace Sentry.Internal; public static DataCategory Attachment = new("attachment"); public static DataCategory Default = new("default"); public static DataCategory Error = new("error"); + public static DataCategory Feedback = new("feedback"); public static DataCategory Internal = new("internal"); public static DataCategory Security = new("security"); public static DataCategory Session = new("session"); diff --git a/src/Sentry/Internal/SentryEventHelper.cs b/src/Sentry/Internal/SentryEventHelper.cs index eb3fbb7f9f..044ec3babe 100644 --- a/src/Sentry/Internal/SentryEventHelper.cs +++ b/src/Sentry/Internal/SentryEventHelper.cs @@ -4,7 +4,8 @@ namespace Sentry.Internal; internal static class SentryEventHelper { - public static SentryEvent? ProcessEvent(SentryEvent? evt, IEnumerable processors, SentryHint? hint, SentryOptions options) + public static SentryEvent? ProcessEvent(SentryEvent? evt, IEnumerable processors, + SentryHint? hint, SentryOptions options, DataCategory dataCategory) { if (evt == null) { @@ -19,7 +20,7 @@ internal static class SentryEventHelper processedEvent = processor.DoProcessEvent(processedEvent, effectiveHint); if (processedEvent == null) { - options.ClientReportRecorder.RecordDiscardedEvent(DiscardReason.EventProcessor, DataCategory.Error); + options.ClientReportRecorder.RecordDiscardedEvent(DiscardReason.EventProcessor, dataCategory); options.LogInfo("Event dropped by processor {0}", processor.GetType().Name); break; } diff --git a/src/Sentry/SentryClient.cs b/src/Sentry/SentryClient.cs index 065ba59c9a..60d9c69c4f 100644 --- a/src/Sentry/SentryClient.cs +++ b/src/Sentry/SentryClient.cs @@ -117,7 +117,8 @@ public SentryId CaptureFeedback(SentryFeedback feedback, out CaptureFeedbackResu evt.Level = scope.Level; } - if (SentryEventHelper.ProcessEvent(evt, scope.GetAllEventProcessors(), hint, _options) is not { } processedEvent) + if (SentryEventHelper.ProcessEvent(evt, scope.GetAllEventProcessors(), hint, _options, DataCategory.Feedback) + is not { } processedEvent) { _options.LogWarning("Feedback dropped by event processor"); result = CaptureFeedbackResult.UnknownError; @@ -352,7 +353,8 @@ private SentryId DoSendEvent(SentryEvent @event, SentryHint? hint, Scope? scope) } } - if (SentryEventHelper.ProcessEvent(@event, scope.GetAllEventProcessors(), hint, _options) is not { } processedEvent) + if (SentryEventHelper.ProcessEvent(@event, scope.GetAllEventProcessors(), hint, _options, DataCategory.Error) + is not { } processedEvent) { return SentryId.Empty; // Dropped by an event processor } diff --git a/test/Sentry.Tests/SentryClientTests.cs b/test/Sentry.Tests/SentryClientTests.cs index a6ac2fe5dd..953b5956f3 100644 --- a/test/Sentry.Tests/SentryClientTests.cs +++ b/test/Sentry.Tests/SentryClientTests.cs @@ -1008,6 +1008,25 @@ public void CaptureFeedback_EventProcessorApplied() @event.Environment.Should().Be("testing 123"); } + [Fact] + public void CaptureFeedback_EventDropped_SendsClientReport() + { + //Arrange + var feedback = new SentryFeedback("Everything is great!"); + var eventProcessor = Substitute.For(); + eventProcessor.Process(Arg.Any()).Returns(_ => null); + _fixture.SentryOptions.AddEventProcessor(eventProcessor); + var sut = _fixture.GetSut(); + + //Act + var result = sut.CaptureFeedback(feedback); + + //Assert + result.Should().Be(SentryId.Empty); + var expectedReason = DiscardReason.EventProcessor; + _fixture.ClientReportRecorder.Received(1).RecordDiscardedEvent(expectedReason, DataCategory.Feedback); + } + [Fact] public void CaptureFeedback_WithHint_HasHintAttachment() { From 00bc7d18a45bfdd6b359bcf8714bec3592162ea1 Mon Sep 17 00:00:00 2001 From: James Crosswell Date: Tue, 24 Feb 2026 14:43:26 +1300 Subject: [PATCH 5/5] . --- src/Sentry/Platforms/Cocoa/SentrySdk.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Sentry/Platforms/Cocoa/SentrySdk.cs b/src/Sentry/Platforms/Cocoa/SentrySdk.cs index 90adf733c9..89bc689013 100644 --- a/src/Sentry/Platforms/Cocoa/SentrySdk.cs +++ b/src/Sentry/Platforms/Cocoa/SentrySdk.cs @@ -295,7 +295,8 @@ private static bool SuppressNativeCrash(SentryOptions options, CocoaSdk.SentryEv } var sentryEvent = evt.ToSentryEvent(); - if (SentryEventHelper.ProcessEvent(sentryEvent, manualProcessors, null, options) is not { } processedEvent) + if (SentryEventHelper.ProcessEvent(sentryEvent, manualProcessors, null, options, DataCategory.Error) + is not { } processedEvent) { return null; }