Skip to content

Commit

Permalink
fix: unhandled error crashed session (#1193)
Browse files Browse the repository at this point in the history
  • Loading branch information
bruno-garcia authored Sep 10, 2021
1 parent 8a30540 commit 997a310
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 4 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Fixes

- Exceptions from UnhandledExceptionIntegration were not marking sessions as crashed ([#1193](https://github.com/getsentry/sentry-dotnet/pull/1193))

## 3.9.1

### Fixes
Expand Down
6 changes: 2 additions & 4 deletions src/Sentry/Internal/Hub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -304,15 +304,13 @@ public SentryId CaptureEvent(SentryEvent evt, Scope? scope = null)

actualScope.SessionUpdate = evt switch
{
// TODO: Extract both branches as internal extension methods (IsCrashed and IsErrored):

// Event contains a terminal exception -> end session as crashed
var e when e.SentryExceptions?.Any(x => !(x.Mechanism?.Handled ?? true)) ?? false =>
var e when e.HasUnhandledException =>
_sessionManager.EndSession(SessionEndStatus.Crashed),

// Event contains a non-terminal exception -> report error
// (this might return null if the session has already reported errors before)
var e when e.Exception is not null || e.SentryExceptions?.Any() == true =>
var e when e.HasException =>
_sessionManager.ReportError(),

// Event doesn't contain any kind of exception -> no reason to attach session update
Expand Down
7 changes: 7 additions & 0 deletions src/Sentry/SentryEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,13 @@ public IReadOnlyList<string> Fingerprint
/// <inheritdoc />
public IReadOnlyDictionary<string, string> Tags => _tags ??= new Dictionary<string, string>();

internal bool HasException => Exception is not null || SentryExceptions?.Any() == true;

internal bool HasUnhandledException => (SentryExceptions?.Any(e => !(e.Mechanism?.Handled ?? true)) ?? false)
// Before event is processed by the client and SentryExceptions created.
// See: AppDomainUnhandledExceptionIntegration
|| Exception?.Data[Mechanism.HandledKey] is false;

/// <summary>
/// Creates a new instance of <see cref="T:Sentry.SentryEvent" />.
/// </summary>
Expand Down
33 changes: 33 additions & 0 deletions test/Sentry.Tests/HubTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Sentry;
using Sentry.Extensibility;
using Sentry.Infrastructure;
using Sentry.Integrations;
using Sentry.Internal;
using Sentry.Protocol;
using Sentry.Protocol.Envelopes;
Expand Down Expand Up @@ -350,6 +351,38 @@ public void CaptureEvent_ActiveSession_UnhandledExceptionSessionEndedAsCrashed()
));
}

[Fact]
public void AppDomainUnhandledExceptionIntegration_ActiveSession_UnhandledExceptionSessionEndedAsCrashed()
{
// Arrange
var worker = Substitute.For<IBackgroundWorker>();

var options = new SentryOptions { Dsn = DsnSamples.ValidDsnWithSecret };
var client = new SentryClient(options, worker);
var hub = new Hub(options, client);

var integration = new AppDomainUnhandledExceptionIntegration(Substitute.For<IAppDomain>());
integration.Register(hub, options);

hub.StartSession();

// Act
// Simulate a terminating exception
integration.Handle(this, new UnhandledExceptionEventArgs(new Exception("test"), true));

// Assert
worker.Received().EnqueueEnvelope(
Arg.Is<Envelope>(e =>
e.Items
.Select(i => i.Payload)
.OfType<JsonSerializable>()
.Select(i => i.Source)
.OfType<SessionUpdate>()
.Single()
.EndStatus == SessionEndStatus.Crashed
));
}

[Fact]
public void StartTransaction_NameOpDescription_Works()
{
Expand Down

0 comments on commit 997a310

Please sign in to comment.