.NET Maui and breadcrumbs in background task #2086
-
Hello, Part of our .NET Maui application is work done in the background, with no direct connection to the UI. I'm unable to report anything to sentry.io without the default breadcrumbs. Is there a way to achieve this? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
This comment has been hidden.
This comment has been hidden.
-
Some background first: In MAUI applications, we force the Global mode is specifically designed for the effect that you are describing - all breadcrumbs from anywhere in the application are presented on each and every event - even if they've been sent on prior events or are from a part of the application other than the one where the event occurred. This is by design. Now getting to your use case - you have a background task that is completely disconnected from the UI and you don't want breadcrumbs and other details from the UI to be reported on events from the background task. One might think at first that this would be handled by disabling global mode. However that applies to the entire application and thus you would lose all benefits I previously described. Also I don't currently allow it disabled for MAUI (you can set it false, but internally we flip it back to true before it takes any effect). Really what you need instead is a way to keep global mode enabled, but to create a separate and independent detached scope for your background thread. This is currently possible because the Here's how you would put this together in a MAUI app: First, you'll need some class to act as the worker that is going to operate the background task. using Microsoft.Extensions.Options;
using Sentry.Maui;
namespace Sentry.Samples.Maui;
public class MyWorker
{
private readonly SentryMauiOptions _options;
public MyWorker(IOptions<SentryMauiOptions> options)
{
_options = options.Value;
}
public async Task DoWorkAsync()
{
// Here a completely new scope is created - detached from any current scope.
// No information is copied over from the current scope. It is starting clean.
var scope = new Scope(_options);
try
{
// You'll need to add breadcrumbs and other items directly on that scope
scope.AddBreadcrumb("Doing a thing");
await Task.Delay(100);
scope.AddBreadcrumb("Doing another thing");
await Task.Delay(100);
throw new Exception("Something went wrong!");
}
catch (Exception ex)
{
// When you capture events, pass the scope in as a parameter.
SentrySdk.CaptureEvent(new SentryEvent(ex), scope);
}
}
} You can see that I've injected builder.Services.AddSingleton<MyWorker>();
builder.Services.AddTransient<MainPage>(); Inject into your page (or wherever it will be used) and use like so: private readonly MyWorker _worker;
public MainPage(MyWorker worker)
{
_worker = worker;
InitializeComponent();
}
private void OnButtonClicked(object sender, EventArgs e)
{
// Run it as background task
Task.Run(() => _worker.DoWorkAsync());
} Keep in mind that any context, tags, user info, or other details from the main scope won't be on the new one unless you copy them over manually yourself. We'll consider making this scenario better supported in a future release - but this should be sufficient for now. |
Beta Was this translation helpful? Give feedback.
Some background first:
In MAUI applications, we force the
IsGlobalMode
option totrue
(you can't change it). This has the effect of there being only one global scope for the entire application. This is what we recommend for client-based applications in general (both mobile and desktop, and not just MAUI), because there are many situations where one thread needs to include breadcrumbs, tags, and other information set from another thread. For example, a UI thread might click a button that uses a background thread to call an API that authenticates the user. The resulting user id would be set in context on the scope, and available both to the background thread and to the original UI thread an…