diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 64e77384a2..026a83cceb 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -2,8 +2,10 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Diagnostics; using System.Globalization; +using System.Linq; using osu.Framework.Configuration; using osu.Framework.Configuration.Tracking; using osu.Framework.Extensions; @@ -164,6 +166,20 @@ namespace osu.Game.Configuration SetDefault(OsuSetting.EditorHitAnimations, false); } + public IDictionary GetLoggableState() => + new Dictionary(ConfigStore.Where(kvp => !keyContainsPrivateInformation(kvp.Key)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToString())); + + private static bool keyContainsPrivateInformation(OsuSetting argKey) + { + switch (argKey) + { + case OsuSetting.Token: + return true; + } + + return false; + } + public OsuConfigManager(Storage storage) : base(storage) { diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b8abef38a8..3d56d33689 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -14,6 +14,7 @@ using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Configuration; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -56,6 +57,8 @@ using osu.Game.Updater; using osu.Game.Users; using osu.Game.Utils; using osuTK.Graphics; +using Sentry; +using Logger = osu.Framework.Logging.Logger; namespace osu.Game { @@ -1197,6 +1200,15 @@ namespace osu.Game private void screenChanged(IScreen current, IScreen newScreen) { + SentrySdk.ConfigureScope(scope => + { + scope.Contexts[@"screen stack"] = new + { + Current = newScreen?.GetType().ReadableName(), + Previous = current?.GetType().ReadableName(), + }; + }); + switch (newScreen) { case IntroScreen intro: diff --git a/osu.Game/Utils/SentryLogger.cs b/osu.Game/Utils/SentryLogger.cs index 16f1a8b039..3edb27ca9b 100644 --- a/osu.Game/Utils/SentryLogger.cs +++ b/osu.Game/Utils/SentryLogger.cs @@ -6,10 +6,19 @@ using System; using System.Diagnostics; using System.IO; +using System.Linq; using System.Net; +using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Logging; +using osu.Framework.Statistics; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Database; +using osu.Game.Models; using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; +using osu.Game.Skinning; using Sentry; using Sentry.Protocol; @@ -24,8 +33,11 @@ namespace osu.Game.Utils private readonly IDisposable? sentrySession; + private readonly OsuGame game; + public SentryLogger(OsuGame game) { + this.game = game; sentrySession = SentrySdk.Init(options => { // Not setting the dsn will completely disable sentry. @@ -94,6 +106,45 @@ namespace osu.Game.Utils { Message = entry.Message, Level = getSentryLevel(entry.Level), + }, scope => + { + var beatmap = game.Dependencies.Get>().Value.BeatmapInfo; + + scope.Contexts[@"config"] = new + { + Game = game.Dependencies.Get().GetLoggableState() + // TODO: add framework config here. needs some consideration on how to expose. + }; + + game.Dependencies.Get().Run(realm => + { + scope.Contexts[@"realm"] = new + { + Counts = new + { + BeatmapSets = realm.All().Count(), + Beatmaps = realm.All().Count(), + Files = realm.All().Count(), + Skins = realm.All().Count(), + } + }; + }); + + scope.Contexts[@"global statistics"] = GlobalStatistics.GetStatistics() + .GroupBy(s => s.Group) + .ToDictionary(g => g.Key, items => items.ToDictionary(i => i.Name, g => g.DisplayValue)); + + scope.Contexts[@"beatmap"] = new + { + Name = beatmap.ToString(), + beatmap.OnlineID, + }; + + scope.Contexts[@"clocks"] = new + { + Audio = game.Dependencies.Get().CurrentTrack.CurrentTime, + Game = game.Clock.CurrentTime, + }; }); } else