osu/osu.Game/Utils/SentryLogger.cs

103 lines
3.1 KiB
C#
Raw Normal View History

// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
2018-08-03 10:25:55 +00:00
using System;
2018-10-31 07:43:35 +00:00
using System.IO;
using System.Net;
2018-08-03 10:25:55 +00:00
using osu.Framework.Logging;
2019-11-12 13:12:38 +00:00
using Sentry;
2018-08-03 10:25:55 +00:00
namespace osu.Game.Utils
{
/// <summary>
/// Report errors to sentry.
/// </summary>
2019-11-12 13:12:38 +00:00
public class SentryLogger : IDisposable
2018-08-03 10:25:55 +00:00
{
2019-11-12 14:16:48 +00:00
private SentryClient sentry;
private Scope sentryScope;
private Exception lastException;
2018-08-03 10:25:55 +00:00
2019-11-12 13:12:38 +00:00
public SentryLogger(OsuGame game)
2018-08-03 10:25:55 +00:00
{
2018-08-17 03:27:36 +00:00
if (!game.IsDeployedBuild) return;
2019-11-12 14:16:48 +00:00
var options = new SentryOptions
2019-11-12 13:12:38 +00:00
{
2021-02-02 04:34:34 +00:00
Dsn = "https://5e342cd55f294edebdc9ad604d28bbd3@sentry.io/1255255",
2019-11-12 13:12:38 +00:00
Release = game.Version
2019-11-12 14:16:48 +00:00
};
2019-11-21 13:55:31 +00:00
2019-11-12 14:16:48 +00:00
sentry = new SentryClient(options);
sentryScope = new Scope(options);
Logger.NewEntry += processLogEntry;
}
2019-03-08 03:00:12 +00:00
private void processLogEntry(LogEntry entry)
{
if (entry.Level < LogLevel.Verbose) return;
2018-08-03 10:25:55 +00:00
var exception = entry.Exception;
if (exception != null)
{
if (!shouldSubmitException(exception)) return;
// since we let unhandled exceptions go ignored at times, we want to ensure they don't get submitted on subsequent reports.
if (lastException != null && lastException.Message == exception.Message && exception.StackTrace.StartsWith(lastException.StackTrace, StringComparison.Ordinal)) return;
lastException = exception;
sentry.CaptureEvent(new SentryEvent(exception) { Message = entry.Message }, sentryScope);
}
else
sentryScope.AddBreadcrumb(DateTimeOffset.Now, entry.Message, entry.Target.ToString(), "navigation");
2018-08-03 10:25:55 +00:00
}
2019-07-30 08:52:06 +00:00
private bool shouldSubmitException(Exception exception)
{
switch (exception)
{
case IOException ioe:
// disk full exceptions, see https://stackoverflow.com/a/9294382
const int hr_error_handle_disk_full = unchecked((int)0x80070027);
const int hr_error_disk_full = unchecked((int)0x80070070);
if (ioe.HResult == hr_error_handle_disk_full || ioe.HResult == hr_error_disk_full)
return false;
break;
case WebException we:
switch (we.Status)
{
// more statuses may need to be blocked as we come across them.
case WebExceptionStatus.Timeout:
return false;
}
break;
}
return true;
}
2018-08-03 10:25:55 +00:00
#region Disposal
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool isDisposing)
{
Logger.NewEntry -= processLogEntry;
2019-11-12 13:39:38 +00:00
sentry = null;
2019-11-12 14:16:48 +00:00
sentryScope = null;
2018-08-03 10:25:55 +00:00
}
#endregion
}
}