Skip to content
Prev Previous commit
Next Next commit
Collect breadcrumbs sent early on startup
  • Loading branch information
jpnurmi committed Nov 5, 2025
commit d3f4476bec135099a94dabbe5408f082bfa184a8
71 changes: 20 additions & 51 deletions integration-test/android.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ Describe 'MAUI app (<tfm>, <configuration>)' -ForEach @(
{
param(
[string] $Dsn,
[string] $TestArg = 'None',
[ScriptBlock] $Callback = $null
[string] $TestArg = 'None'
)
Write-Host "::group::Run Android app (TestArg=$TestArg)"
$dsn = $Dsn.Replace('http://', 'http://key@') + '/0'
Expand All @@ -74,10 +73,7 @@ Describe 'MAUI app (<tfm>, <configuration>)' -ForEach @(

$procid = (& xharness android adb -- shell pidof "io.sentry.dotnet.maui.device.integrationtestapp") -replace '\s', ''
$activity = (& xharness android adb -- shell dumpsys activity activities) -match "io\.sentry\.dotnet\.maui\.device\.integrationtestapp"
if ($procid -and $activity -and $Callback)
{
& $Callback | ForEach-Object { Write-Host $_ }
}

} while ($procid -and $activity)
}

Expand Down Expand Up @@ -182,54 +178,27 @@ Describe 'MAUI app (<tfm>, <configuration>)' -ForEach @(
}
}

It 'Delivers battery breadcrumbs in main thread (<configuration>)' -Skip:($configuration -eq "Release") {
try
{
$result = Invoke-SentryServer {
param([string]$url)
RunAndroidApp -Dsn $url -TestArg "BATTERY_CHANGED" {
# Trigger BATTERY_CHANGED events by incrementing the battery level
$battery = [int](& xharness android adb -- shell dumpsys battery get level)
$battery = ($battery % 100) + 1
xharness android adb -v -- shell dumpsys battery set level $battery | ForEach-Object { Write-Host $_ }
}
}

Dump-ServerErrors -Result $result
$result.HasErrors() | Should -BeFalse
$result.Envelopes() | Should -AnyElementMatch "`"type`":`"system`",`"thread_id`":1,`"category`":`"device.event`",`"action`":`"BATTERY_CHANGED`""
$result.Envelopes() | Should -HaveCount 1
}
finally
{
xharness android adb -v -- shell dumpsys battery reset | ForEach-Object { Write-Host $_ }
It 'Delivers battery breadcrumbs in main thread (<configuration>)' {
$result = Invoke-SentryServer {
param([string]$url)
RunAndroidApp -Dsn $url -TestArg "BATTERY_CHANGED"
}
}

It 'Delivers network breadcrumbs in main thread (<configuration>)' -Skip:($configuration -eq "Release") {
try
{
$result = Invoke-SentryServer {
param([string]$url)
RunAndroidApp -Dsn $url -TestArg "NETWORK_CAPABILITIES_CHANGED" {
# Trigger NETWORK_CAPABILITIES_CHANGED events by toggling WiFi on/off
$wifi = (& xharness android adb -- shell settings get global wifi_on) -replace '\s', ''
if ($wifi -eq '1') {
xharness android adb -v -- shell svc wifi disable | ForEach-Object { Write-Host $_ }
} else {
xharness android adb -v -- shell svc wifi enable | ForEach-Object { Write-Host $_ }
}
}
}
Dump-ServerErrors -Result $result
$result.HasErrors() | Should -BeFalse
$result.Envelopes() | Should -AnyElementMatch "`"type`":`"system`",`"thread_id`":`"1`",`"category`":`"device.event`",`"action`":`"BATTERY_CHANGED`""
$result.Envelopes() | Should -HaveCount 1
}

Dump-ServerErrors -Result $result
$result.HasErrors() | Should -BeFalse
$result.Envelopes() | Should -AnyElementMatch "`"type`":`"system`",`"thread_id`":1,`"category`":`"network.event`",`"action`":`"NETWORK_CAPABILITIES_CHANGED`""
$result.Envelopes() | Should -HaveCount 1
}
finally
{
xharness android adb -v -- shell svc wifi enable | ForEach-Object { Write-Host $_ }
It 'Delivers network breadcrumbs in main thread (<configuration>)' {
$result = Invoke-SentryServer {
param([string]$url)
RunAndroidApp -Dsn $url -TestArg "NETWORK_CAPABILITIES_CHANGED"
}

Dump-ServerErrors -Result $result
$result.HasErrors() | Should -BeFalse
$result.Envelopes() | Should -AnyElementMatch "`"type`":`"system`",`"thread_id`":`"1`",`"category`":`"network.event`",`"action`":`"NETWORK_CAPABILITIES_CHANGED`""
$result.Envelopes() | Should -HaveCount 1
}
}
27 changes: 27 additions & 0 deletions integration-test/net9-maui/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#if ANDROID
using Android.OS;
#endif
using System.Collections.Concurrent;

namespace Sentry.Maui.Device.IntegrationTestApp;

public partial class App : Application
{
private static readonly ConcurrentDictionary<string, Breadcrumb> _breadcrumbs = new();

public App()
{
InitializeComponent();
Expand All @@ -18,6 +21,30 @@ public static bool HasTestArg(string arg)
return string.Equals(TestArg, arg, StringComparison.OrdinalIgnoreCase);
}

public static void RecordBreadcrumb(Breadcrumb breadcrumb)
{
if (breadcrumb.Data?.TryGetValue("action", out var action) != true)
{
return;
}

_breadcrumbs[action] = new Breadcrumb(
breadcrumb.Message,
breadcrumb.Type,
new Dictionary<string, string>
{
["action"] = action,
["thread_id"] = Thread.CurrentThread.ManagedThreadId.ToString()
},
breadcrumb.Category,
breadcrumb.Level);
}

public static bool TryGetBreadcrumb(string action, out Breadcrumb? breadcrumb)
{
return _breadcrumbs.TryGetValue(action, out breadcrumb);
}

protected override Window CreateWindow(IActivationState? activationState)
{
return new Window(new AppShell());
Expand Down
15 changes: 12 additions & 3 deletions integration-test/net9-maui/MainPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,20 @@ protected override void OnAppearing()
{
SentrySdk.CaptureException(ex);
}
App.Kill();
}
else if (App.HasTestArg("None"))
else if (App.TryGetBreadcrumb(App.TestArg, out var breadcrumb) && breadcrumb.Data != null)
{
App.Kill();
SentrySdk.CaptureMessage(App.TestArg, scope =>
{
scope.SetExtra("category", breadcrumb.Category);
foreach (var kvp in breadcrumb.Data)
{
scope.SetExtra(kvp.Key, kvp.Value);
}
scope.SetExtra("type", breadcrumb.Type);
});
}

App.Kill();
}
}
12 changes: 1 addition & 11 deletions integration-test/net9-maui/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,7 @@ public static MauiApp CreateMauiApp()

options.SetBeforeBreadcrumb((breadcrumb, hint) =>
{
if (breadcrumb.Data?.TryGetValue("action", out var action) == true && App.HasTestArg(action))
{
SentrySdk.CaptureMessage(action, scope =>
{
scope.SetExtra("action", action);
scope.SetExtra("category", breadcrumb.Category);
scope.SetExtra("thread_id", Thread.CurrentThread.ManagedThreadId);
scope.SetExtra("type", breadcrumb.Type);
});
App.Kill();
}
App.RecordBreadcrumb(breadcrumb);
return breadcrumb;
});
})
Expand Down