Skip to content
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Features

- Added `CaptureFeedback` overload with `configureScope` parameter ([#4073](https://github.com/getsentry/sentry-dotnet/pull/4073))
- Custom SessionReplay masks in MAUI Android apps ([#4121](https://github.com/getsentry/sentry-dotnet/pull/4121))

### Fixes
Expand Down
7 changes: 7 additions & 0 deletions src/Sentry/Extensibility/DisabledHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,13 @@ public bool CaptureEnvelope(Envelope envelope)
/// </summary>
public SentryId CaptureEvent(SentryEvent evt, Scope? scope = null, SentryHint? hint = null) => SentryId.Empty;

/// <summary>
/// No-Op.
/// </summary>
public void CaptureFeedback(SentryFeedback feedback, Action<Scope> configureScope, SentryHint? hint = null)
{
}

/// <summary>
/// No-Op.
/// </summary>
Expand Down
8 changes: 8 additions & 0 deletions src/Sentry/Extensibility/HubAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,14 @@ public SentryId CaptureEvent(SentryEvent evt, Scope? scope)
public SentryId CaptureEvent(SentryEvent evt, Scope? scope, SentryHint? hint = null)
=> SentrySdk.CaptureEvent(evt, scope, hint);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>.
/// </summary>
[DebuggerStepThrough]
[EditorBrowsable(EditorBrowsableState.Never)]
public void CaptureFeedback(SentryFeedback feedback, Action<Scope> configureScope, SentryHint? hint = null)
=> SentrySdk.CaptureFeedback(feedback, configureScope, hint);

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>.
/// </summary>
Expand Down
8 changes: 8 additions & 0 deletions src/Sentry/IHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,12 @@ public TransactionContext ContinueTrace(
/// <param name="configureScope">The callback to configure the scope.</param>
/// <returns></returns>
public SentryId CaptureEvent(SentryEvent evt, SentryHint? hint, Action<Scope> configureScope);

/// <summary>
/// Captures feedback from the user.
/// </summary>
/// <param name="feedback">The feedback to send to Sentry.</param>
/// <param name="configureScope">Callback method to configure the scope.</param>
/// <param name="hint">An optional hint providing high level context for the source of the event, including attachments</param>
public void CaptureFeedback(SentryFeedback feedback, Action<Scope> configureScope, SentryHint? hint = null);
}
31 changes: 29 additions & 2 deletions src/Sentry/Internal/Hub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -506,15 +506,42 @@ private SentryId CaptureEvent(SentryEvent evt, SentryHint? hint, Scope scope)
}
}

public void CaptureFeedback(SentryFeedback feedback, Action<Scope> configureScope, SentryHint? hint = null)
{
if (!IsEnabled)
{
return;
}

try
{
var clonedScope = CurrentScope.Clone();
configureScope(clonedScope);

CaptureFeedback(feedback, clonedScope, hint);
}
catch (Exception e)
{
_options.LogError(e, "Failure to capture feedback");
}
}

public void CaptureFeedback(SentryFeedback feedback, Scope? scope = null, SentryHint? hint = null)
{
if (!IsEnabled)
{
return;
}

scope ??= CurrentScope;
CurrentClient.CaptureFeedback(feedback, scope, hint);
try
{
scope ??= CurrentScope;
CurrentClient.CaptureFeedback(feedback, scope, hint);
}
catch (Exception e)
{
_options.LogError(e, "Failure to capture feedback");
}
}

#if MEMORY_DUMP_SUPPORTED
Expand Down
7 changes: 7 additions & 0 deletions src/Sentry/SentrySdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,13 @@ public static SentryId CaptureMessage(string message, SentryLevel level = Sentry
public static SentryId CaptureMessage(string message, Action<Scope> configureScope, SentryLevel level = SentryLevel.Info)
=> CurrentHub.CaptureMessage(message, configureScope, level);

/// <summary>
/// Captures feedback from the user.
/// </summary>
[DebuggerStepThrough]
public static void CaptureFeedback(SentryFeedback feedback, Action<Scope> configureScope, SentryHint? hint = null)
=> CurrentHub.CaptureFeedback(feedback, configureScope, hint);

/// <summary>
/// Captures feedback from the user.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ namespace Sentry
void BindException(System.Exception exception, Sentry.ISpan span);
Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, System.Action<Sentry.Scope> configureScope);
Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.SentryHint? hint, System.Action<Sentry.Scope> configureScope);
void CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null);
Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null);
Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null);
void EndSession(Sentry.SessionEndStatus status = 0);
Expand Down Expand Up @@ -824,6 +825,7 @@ namespace Sentry
public static Sentry.SentryId CaptureException(System.Exception exception) { }
public static Sentry.SentryId CaptureException(System.Exception exception, System.Action<Sentry.Scope> configureScope) { }
public static void CaptureFeedback(Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public static void CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public static void CaptureFeedback(string message, string? contactEmail = null, string? name = null, string? replayId = null, string? url = null, Sentry.SentryId? associatedEventId = default, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureMessage(string message, Sentry.SentryLevel level = 1) { }
public static Sentry.SentryId CaptureMessage(string message, System.Action<Sentry.Scope> configureScope, Sentry.SentryLevel level = 1) { }
Expand Down Expand Up @@ -1334,6 +1336,7 @@ namespace Sentry.Extensibility
public Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.SentryHint? hint, System.Action<Sentry.Scope> configureScope) { }
public void CaptureFeedback(Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public void CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public void CaptureSession(Sentry.SessionUpdate sessionUpdate) { }
public void CaptureTransaction(Sentry.SentryTransaction transaction) { }
public void CaptureTransaction(Sentry.SentryTransaction transaction, Sentry.Scope? scope, Sentry.SentryHint? hint) { }
Expand Down Expand Up @@ -1380,6 +1383,7 @@ namespace Sentry.Extensibility
public Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.SentryHint? hint, System.Action<Sentry.Scope> configureScope) { }
public Sentry.SentryId CaptureException(System.Exception exception) { }
public void CaptureFeedback(Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public void CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public void CaptureSession(Sentry.SessionUpdate sessionUpdate) { }
public void CaptureTransaction(Sentry.SentryTransaction transaction) { }
public void CaptureTransaction(Sentry.SentryTransaction transaction, Sentry.Scope? scope, Sentry.SentryHint? hint) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ namespace Sentry
void BindException(System.Exception exception, Sentry.ISpan span);
Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, System.Action<Sentry.Scope> configureScope);
Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.SentryHint? hint, System.Action<Sentry.Scope> configureScope);
void CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null);
Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null);
Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null);
void EndSession(Sentry.SessionEndStatus status = 0);
Expand Down Expand Up @@ -824,6 +825,7 @@ namespace Sentry
public static Sentry.SentryId CaptureException(System.Exception exception) { }
public static Sentry.SentryId CaptureException(System.Exception exception, System.Action<Sentry.Scope> configureScope) { }
public static void CaptureFeedback(Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public static void CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public static void CaptureFeedback(string message, string? contactEmail = null, string? name = null, string? replayId = null, string? url = null, Sentry.SentryId? associatedEventId = default, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureMessage(string message, Sentry.SentryLevel level = 1) { }
public static Sentry.SentryId CaptureMessage(string message, System.Action<Sentry.Scope> configureScope, Sentry.SentryLevel level = 1) { }
Expand Down Expand Up @@ -1334,6 +1336,7 @@ namespace Sentry.Extensibility
public Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.SentryHint? hint, System.Action<Sentry.Scope> configureScope) { }
public void CaptureFeedback(Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public void CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public void CaptureSession(Sentry.SessionUpdate sessionUpdate) { }
public void CaptureTransaction(Sentry.SentryTransaction transaction) { }
public void CaptureTransaction(Sentry.SentryTransaction transaction, Sentry.Scope? scope, Sentry.SentryHint? hint) { }
Expand Down Expand Up @@ -1380,6 +1383,7 @@ namespace Sentry.Extensibility
public Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.SentryHint? hint, System.Action<Sentry.Scope> configureScope) { }
public Sentry.SentryId CaptureException(System.Exception exception) { }
public void CaptureFeedback(Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public void CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public void CaptureSession(Sentry.SessionUpdate sessionUpdate) { }
public void CaptureTransaction(Sentry.SentryTransaction transaction) { }
public void CaptureTransaction(Sentry.SentryTransaction transaction, Sentry.Scope? scope, Sentry.SentryHint? hint) { }
Expand Down
4 changes: 4 additions & 0 deletions test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ namespace Sentry
void BindException(System.Exception exception, Sentry.ISpan span);
Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, System.Action<Sentry.Scope> configureScope);
Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.SentryHint? hint, System.Action<Sentry.Scope> configureScope);
void CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null);
Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null);
Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null);
void EndSession(Sentry.SessionEndStatus status = 0);
Expand Down Expand Up @@ -805,6 +806,7 @@ namespace Sentry
public static Sentry.SentryId CaptureException(System.Exception exception) { }
public static Sentry.SentryId CaptureException(System.Exception exception, System.Action<Sentry.Scope> configureScope) { }
public static void CaptureFeedback(Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public static void CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public static void CaptureFeedback(string message, string? contactEmail = null, string? name = null, string? replayId = null, string? url = null, Sentry.SentryId? associatedEventId = default, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureMessage(string message, Sentry.SentryLevel level = 1) { }
public static Sentry.SentryId CaptureMessage(string message, System.Action<Sentry.Scope> configureScope, Sentry.SentryLevel level = 1) { }
Expand Down Expand Up @@ -1315,6 +1317,7 @@ namespace Sentry.Extensibility
public Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.SentryHint? hint, System.Action<Sentry.Scope> configureScope) { }
public void CaptureFeedback(Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public void CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public void CaptureSession(Sentry.SessionUpdate sessionUpdate) { }
public void CaptureTransaction(Sentry.SentryTransaction transaction) { }
public void CaptureTransaction(Sentry.SentryTransaction transaction, Sentry.Scope? scope, Sentry.SentryHint? hint) { }
Expand Down Expand Up @@ -1361,6 +1364,7 @@ namespace Sentry.Extensibility
public Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.SentryHint? hint, System.Action<Sentry.Scope> configureScope) { }
public Sentry.SentryId CaptureException(System.Exception exception) { }
public void CaptureFeedback(Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public void CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public void CaptureSession(Sentry.SessionUpdate sessionUpdate) { }
public void CaptureTransaction(Sentry.SentryTransaction transaction) { }
public void CaptureTransaction(Sentry.SentryTransaction transaction, Sentry.Scope? scope, Sentry.SentryHint? hint) { }
Expand Down
17 changes: 17 additions & 0 deletions test/Sentry.Tests/Extensibility/HubAdapterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,23 @@ public void CaptureEvent_WithScope_MockInvoked()
Hub.Received(1).CaptureEvent(expectedEvent, expectedScope);
}

[Fact]
public void CaptureFeedback_MockInvoked()
{
var expected = new SentryFeedback("foo");
HubAdapter.Instance.CaptureFeedback(expected);
Hub.Received(1).CaptureFeedback(expected);
}

[Fact]
public void CaptureFeedback_WithScope_MockInvoked()
{
var expectedEvent = new SentryFeedback("foo");
var expectedScope = new Scope();
HubAdapter.Instance.CaptureFeedback(expectedEvent, expectedScope);
Hub.Received(1).CaptureFeedback(expectedEvent, expectedScope);
}

[Fact]
public void CaptureException_MockInvoked()
{
Expand Down
21 changes: 21 additions & 0 deletions test/Sentry.Tests/HubTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1596,6 +1596,27 @@ public void CaptureFeedback_HubEnabled(bool enabled)
_fixture.Client.Received(enabled ? 1 : 0).CaptureFeedback(Arg.Any<SentryFeedback>(), Arg.Any<Scope>(), Arg.Any<SentryHint>());
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void CaptureFeedback_ConfigureScope_ScopeApplied(bool enabled)
{
// Arrange
var hub = _fixture.GetSut();
if (!enabled)
{
hub.Dispose();
}

var feedback = new SentryFeedback("Test feedback");

// Act
hub.CaptureFeedback(feedback, s => s.SetTag("foo", "bar"));

// Assert
_fixture.Client.Received(enabled ? 1 : 0).CaptureFeedback(Arg.Any<SentryFeedback>(), Arg.Is<Scope>(s => s.Tags["foo"] == "bar"), Arg.Any<SentryHint>());
}

[Theory]
[InlineData(true)]
[InlineData(false)]
Expand Down
17 changes: 17 additions & 0 deletions test/Sentry.Tests/SentrySdkTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,23 @@ public void CaptureEvent_WithConfiguredScope_ScopeCallbackGetsInvoked()
Assert.True(scopeCallbackWasInvoked);
}

[Fact]
public void CaptureFeedback_WithConfiguredScope_ScopeCallbackGetsInvoked()
{
using var _ = SentrySdk.Init(o =>
{
o.Dsn = ValidDsn;
o.AutoSessionTracking = false;
o.BackgroundWorker = Substitute.For<IBackgroundWorker>();
o.InitNativeSdks = false;
});

var scopeCallbackWasInvoked = false;
SentrySdk.CaptureFeedback(new SentryFeedback("Foo"), _ => scopeCallbackWasInvoked = true);

Assert.True(scopeCallbackWasInvoked);
}

[Fact]
public void CaptureException_WithConfiguredScope_ScopeCallbackGetsInvoked()
{
Expand Down
Loading