diff --git a/CHANGELOG.md b/CHANGELOG.md
index 270fb60358..5f1d0ef539 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,7 +5,11 @@
### Features
- GA release for Sentry Metrics ([#5023](https://github.com/getsentry/sentry-dotnet/pull/5023))
-
+
+### Fixes
+
+- Common tags such as `Environment` and `Release` and custom event processors are all now correctly applied to CaptureFeedback events ([#4942](https://github.com/getsentry/sentry-dotnet/pull/4942))
+
## 6.2.0
### Features
diff --git a/src/Sentry/CaptureFeedbackErrorReason.cs b/src/Sentry/CaptureFeedbackErrorReason.cs
index 728a7b1b47..0a2e5c177f 100644
--- a/src/Sentry/CaptureFeedbackErrorReason.cs
+++ b/src/Sentry/CaptureFeedbackErrorReason.cs
@@ -40,4 +40,8 @@ public enum CaptureFeedbackResult
/// Capture failed because the message is empty.
///
EmptyMessage,
+ ///
+ /// The was discarded by an event processor.
+ ///
+ DroppedByEventProcessor,
}
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/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;
}
diff --git a/src/Sentry/SentryClient.cs b/src/Sentry/SentryClient.cs
index 905070861e..64da285d5e 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, DataCategory.Feedback)
+ is not { } processedEvent)
+ {
+ result = CaptureFeedbackResult.DroppedByEventProcessor;
+ 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;
@@ -345,7 +352,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/ApiApprovalTests.Run.DotNet10_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt
index d614075852..a0c9848a7c 100644
--- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt
+++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet10_0.verified.txt
@@ -51,6 +51,7 @@ namespace Sentry
UnknownError = 1,
DisabledHub = 2,
EmptyMessage = 3,
+ DroppedByEventProcessor = 4,
}
public enum CheckInStatus
{
diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt
index d614075852..a0c9848a7c 100644
--- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt
+++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt
@@ -51,6 +51,7 @@ namespace Sentry
UnknownError = 1,
DisabledHub = 2,
EmptyMessage = 3,
+ DroppedByEventProcessor = 4,
}
public enum CheckInStatus
{
diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt
index d614075852..a0c9848a7c 100644
--- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt
+++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet9_0.verified.txt
@@ -51,6 +51,7 @@ namespace Sentry
UnknownError = 1,
DisabledHub = 2,
EmptyMessage = 3,
+ DroppedByEventProcessor = 4,
}
public enum CheckInStatus
{
diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt
index 8d15f59117..12c19434e6 100644
--- a/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt
+++ b/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt
@@ -51,6 +51,7 @@ namespace Sentry
UnknownError = 1,
DisabledHub = 2,
EmptyMessage = 3,
+ DroppedByEventProcessor = 4,
}
public enum CheckInStatus
{
diff --git a/test/Sentry.Tests/SentryClientTests.cs b/test/Sentry.Tests/SentryClientTests.cs
index ce7f9c29ba..1fedab2ff8 100644
--- a/test/Sentry.Tests/SentryClientTests.cs
+++ b/test/Sentry.Tests/SentryClientTests.cs
@@ -976,6 +976,58 @@ public void CaptureFeedback_WithScope_ScopeCopiedToEvent()
Assert.Equal(scope.Breadcrumbs, @event.Breadcrumbs);
}
+ [Fact]
+ public void CaptureFeedback_WithEventProcessor_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_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 id = sut.CaptureFeedback(feedback, out var result);
+
+ //Assert
+ result.Should().Be(CaptureFeedbackResult.DroppedByEventProcessor);
+ id.Should().Be(SentryId.Empty);
+ var expectedReason = DiscardReason.EventProcessor;
+ _fixture.ClientReportRecorder.Received(1).RecordDiscardedEvent(expectedReason, DataCategory.Feedback);
+ }
+
[Fact]
public void CaptureFeedback_WithHint_HasHintAttachment()
{