diff --git a/CHANGELOG.md b/CHANGELOG.md
index e763e5ad19..c0c82d9d30 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,7 @@
### Features
-- Initial support for .NET MAUI ([#1663](https://github.com/getsentry/sentry-dotnet/pull/1663))
+- Initial support for .NET MAUI ([#1663](https://github.com/getsentry/sentry-dotnet/pull/1663)) ([#1670](https://github.com/getsentry/sentry-dotnet/pull/1670))
- Initial support for `net6.0-android` apps ([#1288](https://github.com/getsentry/sentry-dotnet/pull/1288)) ([#1669](https://github.com/getsentry/sentry-dotnet/pull/1669))
### Fixes
diff --git a/samples/Sentry.Samples.Maui/Sentry.Samples.Maui.csproj b/samples/Sentry.Samples.Maui/Sentry.Samples.Maui.csproj
index 18129fde5c..4ae723a232 100644
--- a/samples/Sentry.Samples.Maui/Sentry.Samples.Maui.csproj
+++ b/samples/Sentry.Samples.Maui/Sentry.Samples.Maui.csproj
@@ -29,6 +29,13 @@
21.0
10.0.17763.0
10.0.17763.0
+
+
+ DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
+
@@ -53,4 +60,11 @@
+
+
+
+
+
+
+
diff --git a/src/Sentry.Maui/Constants.cs b/src/Sentry.Maui/Constants.cs
new file mode 100644
index 0000000000..cc59423a3f
--- /dev/null
+++ b/src/Sentry.Maui/Constants.cs
@@ -0,0 +1,12 @@
+using System.Reflection;
+
+namespace Sentry.Maui;
+
+internal static class Constants
+{
+ // See: https://github.com/getsentry/sentry-release-registry
+ public const string SdkName = "sentry.dotnet.maui";
+
+ public static string SdkVersion = typeof(SentryMauiOptions).Assembly
+ .GetCustomAttribute()!.InformationalVersion;
+}
diff --git a/src/Sentry.Maui/MauiEventProcessor.cs b/src/Sentry.Maui/MauiEventProcessor.cs
new file mode 100644
index 0000000000..1680548be8
--- /dev/null
+++ b/src/Sentry.Maui/MauiEventProcessor.cs
@@ -0,0 +1,15 @@
+using Sentry.Extensibility;
+
+namespace Sentry.Maui;
+
+internal class MauiEventProcessor : ISentryEventProcessor
+{
+ public SentryEvent Process(SentryEvent @event)
+ {
+ // Set SDK name and version for MAUI
+ @event.Sdk.Name = Constants.SdkName;
+ @event.Sdk.Version = Constants.SdkVersion;
+
+ return @event;
+ }
+}
diff --git a/src/Sentry.Maui/SentryMauiInitializer.cs b/src/Sentry.Maui/SentryMauiInitializer.cs
index 3602eb7bf2..615522a664 100644
--- a/src/Sentry.Maui/SentryMauiInitializer.cs
+++ b/src/Sentry.Maui/SentryMauiInitializer.cs
@@ -9,6 +9,12 @@ internal class SentryMauiInitializer : IMauiInitializeService
public void Initialize(IServiceProvider services)
{
var options = services.GetRequiredService>().Value;
+
+#if ANDROID
+ var context = global::Android.App.Application.Context;
+ SentrySdk.Init(context, options);
+#else
SentrySdk.Init(options);
+#endif
}
}
diff --git a/src/Sentry.Maui/SentryMauiOptionsSetup.cs b/src/Sentry.Maui/SentryMauiOptionsSetup.cs
index 4afacf48c1..15bef83319 100644
--- a/src/Sentry.Maui/SentryMauiOptionsSetup.cs
+++ b/src/Sentry.Maui/SentryMauiOptionsSetup.cs
@@ -16,6 +16,10 @@ public override void Configure(SentryMauiOptions options)
// We'll initialize the SDK in SentryMauiInitializer
options.InitializeSdk = false;
- // TODO: Anything MAUI specific for setting up the options. (Can inject dependencies.)
+ // Global Mode makes sense for client apps
+ options.IsGlobalModeEnabled = true;
+
+ // We'll use an event processor to set things like SDK name
+ options.AddEventProcessor(new MauiEventProcessor());
}
}
diff --git a/src/Sentry/Android/SentrySdk.cs b/src/Sentry/Android/SentrySdk.cs
index 3a5b1d9ded..9cc5573095 100644
--- a/src/Sentry/Android/SentrySdk.cs
+++ b/src/Sentry/Android/SentrySdk.cs
@@ -15,6 +15,14 @@ public static IDisposable Init(
Action? configureOptions)
{
var options = new SentryOptions();
+ configureOptions?.Invoke(options);
+ return Init(context, options);
+ }
+
+ public static IDisposable Init(
+ global::Android.Content.Context context,
+ SentryOptions options)
+ {
// TODO: Pause/Resume
options.AutoSessionTracking = true;
options.IsGlobalModeEnabled = true;
@@ -27,8 +35,6 @@ public static IDisposable Init(
return evt;
}));
- configureOptions?.Invoke(options);
-
Sentry.Android.SentryAndroid.Init(context, new JavaLogger(options),
new ConfigureOption(o =>
{
diff --git a/test/Sentry.Maui.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt b/test/Sentry.Maui.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt
new file mode 100644
index 0000000000..27896e0d18
--- /dev/null
+++ b/test/Sentry.Maui.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt
@@ -0,0 +1,12 @@
+[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName="")]
+namespace Microsoft.Maui.Hosting
+{
+ public static class SentryMauiAppBuilderExtensions { }
+}
+namespace Sentry.Maui
+{
+ public class SentryMauiOptions : Sentry.Extensions.Logging.SentryLoggingOptions
+ {
+ public SentryMauiOptions() { }
+ }
+}
\ No newline at end of file
diff --git a/test/Sentry.Maui.Tests/ApiApprovalTests.cs b/test/Sentry.Maui.Tests/ApiApprovalTests.cs
new file mode 100644
index 0000000000..b52a2c408c
--- /dev/null
+++ b/test/Sentry.Maui.Tests/ApiApprovalTests.cs
@@ -0,0 +1,13 @@
+using Sentry.Tests;
+
+namespace Sentry.Maui.Tests;
+
+[UsesVerify]
+public class ApiApprovalTests
+{
+ [Fact]
+ public Task Run()
+ {
+ return typeof(SentryMauiOptions).Assembly.CheckApproval();
+ }
+}
diff --git a/test/Sentry.Maui.Tests/SentryMauiAppBuilderExtensionsTests.cs b/test/Sentry.Maui.Tests/SentryMauiAppBuilderExtensionsTests.cs
index b530063e5c..6015a22d90 100644
--- a/test/Sentry.Maui.Tests/SentryMauiAppBuilderExtensionsTests.cs
+++ b/test/Sentry.Maui.Tests/SentryMauiAppBuilderExtensionsTests.cs
@@ -95,4 +95,50 @@ public void CanUseSentry_WithConfigurationAndOptions()
Assert.Equal(DsnSamples.ValidDsnWithoutSecret, options.Dsn);
Assert.True(options.Debug);
}
+
+ [Fact]
+ public void UseSentry_EnablesGlobalMode()
+ {
+ // Arrange
+ var builder = MauiApp.CreateBuilder();
+
+ // Act
+ _ = builder.UseSentry(DsnSamples.ValidDsnWithoutSecret);
+
+ using var app = builder.Build();
+ var options = app.Services.GetRequiredService>().Value;
+
+ // Assert
+ Assert.True(options.IsGlobalModeEnabled);
+ }
+
+ [Fact]
+ public void UseSentry_SetsMauiSdkNameAndVersion()
+ {
+ // Arrange
+ SentryEvent @event = null;
+ var builder = MauiApp.CreateBuilder()
+ .UseSentry(options =>
+ {
+ options.Dsn = DsnSamples.ValidDsnWithoutSecret;
+ options.BeforeSend = e =>
+ {
+ // capture the event
+ @event = e;
+
+ // but don't actually send it
+ return null;
+ };
+ });
+
+ // Act
+ using var app = builder.Build();
+ var client = app.Services.GetRequiredService();
+ client.CaptureMessage("test");
+
+ // Assert
+ Assert.NotNull(@event);
+ Assert.Equal(Constants.SdkName, @event.Sdk.Name);
+ Assert.Equal(Constants.SdkVersion, @event.Sdk.Version);
+ }
}