Skip to content

Commit

Permalink
IHub.ResumeSession(): don't start a new session if pause wasn't calle…
Browse files Browse the repository at this point in the history
…d or if there is no active session (#1089)

* IHub.ResumeSession(): don't start a new session if pause wasn't called or if there is no active session

* Changelog

* rearrange

* asd
  • Loading branch information
Tyrrrz authored Jun 25, 2021
1 parent 9a07c9a commit 241ec58
Show file tree
Hide file tree
Showing 5 changed files with 87 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

- `IHub.ResumeSession()`: don't start a new session if pause wasn't called or if there is no active session ([#1089](https://github.com/getsentry/sentry-dotnet/pull/1089))

## 3.6.0

### Features
Expand Down
2 changes: 2 additions & 0 deletions src/Sentry/GlobalSessionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ internal class GlobalSessionManager : ISessionManager
// Internal for testing
internal Session? CurrentSession => _currentSession;

public bool IsSessionActive => _currentSession is not null;

public GlobalSessionManager(SentryOptions options, ISystemClock clock)
{
_options = options;
Expand Down
2 changes: 2 additions & 0 deletions src/Sentry/ISessionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ namespace Sentry
{
internal interface ISessionManager
{
bool IsSessionActive { get; }

SessionUpdate? StartSession();

SessionUpdate? EndSession(DateTimeOffset timestamp, SessionEndStatus status);
Expand Down
25 changes: 21 additions & 4 deletions src/Sentry/Internal/Hub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal class Hub : IHub, IDisposable
private readonly IDisposable _rootScope;
private readonly Enricher _enricher;

private DateTimeOffset _sessionPauseTimestamp;
private DateTimeOffset? _sessionPauseTimestamp;

// Internal for testability
internal ConditionalWeakTable<Exception, ISpan> ExceptionToSpanMap { get; } = new();
Expand Down Expand Up @@ -198,15 +198,29 @@ public void PauseSession()
{
lock (_sessionPauseLock)
{
_sessionPauseTimestamp = _clock.GetUtcNow();
// Only pause if there's anything to pause.
// This might race if a session is started at the same time,
// but that's fine.
if (_sessionManager.IsSessionActive)
{
_sessionPauseTimestamp = _clock.GetUtcNow();
}
}
}

public void ResumeSession()
{
lock (_sessionPauseLock)
{
var pauseDuration = (_clock.GetUtcNow() - _sessionPauseTimestamp).Duration();
// Ensure a session has been paused before
if (_sessionPauseTimestamp is not { } sessionPauseTimestamp)
{
return;
}

// If the pause duration exceeded tracking interval, start a new session
// (otherwise do nothing)
var pauseDuration = (_clock.GetUtcNow() - sessionPauseTimestamp).Duration();
if (pauseDuration >= _options.AutoSessionTrackingInterval)
{
_options.DiagnosticLogger?.LogDebug(
Expand All @@ -215,9 +229,12 @@ public void ResumeSession()
pauseDuration
);

EndSession(_sessionPauseTimestamp, SessionEndStatus.Exited);
EndSession(sessionPauseTimestamp, SessionEndStatus.Exited);
StartSession();
}

// Reset the pause timestamp since the session is now resumed
_sessionPauseTimestamp = null;
}
}

Expand Down
56 changes: 56 additions & 0 deletions test/Sentry.Tests/HubTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -876,5 +876,61 @@ public void ResumeSession_BeyondAutoTrackingInterval_EndsPreviousSessionAndStart
client.Received().CaptureSession(Arg.Is<SessionUpdate>(s => s.EndStatus == SessionEndStatus.Exited));
client.Received().CaptureSession(Arg.Is<SessionUpdate>(s => s.IsInitial));
}

[Fact]
public void ResumeSession_NoActiveSession_DoesNothing()
{
// Arrange
var client = Substitute.For<ISentryClient>();
var clock = Substitute.For<ISystemClock>();

var options = new SentryOptions
{
Dsn = DsnSamples.ValidDsnWithSecret,
AutoSessionTrackingInterval = TimeSpan.FromMilliseconds(10)
};

var hub = new Hub(client, clock, new GlobalSessionManager(options, clock), options);

clock.GetUtcNow().Returns(DateTimeOffset.Now);

hub.PauseSession();

clock.GetUtcNow().Returns(DateTimeOffset.Now + TimeSpan.FromDays(1));

// Act
hub.ResumeSession();

// Assert
client.DidNotReceive().CaptureSession(Arg.Any<SessionUpdate>());
}

[Fact]
public void ResumeSession_NoPausedSession_DoesNothing()
{
// Arrange
var client = Substitute.For<ISentryClient>();
var clock = Substitute.For<ISystemClock>();

var options = new SentryOptions
{
Dsn = DsnSamples.ValidDsnWithSecret,
AutoSessionTrackingInterval = TimeSpan.FromMilliseconds(10)
};

var hub = new Hub(client, clock, new GlobalSessionManager(options, clock), options);

clock.GetUtcNow().Returns(DateTimeOffset.Now);

hub.StartSession();

clock.GetUtcNow().Returns(DateTimeOffset.Now + TimeSpan.FromDays(1));

// Act
hub.ResumeSession();

// Assert
client.DidNotReceive().CaptureSession(Arg.Is<SessionUpdate>(s => s.EndStatus != null));
}
}
}

0 comments on commit 241ec58

Please sign in to comment.