Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update unobserved task exception integration #2034

Merged
merged 7 commits into from
Nov 9, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

- Simplify API for flushing events ([#2030](https://github.com/getsentry/sentry-dotnet/pull/2030))

### Fixes

- Update unobserved task exception integration ([#2034](https://github.com/getsentry/sentry-dotnet/pull/2034))

## 3.23.1

### Fixes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@

namespace Sentry.Integrations
{
internal class TaskUnobservedTaskExceptionIntegration : ISdkIntegration
internal class UnobservedTaskExceptionIntegration : ISdkIntegration
{
private readonly IAppDomain _appDomain;
private IHub? _hub;
private IHub _hub = null!;

internal TaskUnobservedTaskExceptionIntegration(IAppDomain? appDomain = null)
internal UnobservedTaskExceptionIntegration(IAppDomain? appDomain = null)
=> _appDomain = appDomain ?? AppDomainAdapter.Instance;

public void Register(IHub hub, SentryOptions _)
Expand All @@ -22,19 +22,24 @@ public void Register(IHub hub, SentryOptions _)
_appDomain.UnobservedTaskException += Handle;
}

// Internal for testability
#if !NET6_0_OR_GREATER
[HandleProcessCorruptedStateExceptions]
#endif
[SecurityCritical]
internal void Handle(object? sender, UnobservedTaskExceptionEventArgs e)
{
if (e.Exception is { } ex)
{
ex.Data[Mechanism.HandledKey] = false;
ex.Data[Mechanism.MechanismKey] = "UnobservedTaskException";
_ = _hub?.CaptureException(ex);
}
// The exception will never be null in any runtime.
// The annotation was corrected in .NET 5
// See: https://github.com/dotnet/runtime/issues/32454

#if NET5_0_OR_GREATER
var ex = e.Exception;
#else
var ex = e.Exception!;
#endif
ex.Data[Mechanism.HandledKey] = false;
ex.Data[Mechanism.MechanismKey] = "UnobservedTaskException";
_hub.CaptureException(ex);
}
}
}
2 changes: 1 addition & 1 deletion src/Sentry/SentryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,7 @@ public SentryOptions()
new AutoSessionTrackingIntegration(),
new AppDomainUnhandledExceptionIntegration(),
new AppDomainProcessExitIntegration(),
new TaskUnobservedTaskExceptionIntegration(),
new UnobservedTaskExceptionIntegration(),
#if NETFRAMEWORK
new NetFxInstallationsIntegration(),
#endif
Expand Down
10 changes: 9 additions & 1 deletion src/Sentry/SentryOptionsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,16 @@ public static void DisableDiagnosticSourceIntegration(this SentryOptions options
/// Disables the capture of errors through <see cref="TaskScheduler.UnobservedTaskException"/>.
/// </summary>
/// <param name="options">The SentryOptions to remove the integration from.</param>
[Obsolete("Method has been renamed to DisableUnobservedTaskExceptionCapture. Please update usage.")]
public static void DisableTaskUnobservedTaskExceptionCapture(this SentryOptions options) =>
options.RemoveIntegration<TaskUnobservedTaskExceptionIntegration>();
options.DisableUnobservedTaskExceptionCapture();

/// <summary>
/// Disables the capture of errors through <see cref="TaskScheduler.UnobservedTaskException"/>.
/// </summary>
/// <param name="options">The SentryOptions to remove the integration from.</param>
public static void DisableUnobservedTaskExceptionCapture(this SentryOptions options) =>
options.RemoveIntegration<UnobservedTaskExceptionIntegration>();

#if NETFRAMEWORK
/// <summary>
Expand Down
3 changes: 3 additions & 0 deletions test/Sentry.Tests/ApiApprovalTests.Run.Core3_1.verified.txt
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,10 @@ namespace Sentry
public static void DisableAppDomainUnhandledExceptionCapture(this Sentry.SentryOptions options) { }
public static void DisableDiagnosticSourceIntegration(this Sentry.SentryOptions options) { }
public static void DisableDuplicateEventDetection(this Sentry.SentryOptions options) { }
[System.Obsolete("Method has been renamed to DisableUnobservedTaskExceptionCapture. Please update " +
"usage.")]
public static void DisableTaskUnobservedTaskExceptionCapture(this Sentry.SentryOptions options) { }
public static void DisableUnobservedTaskExceptionCapture(this Sentry.SentryOptions options) { }
public static System.Collections.Generic.IEnumerable<Sentry.Extensibility.ISentryEventProcessor> GetAllEventProcessors(this Sentry.SentryOptions options) { }
public static System.Collections.Generic.IEnumerable<Sentry.Extensibility.ISentryEventExceptionProcessor> GetAllExceptionProcessors(this Sentry.SentryOptions options) { }
public static System.Collections.Generic.IEnumerable<Sentry.Extensibility.ISentryTransactionProcessor> GetAllTransactionProcessors(this Sentry.SentryOptions options) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,10 @@ namespace Sentry
public static void DisableAppDomainUnhandledExceptionCapture(this Sentry.SentryOptions options) { }
public static void DisableDuplicateEventDetection(this Sentry.SentryOptions options) { }
public static void DisableNetFxInstallationsIntegration(this Sentry.SentryOptions options) { }
[System.Obsolete("Method has been renamed to DisableUnobservedTaskExceptionCapture. Please update " +
"usage.")]
public static void DisableTaskUnobservedTaskExceptionCapture(this Sentry.SentryOptions options) { }
public static void DisableUnobservedTaskExceptionCapture(this Sentry.SentryOptions options) { }
public static System.Collections.Generic.IEnumerable<Sentry.Extensibility.ISentryEventProcessor> GetAllEventProcessors(this Sentry.SentryOptions options) { }
public static System.Collections.Generic.IEnumerable<Sentry.Extensibility.ISentryEventExceptionProcessor> GetAllExceptionProcessors(this Sentry.SentryOptions options) { }
public static System.Collections.Generic.IEnumerable<Sentry.Extensibility.ISentryTransactionProcessor> GetAllTransactionProcessors(this Sentry.SentryOptions options) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,10 @@ namespace Sentry
public static void DisableAppDomainUnhandledExceptionCapture(this Sentry.SentryOptions options) { }
public static void DisableDiagnosticSourceIntegration(this Sentry.SentryOptions options) { }
public static void DisableDuplicateEventDetection(this Sentry.SentryOptions options) { }
[System.Obsolete("Method has been renamed to DisableUnobservedTaskExceptionCapture. Please update " +
"usage.")]
public static void DisableTaskUnobservedTaskExceptionCapture(this Sentry.SentryOptions options) { }
public static void DisableUnobservedTaskExceptionCapture(this Sentry.SentryOptions options) { }
public static System.Collections.Generic.IEnumerable<Sentry.Extensibility.ISentryEventProcessor> GetAllEventProcessors(this Sentry.SentryOptions options) { }
public static System.Collections.Generic.IEnumerable<Sentry.Extensibility.ISentryEventExceptionProcessor> GetAllExceptionProcessors(this Sentry.SentryOptions options) { }
public static System.Collections.Generic.IEnumerable<Sentry.Extensibility.ISentryTransactionProcessor> GetAllTransactionProcessors(this Sentry.SentryOptions options) { }
Expand Down
8 changes: 4 additions & 4 deletions test/Sentry.Tests/SentryOptionsExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ public void DisableAppDomainUnhandledExceptionCapture_RemovesAppDomainUnhandledE
}

[Fact]
public void DisableTaskUnobservedTaskExceptionCapture_TaskUnobservedTaskExceptionIntegration()
public void DisableTaskUnobservedTaskExceptionCapture_UnobservedTaskExceptionIntegration()
{
Sut.DisableTaskUnobservedTaskExceptionCapture();
Sut.DisableUnobservedTaskExceptionCapture();
Assert.DoesNotContain(Sut.Integrations!,
p => p.GetType() == typeof(TaskUnobservedTaskExceptionIntegration));
p => p.GetType() == typeof(UnobservedTaskExceptionIntegration));
}

[Fact]
Expand Down Expand Up @@ -291,7 +291,7 @@ public void Integrations_Includes_AppDomainProcessExitIntegration()
[Fact]
public void Integrations_Includes_TaskUnobservedTaskExceptionIntegration()
{
Assert.Contains(Sut.Integrations!, i => i.GetType() == typeof(TaskUnobservedTaskExceptionIntegration));
Assert.Contains(Sut.Integrations!, i => i.GetType() == typeof(UnobservedTaskExceptionIntegration));
}

[Theory]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Sentry.Tests;

public class TaskUnobservedTaskExceptionIntegrationTests
public class UnobservedTaskExceptionIntegrationTests
{
private class Fixture
{
Expand All @@ -13,7 +13,7 @@ private class Fixture

public Fixture() => Hub.IsEnabled.Returns(true);

public TaskUnobservedTaskExceptionIntegration GetSut()
public UnobservedTaskExceptionIntegration GetSut()
=> new(AppDomain);
}

Expand Down Expand Up @@ -64,17 +64,6 @@ public void Handle_UnobservedTaskException_CaptureEvent()
}
#endif

[Fact]
public void Handle_NoException_NoCaptureEvent()
{
var sut = _fixture.GetSut();
sut.Register(_fixture.Hub, SentryOptions);

sut.Handle(this, new UnobservedTaskExceptionEventArgs(null));

_ = _fixture.Hub.DidNotReceive().CaptureEvent(Arg.Any<SentryEvent>());
}

[Fact]
public void Register_UnhandledException_Subscribes()
{
Expand Down