using Avalonia.Threading; using MeWeb.Shared; namespace MeWeb.App.Services; public static class ErrorLog { const long MaxBytes = 256 * 1024; static string FilePath => Path.Combine(AppServices.Folder, "errors.log"); static readonly Lock Gate = new(); public static void Watch() { Dispatcher.UIThread.UnhandledException += OnDispatcher; TaskScheduler.UnobservedTaskException += OnUnobserved; AppDomain.CurrentDomain.UnhandledException += OnDomain; } public static void Write(Exception error) { if (error is null) return; lock (Gate) { try { Directory.CreateDirectory(Path.GetDirectoryName(FilePath)); if (File.Exists(FilePath) && new FileInfo(FilePath).Length > MaxBytes) File.Delete(FilePath); File.AppendAllText(FilePath, $"{DateTimeOffset.UtcNow:O} me-web? {BuildInfo.Version}{Environment.NewLine}{error}{Environment.NewLine}{Environment.NewLine}"); } catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) { } } } static void OnDispatcher(object sender, DispatcherUnhandledExceptionEventArgs e) { Write(e.Exception); e.Handled = true; } static void OnUnobserved(object sender, UnobservedTaskExceptionEventArgs e) { Write(e.Exception); e.SetObserved(); } static void OnDomain(object sender, UnhandledExceptionEventArgs e) => Write(e.ExceptionObject as Exception); }