From 2ea90ef98abebc68d80724b9a1964d30cc4df2cd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 3 Aug 2018 19:25:55 +0900 Subject: [PATCH] Add sentry logging --- osu.Desktop/Program.cs | 22 +++++++ osu.Game/OsuGame.cs | 16 +++++ osu.Game/Screens/Select/PlaySongSelect.cs | 3 + osu.Game/Utils/RavenLogger.cs | 73 +++++++++++++++++++++++ osu.Game/osu.Game.csproj | 3 +- 5 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Utils/RavenLogger.cs diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index cc08e08653..4574fb6fc9 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -4,7 +4,10 @@ using System; using System.IO; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using osu.Framework; +using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.IPC; @@ -20,6 +23,8 @@ public static int Main(string[] args) using (DesktopGameHost host = Host.GetSuitableHost(@"osu", true)) { + host.ExceptionThrown += handleException; + if (!host.IsPrimaryInstance) { var importer = new ArchiveImportIPCChannel(host); @@ -45,5 +50,22 @@ public static int Main(string[] args) return 0; } } + + private static int allowableExceptions = 1; + + /// + /// Allow a maximum of one unhandled exception, per second of execution. + /// + /// + /// + private static bool handleException(Exception arg) + { + bool continueExecution = Interlocked.Decrement(ref allowableExceptions) >= 0; + + Logger.Log($"Unhandled exception has been {(continueExecution ? "allowed" : "denied")} with {allowableExceptions} more allowable exceptions."); + + Task.Delay(1000).ContinueWith(_ => Interlocked.Increment(ref allowableExceptions)); + return Interlocked.Decrement(ref allowableExceptions) >= 0; + } } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 025d5f50e3..3e6317348c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -36,6 +36,8 @@ using OpenTK.Graphics; using osu.Game.Overlays.Volume; using osu.Game.Screens.Select; +using osu.Game.Utils; +using LogLevel = osu.Framework.Logging.LogLevel; namespace osu.Game { @@ -65,6 +67,8 @@ public class OsuGame : OsuGameBase, IKeyBindingHandler private ScreenshotManager screenshotManager; + protected RavenLogger RavenLogger; + public virtual Storage GetStorageForStableInstall() => null; private Intro intro @@ -106,6 +110,8 @@ public OsuGame(string[] args = null) this.args = args; forwardLoggedErrorsToNotifications(); + + RavenLogger = new RavenLogger(this); } public void ToggleSettings() => settings.ToggleVisibility(); @@ -150,6 +156,8 @@ private void load(FrameworkConfigManager frameworkConfig) dependencies.CacheAs(this); + dependencies.Cache(RavenLogger); + dependencies.CacheAs(ruleset); dependencies.CacheAs>(ruleset); @@ -271,6 +279,12 @@ protected void LoadScore(Score s) menu.Push(new PlayerLoader(new ReplayPlayer(s.Replay))); } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + RavenLogger.Dispose(); + } + protected override void LoadComplete() { // this needs to be cached before base.LoadComplete as it is used by MenuCursorContainer. @@ -599,6 +613,7 @@ protected override void UpdateAfterChildren() private void screenAdded(Screen newScreen) { currentScreen = (OsuScreen)newScreen; + Logger.Log($"Screen changed → {currentScreen}"); newScreen.ModePushed += screenAdded; newScreen.Exited += screenRemoved; @@ -607,6 +622,7 @@ private void screenAdded(Screen newScreen) private void screenRemoved(Screen newScreen) { currentScreen = (OsuScreen)newScreen; + Logger.Log($"Screen changed ← {currentScreen}"); if (newScreen == null) Exit(); diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index a346911ca2..a73254627d 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -141,6 +142,8 @@ protected override bool OnStart() { if (player != null) return false; + throw new Exception("this is a test!"); + // Ctrl+Enter should start map with autoplay enabled. if (GetContainingInputManager().CurrentState?.Keyboard.ControlPressed == true) { diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/RavenLogger.cs new file mode 100644 index 0000000000..aadb70add8 --- /dev/null +++ b/osu.Game/Utils/RavenLogger.cs @@ -0,0 +1,73 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using osu.Framework.Logging; +using SharpRaven; +using SharpRaven.Data; + +namespace osu.Game.Utils +{ + /// + /// Report errors to sentry. + /// + public class RavenLogger : IDisposable + { + private readonly RavenClient raven = new RavenClient("https://5e342cd55f294edebdc9ad604d28bbd3@sentry.io/1255255"); + + private readonly List tasks = new List(); + + public RavenLogger(OsuGame game) + { + raven.Release = game.Version; + + Logger.NewEntry += entry => + { + if (entry.Level < LogLevel.Verbose) return; + + if (entry.Exception != null) + queuePendingTask(raven.CaptureAsync(new SentryEvent(entry.Exception))); + else + raven.AddTrail(new Breadcrumb(entry.Target.ToString(), BreadcrumbType.Navigation) { Message = entry.Message }); + }; + } + + private void queuePendingTask(Task task) + { + lock (tasks) tasks.Add(task); + task.ContinueWith(_ => + { + lock (tasks) + tasks.Remove(task); + }); + } + + #region Disposal + + ~RavenLogger() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private bool isDisposed; + + protected virtual void Dispose(bool isDisposing) + { + if (isDisposed) + return; + + isDisposed = true; + lock (tasks) Task.WaitAll(tasks.ToArray(), 5000); + } + + #endregion + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 89e80bd06b..9a7edb6ae2 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,9 +18,10 @@ - + + \ No newline at end of file