Skip to content

Commit 17cf494

Browse files
authored
feat: Add breadcrumb for lowMemory events (#2406)
1 parent 1ab0a59 commit 17cf494

File tree

6 files changed

+121
-1
lines changed

6 files changed

+121
-1
lines changed

CHANGELOG.md

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

55
### Features
66

7+
- The SDK automatically subscribes to and leaves breadcrumbs for `Application.lowMemory` events ([#2406](https://github.com/getsentry/sentry-unity/pull/2406))
78
- The SDK now also reports the currently allocated memory when reporting an event or transaction. ([#2398](https://github.com/getsentry/sentry-unity/pull/2398))
89
- The SDK defaults `EnvironmentUser` to sensible values based on the current platform. This is still guarded by the `SendDefaultPII` flag. ([#2402](https://github.com/getsentry/sentry-unity/pull/2402))
910

src/Sentry.Unity/Integrations/IApplication.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace Sentry.Unity.Integrations;
77
internal interface IApplication
88
{
99
event Application.LogCallback LogMessageReceived;
10+
event Action LowMemory;
1011
event Action Quitting;
1112
string ActiveSceneName { get; }
1213
bool IsEditor { get; }
@@ -28,10 +29,12 @@ public sealed class ApplicationAdapter : IApplication
2829
private ApplicationAdapter()
2930
{
3031
Application.logMessageReceivedThreaded += OnLogMessageReceived;
32+
Application.lowMemory += OnLowMemory;
3133
Application.quitting += OnQuitting;
3234
}
3335

3436
public event Application.LogCallback? LogMessageReceived;
37+
public event Action? LowMemory;
3538

3639
public event Action? Quitting;
3740

@@ -54,6 +57,9 @@ private ApplicationAdapter()
5457
private void OnLogMessageReceived(string condition, string stackTrace, LogType type)
5558
=> LogMessageReceived?.Invoke(condition, stackTrace, type);
5659

60+
private void OnLowMemory()
61+
=> LowMemory?.Invoke();
62+
5763
private void OnQuitting()
5864
=> Quitting?.Invoke();
5965
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System.Collections.Generic;
2+
using Sentry.Integrations;
3+
4+
namespace Sentry.Unity.Integrations;
5+
6+
internal class LowMemoryIntegration : ISdkIntegration
7+
{
8+
private static readonly Dictionary<string, string> lowMemoryData = new() { { "action", "LOW_MEMORY" } };
9+
10+
private IHub _hub = null!;
11+
private IApplication _application;
12+
13+
public LowMemoryIntegration(IApplication? application = null)
14+
{
15+
_application = application ?? ApplicationAdapter.Instance;
16+
}
17+
18+
public void Register(IHub hub, SentryOptions options)
19+
{
20+
_hub = hub;
21+
22+
_application.LowMemory += () =>
23+
{
24+
if (!_hub.IsEnabled)
25+
{
26+
return;
27+
}
28+
29+
hub.AddBreadcrumb(new Breadcrumb(
30+
message: "Low memory",
31+
type: "system",
32+
data: lowMemoryData,
33+
category: "device.event",
34+
level: BreadcrumbLevel.Warning));
35+
};
36+
}
37+
}

src/Sentry.Unity/SentryUnityOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ internal SentryUnityOptions(IApplication? application = null,
365365
AddIntegration(new SceneManagerTracingIntegration());
366366
AddIntegration(new LifeCycleIntegration(behaviour));
367367
AddIntegration(new TraceGenerationIntegration(behaviour));
368+
AddIntegration(new LowMemoryIntegration());
368369

369370
AddExceptionFilter(new UnityBadGatewayExceptionFilter());
370371
AddExceptionFilter(new UnityWebExceptionFilter());
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using System.Linq;
2+
using NUnit.Framework;
3+
using Sentry.Unity.Integrations;
4+
using Sentry.Unity.Tests.Stubs;
5+
6+
namespace Sentry.Unity.Tests;
7+
8+
public class LowMemoryIntegrationTests
9+
{
10+
private class Fixture
11+
{
12+
public TestApplication Application { get; set; } = new();
13+
public TestHub Hub { get; set; } = new();
14+
public SentryUnityOptions Options { get; set; } = new();
15+
16+
public LowMemoryIntegration GetSut() => new(Application);
17+
}
18+
19+
private Fixture _fixture = null!;
20+
21+
[SetUp]
22+
public void SetUp()
23+
{
24+
_fixture = new Fixture();
25+
}
26+
27+
[Test]
28+
public void LowMemory_DisabledHub_NoBreadcrumbAdded()
29+
{
30+
_fixture.Hub = new TestHub(false);
31+
var sut = _fixture.GetSut();
32+
33+
sut.Register(_fixture.Hub, _fixture.Options);
34+
_fixture.Application.OnLowMemory();
35+
36+
Assert.Zero(_fixture.Hub.ConfigureScopeCalls.Count);
37+
}
38+
39+
[Test]
40+
public void LowMemory_EnabledHub_BreadcrumbAdded()
41+
{
42+
var sut = _fixture.GetSut();
43+
44+
sut.Register(_fixture.Hub, _fixture.Options);
45+
_fixture.Application.OnLowMemory();
46+
47+
var configureScope = _fixture.Hub.ConfigureScopeCalls.Single();
48+
var scope = new Scope(_fixture.Options);
49+
configureScope(scope);
50+
var actualCrumb = scope.Breadcrumbs.Single();
51+
52+
Assert.AreEqual("Low memory", actualCrumb.Message);
53+
Assert.AreEqual("device.event", actualCrumb.Category);
54+
Assert.AreEqual("system", actualCrumb.Type);
55+
Assert.AreEqual(BreadcrumbLevel.Warning, actualCrumb.Level);
56+
Assert.NotNull(actualCrumb.Data);
57+
Assert.AreEqual("LOW_MEMORY", actualCrumb.Data?["action"]);
58+
}
59+
60+
[Test]
61+
public void LowMemory_MultipleTriggers_MultipleBreadcrumbsAdded()
62+
{
63+
var sut = _fixture.GetSut();
64+
65+
sut.Register(_fixture.Hub, _fixture.Options);
66+
_fixture.Application.OnLowMemory();
67+
_fixture.Application.OnLowMemory();
68+
_fixture.Application.OnLowMemory();
69+
70+
Assert.AreEqual(3, _fixture.Hub.ConfigureScopeCalls.Count);
71+
}
72+
}

test/SharedClasses/TestApplication.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public TestApplication(
2525
}
2626

2727
public event Application.LogCallback? LogMessageReceived;
28+
public event Action? LowMemory;
2829
public event Action? Quitting;
2930
public string ActiveSceneName => "TestSceneName";
3031
public bool IsEditor { get; set; }
@@ -34,8 +35,10 @@ public TestApplication(
3435
public string UnityVersion { get; set; }
3536
public string PersistentDataPath { get; set; }
3637
public RuntimePlatform Platform { get; set; }
37-
private void OnQuitting() => Quitting?.Invoke();
3838

3939
private void OnLogMessageReceived(string condition, string stacktrace, LogType type)
4040
=> LogMessageReceived?.Invoke(condition, stacktrace, type);
41+
42+
public void OnLowMemory() => LowMemory?.Invoke();
43+
private void OnQuitting() => Quitting?.Invoke();
4144
}

0 commit comments

Comments
 (0)