Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions src/Sentry/HubExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Sentry.Infrastructure;
using Sentry.Internal;
using Sentry.Internal.Extensions;
using Sentry.Protocol;

namespace Sentry;

Expand Down Expand Up @@ -268,8 +269,11 @@ public LockedScope(IHub hub)
public void Dispose() => _scope.Dispose();
}

internal static SentryId CaptureExceptionInternal(this IHub hub, Exception ex) =>
hub.CaptureEvent(new SentryEvent(ex));
internal static SentryId CaptureExceptionInternal(this IHub hub, Exception ex)
{
ex.Data[Mechanism.HandledKey] = false;
return hub.CaptureEvent(new SentryEvent(ex));
}
Comment thread
vladbrincoveanu marked this conversation as resolved.

/// <summary>
/// Captures the exception with a configurable scope callback.
Expand All @@ -281,6 +285,21 @@ internal static SentryId CaptureExceptionInternal(this IHub hub, Exception ex) =
public static SentryId CaptureException(this IHub hub, Exception ex, Action<Scope> configureScope) =>
hub.CaptureEvent(new SentryEvent(ex), configureScope);

/// <summary>
/// Captures the exception with a configurable scope callback, explicitly marking it as handled or unhandled.
/// </summary>
/// <param name="hub">The Sentry hub.</param>
/// <param name="ex">The exception.</param>
/// <param name="configureScope">The callback to configure the scope.</param>
/// <param name="handled">Whether the exception was handled. Recorded on the exception, overriding any flag
/// previously set on it, including one set via <see cref="SentryExceptionExtensions.SetSentryMechanism"/>.</param>
/// <returns>The Id of the event</returns>
public static SentryId CaptureException(this IHub hub, Exception ex, Action<Scope> configureScope, bool handled)
Comment thread
jamescrosswell marked this conversation as resolved.
Outdated
{
ex.Data[Mechanism.HandledKey] = handled;
return hub.CaptureEvent(new SentryEvent(ex), configureScope);
}
Comment thread
sentry[bot] marked this conversation as resolved.
Outdated

/// <summary>
/// Captures feedback from the user.
/// </summary>
Expand Down
13 changes: 4 additions & 9 deletions src/Sentry/Internal/MainExceptionProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,17 +174,12 @@ private static Mechanism GetMechanism(Exception exception, int id, int? parentId
mechanism.Handled = handled;
exception.Data.Remove(Mechanism.HandledKey);
}
else if (exception.StackTrace != null)
{
// The exception was thrown, but it was caught by the user, not an integration.
// Thus, we can mark it as handled.
mechanism.Handled = true;
}
else
{
// The exception was never thrown. It was just constructed and then captured.
// Thus, it is neither handled nor unhandled.
mechanism.Handled = null;
// https://getsentry.github.io/relay/relay_event_schema/protocol/struct.Mechanism.html#structfield.handled
// "Exceptions captured using capture_exception (called from user code) are handled=true as the user
// explicitly captured the exception (and therefore kind of handled it)."
mechanism.Handled = true;

@jamescrosswell jamescrosswell Jul 27, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be a change in behaviour. I think it probably makes sense... we can probably do it without making a major release - arguably it's a bug fix rather than an arbitrary change.

@dingsdax do you have any steer?

}

if (exception.Data[Mechanism.MechanismKey] is string mechanismType)
Comment thread
vladbrincoveanu marked this conversation as resolved.
Expand Down
20 changes: 20 additions & 0 deletions src/Sentry/SentryClientExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Sentry.Extensibility;
using Sentry.Internal;
using Sentry.Protocol;

namespace Sentry;

Expand All @@ -18,6 +19,25 @@ public static class SentryClientExtensions
public static SentryId CaptureException(this ISentryClient client, Exception ex) =>
client.IsEnabled ? client.CaptureEvent(new SentryEvent(ex)) : SentryId.Empty;

/// <summary>
/// Captures the exception, explicitly marking it as handled or unhandled.
/// </summary>
/// <param name="client">The Sentry client.</param>
/// <param name="ex">The exception.</param>
/// <param name="handled">Whether the exception was handled. Recorded on the exception, overriding any flag
/// previously set on it, including one set via <see cref="SentryExceptionExtensions.SetSentryMechanism"/>.</param>
/// <returns>The Id of the event</returns>
public static SentryId CaptureException(this ISentryClient client, Exception ex, bool handled)
{
if (!client.IsEnabled)
{
return SentryId.Empty;
}

ex.Data[Mechanism.HandledKey] = handled;
return client.CaptureEvent(new SentryEvent(ex));
}
Comment thread
cursor[bot] marked this conversation as resolved.

