|
|
|
@ -9,6 +9,7 @@ using NLog;
|
|
|
|
|
using NLog.Common;
|
|
|
|
|
using NLog.Targets;
|
|
|
|
|
using NzbDrone.Common.EnvironmentInfo;
|
|
|
|
|
using NzbDrone.Common.Extensions;
|
|
|
|
|
using Sentry;
|
|
|
|
|
|
|
|
|
|
namespace NzbDrone.Common.Instrumentation.Sentry
|
|
|
|
@ -99,7 +100,7 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
|
|
|
|
public bool FilterEvents { get; set; }
|
|
|
|
|
public bool SentryEnabled { get; set; }
|
|
|
|
|
|
|
|
|
|
public SentryTarget(string dsn)
|
|
|
|
|
public SentryTarget(string dsn, IAppFolderInfo appFolderInfo)
|
|
|
|
|
{
|
|
|
|
|
_sdk = SentrySdk.Init(o =>
|
|
|
|
|
{
|
|
|
|
@ -107,9 +108,33 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
|
|
|
|
o.AttachStacktrace = true;
|
|
|
|
|
o.MaxBreadcrumbs = 200;
|
|
|
|
|
o.Release = $"{BuildInfo.AppName}@{BuildInfo.Release}";
|
|
|
|
|
o.BeforeSend = x => SentryCleanser.CleanseEvent(x);
|
|
|
|
|
o.BeforeBreadcrumb = x => SentryCleanser.CleanseBreadcrumb(x);
|
|
|
|
|
o.SetBeforeSend(x => SentryCleanser.CleanseEvent(x));
|
|
|
|
|
o.SetBeforeBreadcrumb(x => SentryCleanser.CleanseBreadcrumb(x));
|
|
|
|
|
o.Environment = BuildInfo.Branch;
|
|
|
|
|
|
|
|
|
|
// Crash free run statistics (sends a ping for healthy and for crashes sessions)
|
|
|
|
|
o.AutoSessionTracking = true;
|
|
|
|
|
|
|
|
|
|
// Caches files in the event device is offline
|
|
|
|
|
// Sentry creates a 'sentry' sub directory, no need to concat here
|
|
|
|
|
o.CacheDirectoryPath = appFolderInfo.GetAppDataPath();
|
|
|
|
|
|
|
|
|
|
// default environment is production
|
|
|
|
|
if (!RuntimeInfo.IsProduction)
|
|
|
|
|
{
|
|
|
|
|
if (RuntimeInfo.IsDevelopment)
|
|
|
|
|
{
|
|
|
|
|
o.Environment = "development";
|
|
|
|
|
}
|
|
|
|
|
else if (RuntimeInfo.IsTesting)
|
|
|
|
|
{
|
|
|
|
|
o.Environment = "testing";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
o.Environment = "other";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
InitializeScope();
|
|
|
|
@ -127,7 +152,7 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
|
|
|
|
{
|
|
|
|
|
SentrySdk.ConfigureScope(scope =>
|
|
|
|
|
{
|
|
|
|
|
scope.User = new User
|
|
|
|
|
scope.User = new SentryUser
|
|
|
|
|
{
|
|
|
|
|
Id = HashUtil.AnonymousToken()
|
|
|
|
|
};
|
|
|
|
@ -169,9 +194,7 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
|
|
|
|
|
|
|
|
|
private void OnError(Exception ex)
|
|
|
|
|
{
|
|
|
|
|
var webException = ex as WebException;
|
|
|
|
|
|
|
|
|
|
if (webException != null)
|
|
|
|
|
if (ex is WebException webException)
|
|
|
|
|
{
|
|
|
|
|
var response = webException.Response as HttpWebResponse;
|
|
|
|
|
var statusCode = response?.StatusCode;
|
|
|
|
@ -290,13 +313,21 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var level = LoggingLevelMap[logEvent.Level];
|
|
|
|
|
var sentryEvent = new SentryEvent(logEvent.Exception)
|
|
|
|
|
{
|
|
|
|
|
Level = LoggingLevelMap[logEvent.Level],
|
|
|
|
|
Level = level,
|
|
|
|
|
Logger = logEvent.LoggerName,
|
|
|
|
|
Message = logEvent.FormattedMessage
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (level is SentryLevel.Fatal && logEvent.Exception is not null)
|
|
|
|
|
{
|
|
|
|
|
// Usages of 'fatal' here indicates the process will crash. In Sentry this is represented with
|
|
|
|
|
// the 'unhandled' exception flag
|
|
|
|
|
logEvent.Exception.SetSentryMechanism("Logger.Fatal", "Logger.Fatal was called", false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sentryEvent.SetExtras(extras);
|
|
|
|
|
sentryEvent.SetFingerprint(fingerPrint);
|
|
|
|
|
|
|
|
|
|