From 053c730799fc36c48a96c606663a7ac11e47f320 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Wed, 4 Jan 2017 00:53:09 -0800 Subject: [PATCH] Added Sentry error reporting --- src/NzbDrone.Common/EnvironmentInfo/OsInfo.cs | 3 + .../Instrumentation/NzbDroneLogger.cs | 32 +++++++ .../Instrumentation/Sentry/SentryTarget.cs | 89 +++++++++++++++++++ src/NzbDrone.Common/NzbDrone.Common.csproj | 5 ++ src/NzbDrone.Common/packages.config | 1 + .../EnvironmentInfo/MonoPlatformInfo.cs | 2 +- .../EnvironmentInfo/DotNetPlatformInfo.cs | 16 ++-- 7 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 src/NzbDrone.Common/Instrumentation/Sentry/SentryTarget.cs diff --git a/src/NzbDrone.Common/EnvironmentInfo/OsInfo.cs b/src/NzbDrone.Common/EnvironmentInfo/OsInfo.cs index cad3d3002..abe4070c6 100644 --- a/src/NzbDrone.Common/EnvironmentInfo/OsInfo.cs +++ b/src/NzbDrone.Common/EnvironmentInfo/OsInfo.cs @@ -82,6 +82,9 @@ namespace NzbDrone.Common.EnvironmentInfo Name = Os.ToString(); FullName = Name; } + + Environment.SetEnvironmentVariable("OS_NAME", Name); + Environment.SetEnvironmentVariable("OS_VERSION", Version); } } diff --git a/src/NzbDrone.Common/Instrumentation/NzbDroneLogger.cs b/src/NzbDrone.Common/Instrumentation/NzbDroneLogger.cs index 19bf34157..55a7071ae 100644 --- a/src/NzbDrone.Common/Instrumentation/NzbDroneLogger.cs +++ b/src/NzbDrone.Common/Instrumentation/NzbDroneLogger.cs @@ -7,6 +7,7 @@ using NLog.Config; using NLog.Targets; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Extensions; +using NzbDrone.Common.Instrumentation.Sentry; namespace NzbDrone.Common.Instrumentation { @@ -38,6 +39,8 @@ namespace NzbDrone.Common.Instrumentation RegisterDebugger(); } + RegisterSentry(updateApp); + if (updateApp) { RegisterUpdateFile(appFolderInfo); @@ -69,6 +72,35 @@ namespace NzbDrone.Common.Instrumentation LogManager.Configuration.LoggingRules.Add(loggingRule); } + private static void RegisterSentry(bool updateClient) + { + string dsn; + + if (updateClient) + { + dsn = RuntimeInfo.IsProduction + ? "https://b85aa82c65b84b0e99e3b7c281438357:392b5bc007974147a922c5d841c47cf9@sentry.sonarr.tv/11" + : "https://6168f0946aba4e60ac23e469ac08eac5:bd59e8454ccc454ea27a90cff1f814ca@sentry.sonarr.tv/9"; + + } + else + { + dsn = RuntimeInfo.IsProduction + ? "https://fed3f47e8bea4527831e96edfa02d495:8ed11e4878614d8e87b1e1b15d890dc9@sentry.sonarr.tv/8" + : "https://4ee3580e01d8407c96a7430fbc953512:5f2d07227a0b4fde99dea07041a3ff93@sentry.sonarr.tv/10"; + } + + var target = new SentryTarget(dsn) + { + Name = "sentryTarget", + Layout = "${message}" + }; + + var loggingRule = new LoggingRule("*", updateClient ? LogLevel.Trace : LogLevel.Error, target); + LogManager.Configuration.AddTarget("logentries", target); + LogManager.Configuration.LoggingRules.Add(loggingRule); + } + private static void RegisterDebugger() { DebuggerTarget target = new DebuggerTarget(); diff --git a/src/NzbDrone.Common/Instrumentation/Sentry/SentryTarget.cs b/src/NzbDrone.Common/Instrumentation/Sentry/SentryTarget.cs new file mode 100644 index 000000000..8d236ddbd --- /dev/null +++ b/src/NzbDrone.Common/Instrumentation/Sentry/SentryTarget.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using NLog; +using NLog.Common; +using NLog.Targets; +using NzbDrone.Common.EnvironmentInfo; +using SharpRaven; +using SharpRaven.Data; + +namespace NzbDrone.Common.Instrumentation.Sentry +{ + + public class SentryUserFactory : ISentryUserFactory + { + public SentryUser Create() + { + return new SentryUser((string)null); + } + } + + [Target("Sentry")] + public class SentryTarget : TargetWithLayout + { + private readonly RavenClient _client; + + /// + /// Map of NLog log levels to Raven/Sentry log levels + /// + private static readonly IDictionary LoggingLevelMap = new Dictionary + { + {LogLevel.Debug, ErrorLevel.Debug}, + {LogLevel.Error, ErrorLevel.Error}, + {LogLevel.Fatal, ErrorLevel.Fatal}, + {LogLevel.Info, ErrorLevel.Info}, + {LogLevel.Trace, ErrorLevel.Debug}, + {LogLevel.Warn, ErrorLevel.Warning}, + }; + + public SentryTarget(string dsn) + { + _client = new RavenClient(new Dsn(dsn), new JsonPacketFactory(), new SentryRequestFactory(), new SentryUserFactory()) + { + Compression = true, + Environment = RuntimeInfo.IsProduction ? "production" : "development", + Release = BuildInfo.Version.ToString(), + }; + + _client.Tags.Add("osfamily", OsInfo.Os.ToString()); + _client.Tags.Add("runtime", PlatformInfo.Platform.ToString().ToLower()); + _client.Tags.Add("culture", Thread.CurrentThread.CurrentCulture.Name); + } + + protected override void Write(LogEventInfo logEvent) + { + try + { + // don't report non-critical events without exceptions + if (logEvent.Exception == null && logEvent.Level < LogLevel.Warn) + { + return; + } + + + var extras = logEvent.Properties.ToDictionary(x => x.Key.ToString(), x => x.Value.ToString()); + _client.Logger = logEvent.LoggerName; + + var sentryMessage = new SentryMessage(Layout.Render(logEvent)); + var sentryEvent = new SentryEvent(logEvent.Exception) + { + Level = LoggingLevelMap[logEvent.Level], + Message = sentryMessage, + Extra = extras, + }; + + sentryEvent.Tags.Add("os_name", Environment.GetEnvironmentVariable("OS_NAME")); + sentryEvent.Tags.Add("os_version", Environment.GetEnvironmentVariable("OS_VERSION")); + sentryEvent.Tags.Add("runtime_version", Environment.GetEnvironmentVariable("RUNTIME_VERSION")); + + _client.Capture(sentryEvent); + } + catch (Exception e) + { + InternalLogger.Error("Unable to send Sentry request: {0}", e.Message); + } + } + } +} diff --git a/src/NzbDrone.Common/NzbDrone.Common.csproj b/src/NzbDrone.Common/NzbDrone.Common.csproj index 766a7c669..c8f98dd84 100644 --- a/src/NzbDrone.Common/NzbDrone.Common.csproj +++ b/src/NzbDrone.Common/NzbDrone.Common.csproj @@ -51,6 +51,10 @@ ..\packages\DotNet4.SocksProxy.1.3.2.0\lib\net40\Org.Mentalis.dll True + + ..\packages\SharpRaven.2.1.0\lib\net40\SharpRaven.dll + True + ..\packages\DotNet4.SocksProxy.1.3.2.0\lib\net40\SocksWebProxy.dll True @@ -178,6 +182,7 @@ + diff --git a/src/NzbDrone.Common/packages.config b/src/NzbDrone.Common/packages.config index 359d382e8..91e117688 100644 --- a/src/NzbDrone.Common/packages.config +++ b/src/NzbDrone.Common/packages.config @@ -4,4 +4,5 @@ + \ No newline at end of file diff --git a/src/NzbDrone.Mono/EnvironmentInfo/MonoPlatformInfo.cs b/src/NzbDrone.Mono/EnvironmentInfo/MonoPlatformInfo.cs index 32079d7cd..8fe776f07 100644 --- a/src/NzbDrone.Mono/EnvironmentInfo/MonoPlatformInfo.cs +++ b/src/NzbDrone.Mono/EnvironmentInfo/MonoPlatformInfo.cs @@ -30,6 +30,7 @@ namespace NzbDrone.Mono.EnvironmentInfo if (versionMatch.Success) { runTimeVersion = new Version(versionMatch.Groups["version"].Value); + Environment.SetEnvironmentVariable("RUNTIME_VERSION", runTimeVersion.ToString()); } } } @@ -39,7 +40,6 @@ namespace NzbDrone.Mono.EnvironmentInfo logger.Error(ex, "Unable to get mono version: " + ex.Message); } - Version = runTimeVersion; } } diff --git a/src/NzbDrone.Windows/EnvironmentInfo/DotNetPlatformInfo.cs b/src/NzbDrone.Windows/EnvironmentInfo/DotNetPlatformInfo.cs index 921e2de10..f5cf9c583 100644 --- a/src/NzbDrone.Windows/EnvironmentInfo/DotNetPlatformInfo.cs +++ b/src/NzbDrone.Windows/EnvironmentInfo/DotNetPlatformInfo.cs @@ -8,7 +8,9 @@ namespace NzbDrone.Windows.EnvironmentInfo { public DotNetPlatformInfo() { - Version = GetFrameworkVersion(); + var version = GetFrameworkVersion(); + Environment.SetEnvironmentVariable("RUNTIME_VERSION", version.ToString()); + Version = version; } public override Version Version { get; } @@ -27,27 +29,27 @@ namespace NzbDrone.Windows.EnvironmentInfo if (releaseKey >= 394802) { - return new Version(4,6,2); + return new Version(4, 6, 2); } if (releaseKey >= 394254) { - return new Version(4,6,1); + return new Version(4, 6, 1); } if (releaseKey >= 393295) { - return new Version(4,6); + return new Version(4, 6); } if (releaseKey >= 379893) { - return new Version(4,5,2); + return new Version(4, 5, 2); } if (releaseKey >= 378675) { - return new Version(4,5,1); + return new Version(4, 5, 1); } if (releaseKey >= 378389) { - return new Version(4,5); + return new Version(4, 5); } return new Version(4, 0);