/// <summary>
/// Captures a message.
/// </summary>
Expand Down
26 changes: 26 additions & 0 deletions src/Sentry/SentrySdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,17 @@ public static SentryId CaptureEvent(SentryEvent evt, SentryHint? hint, Action<Sc
public static SentryId CaptureException(Exception exception)
=> CurrentHub.CaptureException(exception);

/// <summary>
/// Captures the exception, explicitly marking it as handled or unhandled.
/// </summary>
/// <param name="exception">The exception.</param>
/// <param name="handled">Whether the exception was handled. Recorded on the exception, overriding any flag
/// previously set on it, including one set via <see cref="SentryExceptionExtensions.SetSentryMechanism"/>.</param>
/// <returns>The Id of the event.</returns>
[DebuggerStepThrough]
public static SentryId CaptureException(Exception exception, bool handled)
=> CurrentHub.CaptureException(exception, handled);

/// <summary>
/// Captures the exception with a configurable scope.
/// </summary>
Expand All @@ -537,6 +548,21 @@ public static SentryId CaptureException(Exception exception)
public static SentryId CaptureException(Exception exception, Action<Scope> configureScope)
=> CurrentHub.CaptureException(exception, configureScope);

/// <summary>
/// Captures the exception with a configurable scope, explicitly marking it as handled or unhandled.
/// </summary>
/// <remarks>
/// This allows modifying a scope without affecting other events.
/// </remarks>
/// <param name="exception">The exception.</param>
/// <param name="configureScope">The callback to configure the scope.</param>
/// <param name="handled">Whether the exception was handled. Recorded on the exception, overriding any flag
/// previously set on it, including one set via <see cref="SentryExceptionExtensions.SetSentryMechanism"/>.</param>
/// <returns>The Id of the event.</returns>
[DebuggerStepThrough]
public static SentryId CaptureException(Exception exception, Action<Scope> configureScope, bool handled)
Comment thread
jamescrosswell marked this conversation as resolved.
Outdated
=> CurrentHub.CaptureException(exception, configureScope, handled);

/// <summary>
/// Captures the message.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
Value: my exception,
Mechanism: {
Type: generic,
Handled: true,
Synthetic: false,
IsExceptionGroup: false,
Data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
Value: my exception,
Mechanism: {
Type: generic,
Handled: true,
Synthetic: false,
IsExceptionGroup: false,
Data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
Value: my exception,
Mechanism: {
Type: generic,
Handled: true,
Synthetic: false,
IsExceptionGroup: false,
Data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
Value: my exception,
Mechanism: {
Type: generic,
Handled: true,
Synthetic: false,
IsExceptionGroup: false,
Data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
Value: my exception,
Mechanism: {
Type: generic,
Handled: true,
Synthetic: false,
IsExceptionGroup: false,
Data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
Value: my exception,
Mechanism: {
Type: generic,
Handled: true,
Synthetic: false,
IsExceptionGroup: false,
Data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ namespace Sentry
public static void AddBreadcrumb(this Sentry.IHub hub, string message, string? category = null, string? type = null, System.Collections.Generic.IDictionary<string, string>? data = null, Sentry.BreadcrumbLevel level = 0) { }
public static void AddBreadcrumb(this Sentry.IHub hub, Sentry.Infrastructure.ISystemClock? clock, string message, string? category = null, string? type = null, System.Collections.Generic.IDictionary<string, string>? data = null, Sentry.BreadcrumbLevel level = 0) { }
public static Sentry.SentryId CaptureException(this Sentry.IHub hub, System.Exception ex, System.Action<Sentry.Scope> configureScope) { }
public static Sentry.SentryId CaptureException(this Sentry.IHub hub, System.Exception ex, System.Action<Sentry.Scope> configureScope, bool handled) { }
public static Sentry.SentryId CaptureFeedback(this Sentry.IHub hub, Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureMessage(this Sentry.IHub hub, string message, System.Action<Sentry.Scope> configureScope, Sentry.SentryLevel level = 1) { }
public static void LockScope(this Sentry.IHub hub) { }
Expand Down Expand Up @@ -491,6 +492,7 @@ namespace Sentry
public static class SentryClientExtensions
{
public static Sentry.SentryId CaptureException(this Sentry.ISentryClient client, System.Exception ex) { }
public static Sentry.SentryId CaptureException(this Sentry.ISentryClient client, System.Exception ex, bool handled) { }
public static Sentry.SentryId CaptureFeedback(this Sentry.ISentryClient client, Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureFeedback(this Sentry.ISentryClient client, 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(this Sentry.ISentryClient client, string message, Sentry.SentryLevel level = 1) { }
Expand Down Expand Up @@ -978,6 +980,8 @@ namespace Sentry
public static Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.SentryHint? hint, System.Action<Sentry.Scope> configureScope) { }
public static Sentry.SentryId CaptureException(System.Exception exception) { }
public static Sentry.SentryId CaptureException(System.Exception exception, System.Action<Sentry.Scope> configureScope) { }
public static Sentry.SentryId CaptureException(System.Exception exception, bool handled) { }
public static Sentry.SentryId CaptureException(System.Exception exception, System.Action<Sentry.Scope> configureScope, bool handled) { }
public static Sentry.SentryId CaptureFeedback(Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureFeedback(Sentry.SentryFeedback feedback, out Sentry.CaptureFeedbackResult result, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ namespace Sentry
public static void AddBreadcrumb(this Sentry.IHub hub, string message, string? category = null, string? type = null, System.Collections.Generic.IDictionary<string, string>? data = null, Sentry.BreadcrumbLevel level = 0) { }
public static void AddBreadcrumb(this Sentry.IHub hub, Sentry.Infrastructure.ISystemClock? clock, string message, string? category = null, string? type = null, System.Collections.Generic.IDictionary<string, string>? data = null, Sentry.BreadcrumbLevel level = 0) { }
public static Sentry.SentryId CaptureException(this Sentry.IHub hub, System.Exception ex, System.Action<Sentry.Scope> configureScope) { }
public static Sentry.SentryId CaptureException(this Sentry.IHub hub, System.Exception ex, System.Action<Sentry.Scope> configureScope, bool handled) { }
public static Sentry.SentryId CaptureFeedback(this Sentry.IHub hub, Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureMessage(this Sentry.IHub hub, string message, System.Action<Sentry.Scope> configureScope, Sentry.SentryLevel level = 1) { }
public static void LockScope(this Sentry.IHub hub) { }
Expand Down Expand Up @@ -491,6 +492,7 @@ namespace Sentry
public static class SentryClientExtensions
{
public static Sentry.SentryId CaptureException(this Sentry.ISentryClient client, System.Exception ex) { }
public static Sentry.SentryId CaptureException(this Sentry.ISentryClient client, System.Exception ex, bool handled) { }
public static Sentry.SentryId CaptureFeedback(this Sentry.ISentryClient client, Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureFeedback(this Sentry.ISentryClient client, 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(this Sentry.ISentryClient client, string message, Sentry.SentryLevel level = 1) { }
Expand Down Expand Up @@ -978,6 +980,8 @@ namespace Sentry
public static Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.SentryHint? hint, System.Action<Sentry.Scope> configureScope) { }
public static Sentry.SentryId CaptureException(System.Exception exception) { }
public static Sentry.SentryId CaptureException(System.Exception exception, System.Action<Sentry.Scope> configureScope) { }
public static Sentry.SentryId CaptureException(System.Exception exception, bool handled) { }
public static Sentry.SentryId CaptureException(System.Exception exception, System.Action<Sentry.Scope> configureScope, bool handled) { }
public static Sentry.SentryId CaptureFeedback(Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureFeedback(Sentry.SentryFeedback feedback, out Sentry.CaptureFeedbackResult result, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ namespace Sentry
public static void AddBreadcrumb(this Sentry.IHub hub, string message, string? category = null, string? type = null, System.Collections.Generic.IDictionary<string, string>? data = null, Sentry.BreadcrumbLevel level = 0) { }
public static void AddBreadcrumb(this Sentry.IHub hub, Sentry.Infrastructure.ISystemClock? clock, string message, string? category = null, string? type = null, System.Collections.Generic.IDictionary<string, string>? data = null, Sentry.BreadcrumbLevel level = 0) { }
public static Sentry.SentryId CaptureException(this Sentry.IHub hub, System.Exception ex, System.Action<Sentry.Scope> configureScope) { }
public static Sentry.SentryId CaptureException(this Sentry.IHub hub, System.Exception ex, System.Action<Sentry.Scope> configureScope, bool handled) { }
public static Sentry.SentryId CaptureFeedback(this Sentry.IHub hub, Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureMessage(this Sentry.IHub hub, string message, System.Action<Sentry.Scope> configureScope, Sentry.SentryLevel level = 1) { }
public static void LockScope(this Sentry.IHub hub) { }
Expand Down Expand Up @@ -491,6 +492,7 @@ namespace Sentry
public static class SentryClientExtensions
{
public static Sentry.SentryId CaptureException(this Sentry.ISentryClient client, System.Exception ex) { }
public static Sentry.SentryId CaptureException(this Sentry.ISentryClient client, System.Exception ex, bool handled) { }
public static Sentry.SentryId CaptureFeedback(this Sentry.ISentryClient client, Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureFeedback(this Sentry.ISentryClient client, 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(this Sentry.ISentryClient client, string message, Sentry.SentryLevel level = 1) { }
Expand Down Expand Up @@ -978,6 +980,8 @@ namespace Sentry
public static Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, Sentry.SentryHint? hint, System.Action<Sentry.Scope> configureScope) { }
public static Sentry.SentryId CaptureException(System.Exception exception) { }
public static Sentry.SentryId CaptureException(System.Exception exception, System.Action<Sentry.Scope> configureScope) { }
public static Sentry.SentryId CaptureException(System.Exception exception, bool handled) { }
public static Sentry.SentryId CaptureException(System.Exception exception, System.Action<Sentry.Scope> configureScope, bool handled) { }
public static Sentry.SentryId CaptureFeedback(Sentry.SentryFeedback feedback, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureFeedback(Sentry.SentryFeedback feedback, System.Action<Sentry.Scope> configureScope, Sentry.SentryHint? hint = null) { }
public static Sentry.SentryId CaptureFeedback(Sentry.SentryFeedback feedback, out Sentry.CaptureFeedbackResult result, Sentry.Scope? scope = null, Sentry.SentryHint? hint = null) { }
Expand Down
Loading
Loading