Browse Source

Add Sentry and SafeFireAndForget extension

pull/5/head
Ionite 1 year ago
parent
commit
596021f9f8
No known key found for this signature in database
  1. 69
      StabilityMatrix/App.xaml.cs
  2. 11
      StabilityMatrix/Services/NotificationBarService.cs
  3. 2
      StabilityMatrix/StabilityMatrix.csproj

69
StabilityMatrix/App.xaml.cs

@ -5,6 +5,7 @@ using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Windows;
using AsyncAwaitBestPractices;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@ -15,6 +16,7 @@ using Polly.Contrib.WaitAndRetry;
using Polly.Extensions.Http;
using Polly.Timeout;
using Refit;
using Sentry;
using StabilityMatrix.Api;
using StabilityMatrix.Helper;
using StabilityMatrix.Helper.Cache;
@ -37,7 +39,11 @@ namespace StabilityMatrix
public partial class App : Application
{
private ServiceProvider? serviceProvider;
public static bool IsSentryEnabled => !Debugger.IsAttached || Environment
.GetEnvironmentVariable("DEBUG_SENTRY")?.ToLowerInvariant() == "true";
public static bool IsExceptionWindowEnabled => !Debugger.IsAttached || Environment
.GetEnvironmentVariable("DEBUG_EXCEPTION_WINDOW")?.ToLowerInvariant() == "true";
public static IConfiguration Config { get; set; }
public App()
@ -47,16 +53,36 @@ namespace StabilityMatrix
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
.Build();
// This needs to be done before OnStartup
// Or Sentry will not be initialized correctly
ConfigureErrorHandling();
}
private void App_OnStartup(object sender, StartupEventArgs e)
private void ConfigureErrorHandling()
{
// Configure window exception handler when not in debug mode
if (!Debugger.IsAttached)
if (IsSentryEnabled)
{
SentrySdk.Init(o =>
{
o.Dsn = "https://eac7a5ea065d44cf9a8565e0f1817da2@o4505314753380352.ingest.sentry.io/4505314756067328";
o.StackTraceMode = StackTraceMode.Enhanced;
o.TracesSampleRate = 1.0;
o.IsGlobalModeEnabled = true;
// Enables Sentry's "Release Health" feature.
o.AutoSessionTracking = true;
// 1.0 to capture 100% of transactions for performance monitoring.
o.TracesSampleRate = 1.0;
});
}
if (IsSentryEnabled || IsExceptionWindowEnabled)
{
DispatcherUnhandledException += App_DispatcherUnhandledException;
}
}
private void App_OnStartup(object sender, StartupEventArgs e)
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<IPageService, PageService>();
serviceCollection.AddSingleton<IContentDialogService, ContentDialogService>();
@ -164,6 +190,14 @@ namespace StabilityMatrix
log.SetMinimumLevel(LogLevel.Trace);
log.AddNLog(logConfig);
});
// Default error handling for 'SafeFireAndForget'
SafeFireAndForgetExtensions.Initialize();
SafeFireAndForgetExtensions.SetDefaultExceptionHandling(ex =>
{
var logger = serviceProvider?.GetRequiredService<ILogger<App>>();
logger?.LogError(ex, "Background Task failed: {ExceptionMessage}", ex.Message);
});
serviceProvider = serviceCollection.BuildServiceProvider();
var window = serviceProvider.GetRequiredService<MainWindow>();
@ -178,18 +212,27 @@ namespace StabilityMatrix
[DoesNotReturn]
private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
if (SentrySdk.IsEnabled)
{
SentrySdk.CaptureException(e.Exception);
}
var logger = serviceProvider?.GetRequiredService<ILogger<App>>();
logger?.LogCritical(e.Exception, "Unhandled Exception: {ExceptionMessage}", e.Exception.Message);
var vm = new ExceptionWindowViewModel
{
Exception = e.Exception
};
var exceptionWindow = new ExceptionWindow
if (IsExceptionWindowEnabled)
{
DataContext = vm,
Owner = MainWindow
};
exceptionWindow.ShowDialog();
var vm = new ExceptionWindowViewModel
{
Exception = e.Exception
};
var exceptionWindow = new ExceptionWindow
{
DataContext = vm,
Owner = MainWindow
};
exceptionWindow.ShowDialog();
}
e.Handled = true;
Environment.Exit(1);
}

11
StabilityMatrix/Services/NotificationBarService.cs

@ -1,5 +1,8 @@
using System.Threading.Tasks;
using AsyncAwaitBestPractices;
using Wpf.Ui.Common;
using Wpf.Ui.Contracts;
using Wpf.Ui.Controls;
using Wpf.Ui.Controls.IconElements;
using Wpf.Ui.Services;
namespace StabilityMatrix.Services;
@ -13,5 +16,11 @@ public class NotificationBarService : SnackbarService, INotificationBarService
{
public void ShowStartupNotifications()
{
Timeout = 10000;
var linkIcon = new SymbolIcon(SymbolRegular.Link24);
var snackbar = ShowAsync(
"Welcome to StabilityMatrix!",
"You can join our Discord server for support and feedback.", linkIcon, ControlAppearance.Info);
snackbar.SafeFireAndForget();
}
}

2
StabilityMatrix/StabilityMatrix.csproj

@ -14,6 +14,7 @@
<ItemGroup>
<PackageReference Include="7-Zip.CommandLine" Version="18.1.0" />
<PackageReference Include="AsyncAwaitBestPractices" Version="6.0.6" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.0" />
<PackageReference Include="FuzzySharp" Version="2.0.2" />
<PackageReference Include="MdXaml" Version="1.19.2" />
@ -32,6 +33,7 @@
<PackageReference Include="Polly.Contrib.WaitAndRetry" Version="1.1.1" />
<PackageReference Include="Refit" Version="6.3.2" />
<PackageReference Include="Refit.HttpClientFactory" Version="6.3.2" />
<PackageReference Include="Sentry" Version="3.33.0" />
<PackageReference Include="SharpCompress" Version="0.33.0" />
<PackageReference Include="WPF-UI" Version="3.0.0-preview.2" />
<PackageReference Include="pythonnet" Version="3.0.1" />

Loading…
Cancel
Save