Skip to content

Commit b63aa7b

Browse files
authored
feat: Trace Generation Integration (#2123)
1 parent f97cb71 commit b63aa7b

File tree

6 files changed

+150
-3
lines changed

6 files changed

+150
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
### Features
1010

11+
- The trace used to connect errors on different layers of your game now gets regenerated every time the app gains focus again, or the active scene changes ([#2123](https://github.com/getsentry/sentry-unity/pull/2123))
1112
- The SDK now links errors and events (managed and native errors) via `trace ID`. This allows you to correlate events captured from different layers of your game ([#1997](https://github.com/getsentry/sentry-unity/pull/1997), [#2089](https://github.com/getsentry/sentry-unity/pull/2089), [#2106](https://github.com/getsentry/sentry-unity/pull/2106))
1213
- Drastically improved performance of scope sync when targeting Android ([#2107](https://github.com/getsentry/sentry-unity/pull/2107))
1314
- The SDK now reports the game's name as part of the app context ([2083](https://github.com/getsentry/sentry-unity/pull/2083))

src/Sentry.Unity/Integrations/SessionIntegration.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ public void Register(IHub hub, SentryOptions options)
1919
return;
2020
}
2121

22-
options.DiagnosticLogger?.LogDebug("Registering Session integration.");
23-
2422
_sentryMonoBehaviour.ApplicationResuming += () =>
2523
{
2624
options.DiagnosticLogger?.LogDebug("Resuming session.");
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using Sentry.Extensibility;
2+
using Sentry.Integrations;
3+
4+
namespace Sentry.Unity.Integrations;
5+
6+
internal sealed class TraceGenerationIntegration : ISdkIntegration
7+
{
8+
private readonly ISceneManager _sceneManager;
9+
private readonly ISentryMonoBehaviour _sentryMonoBehaviour;
10+
11+
public TraceGenerationIntegration(SentryMonoBehaviour sentryMonoBehaviour) : this(sentryMonoBehaviour, SceneManagerAdapter.Instance)
12+
{ }
13+
14+
internal TraceGenerationIntegration(ISentryMonoBehaviour sentryMonoBehaviour, ISceneManager sceneManager)
15+
{
16+
_sceneManager = sceneManager;
17+
_sentryMonoBehaviour = sentryMonoBehaviour;
18+
}
19+
20+
public void Register(IHub hub, SentryOptions options)
21+
{
22+
hub.ConfigureScope(UpdatePropagationContext);
23+
24+
_sentryMonoBehaviour.ApplicationResuming += () =>
25+
{
26+
options.DiagnosticLogger?.LogDebug("Application resumed. Creating new Trace.");
27+
hub.ConfigureScope(UpdatePropagationContext);
28+
};
29+
30+
_sceneManager.ActiveSceneChanged += (_, _) =>
31+
{
32+
options.DiagnosticLogger?.LogDebug("Active Scene changed. Creating new Trace.");
33+
hub.ConfigureScope(UpdatePropagationContext);
34+
};
35+
}
36+
37+
private static void UpdatePropagationContext(Scope scope) =>
38+
scope.SetPropagationContext(new SentryPropagationContext());
39+
}

src/Sentry.Unity/SentryMonoBehaviour.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@
44

55
namespace Sentry.Unity;
66

7+
internal interface ISentryMonoBehaviour
8+
{
9+
event Action? ApplicationResuming;
10+
}
11+
712
/// <summary>
813
/// Singleton and DontDestroyOnLoad setup.
914
/// </summary>
1015
[AddComponentMenu("")] // Hides it from being added as a component in the inspector
11-
public partial class SentryMonoBehaviour : MonoBehaviour
16+
public partial class SentryMonoBehaviour : MonoBehaviour, ISentryMonoBehaviour
1217
{
1318
private static SentryMonoBehaviour? _instance;
1419
public static SentryMonoBehaviour Instance

src/Sentry.Unity/SentryUnityOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ internal SentryUnityOptions(SentryMonoBehaviour behaviour, IApplication applicat
319319
this.AddIntegration(new UnityBeforeSceneLoadIntegration());
320320
this.AddIntegration(new SceneManagerIntegration());
321321
this.AddIntegration(new SessionIntegration(behaviour));
322+
this.AddIntegration(new TraceGenerationIntegration(behaviour));
322323

323324
this.AddExceptionFilter(new UnityBadGatewayExceptionFilter());
324325
this.AddExceptionFilter(new UnityWebExceptionFilter());
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
using System;
2+
using System.Linq;
3+
using NUnit.Framework;
4+
using Sentry.Unity.Integrations;
5+
using Sentry.Unity.Tests.SharedClasses;
6+
using Sentry.Unity.Tests.Stubs;
7+
using static Sentry.Unity.Tests.SceneManagerIntegrationTests;
8+
9+
namespace Sentry.Unity.Tests;
10+
11+
public class TraceGenerationIntegrationTests
12+
{
13+
private class Fixture
14+
{
15+
public FakeSceneManager SceneManager { get; set; } = new();
16+
public TestSentryMonoBehaviour SentryMonoBehaviour { get; set; } = new();
17+
public TestHub TestHub { get; set; } = new();
18+
public TestLogger Logger { get; set; } = new();
19+
public SentryOptions SentryOptions { get; set; }
20+
21+
public Fixture() => SentryOptions = new SentryOptions { DiagnosticLogger = Logger };
22+
23+
public TraceGenerationIntegration GetSut() => new(SentryMonoBehaviour, SceneManager);
24+
}
25+
26+
private readonly Fixture _fixture = new();
27+
28+
[SetUp]
29+
public void SetUp()
30+
{
31+
_fixture.TestHub = new TestHub();
32+
SentrySdk.UseHub(_fixture.TestHub);
33+
}
34+
35+
[Test]
36+
public void TraceGeneration_OnRegister_GeneratesInitialTrace()
37+
{
38+
// Arrange
39+
var sut = _fixture.GetSut();
40+
41+
// Act
42+
sut.Register(_fixture.TestHub, _fixture.SentryOptions);
43+
44+
// Assert
45+
var configureScope = _fixture.TestHub.ConfigureScopeCalls.Single();
46+
var scope = new Scope(_fixture.SentryOptions);
47+
var initialPropagationContext = scope.PropagationContext;
48+
configureScope(scope);
49+
50+
Assert.AreNotEqual(initialPropagationContext, scope.PropagationContext);
51+
}
52+
53+
[Test]
54+
public void TraceGeneration_OnApplicationResume_GeneratesNewTrace()
55+
{
56+
// Arrange
57+
var sut = _fixture.GetSut();
58+
sut.Register(_fixture.TestHub, _fixture.SentryOptions);
59+
var initialCallsCount = _fixture.TestHub.ConfigureScopeCalls.Count;
60+
61+
// Act
62+
_fixture.SentryMonoBehaviour.ResumeApplication();
63+
64+
// Assert
65+
// Calling 'Register' already generated a trace, so we expect 1+1 calls to ConfigureScope
66+
Assert.AreEqual(initialCallsCount + 1, _fixture.TestHub.ConfigureScopeCalls.Count);
67+
var configureScope = _fixture.TestHub.ConfigureScopeCalls.Last();
68+
var scope = new Scope(_fixture.SentryOptions);
69+
var initialPropagationContext = scope.PropagationContext;
70+
configureScope(scope);
71+
72+
Assert.AreNotEqual(initialPropagationContext, scope.PropagationContext);
73+
}
74+
75+
[Test]
76+
public void TraceGeneration_OnActiveSceneChange_GeneratesNewTrace()
77+
{
78+
// Arrange
79+
var sut = _fixture.GetSut();
80+
sut.Register(_fixture.TestHub, _fixture.SentryOptions);
81+
var initialCallsCount = _fixture.TestHub.ConfigureScopeCalls.Count;
82+
83+
// Act
84+
_fixture.SceneManager.OnActiveSceneChanged(new SceneAdapter("from scene name"), new SceneAdapter("to scene name"));
85+
86+
// Assert
87+
// Calling 'Register' already generated a trace, so we expect 1+1 calls to ConfigureScope
88+
Assert.AreEqual(initialCallsCount + 1, _fixture.TestHub.ConfigureScopeCalls.Count);
89+
var configureScope = _fixture.TestHub.ConfigureScopeCalls.Last();
90+
var scope = new Scope(_fixture.SentryOptions);
91+
var initialPropagationContext = scope.PropagationContext;
92+
configureScope(scope);
93+
94+
Assert.AreNotEqual(initialPropagationContext, scope.PropagationContext);
95+
}
96+
97+
internal class TestSentryMonoBehaviour : ISentryMonoBehaviour
98+
{
99+
public event Action? ApplicationResuming;
100+
101+
public void ResumeApplication() => ApplicationResuming?.Invoke();
102+
}
103+
}

0 commit comments

Comments
 (0)