From 783878be1e501f24c60d02d2e1d142060f113151 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Sun, 14 May 2023 19:09:19 +0300 Subject: [PATCH] Minor improvements in health checks (cherry picked from commit a22f598b0c129110f2a3b663e9b40c84f3a1f02b) Closes #8615 --- .../Checks/DownloadClientRootFolderCheck.cs | 8 +-- .../Checks/IndexerJackettAllCheck.cs | 14 +++-- .../Checks/IndexerLongTermStatusCheck.cs | 13 ++-- .../HealthCheck/Checks/IndexerStatusCheck.cs | 13 ++-- .../HealthCheck/Checks/MountCheck.cs | 8 +-- .../HealthCheck/Checks/PTPOldSettingsCheck.cs | 6 +- .../HealthCheck/Checks/ProxyCheck.cs | 47 ++++++++------- .../Checks/RemotePathMappingCheck.cs | 60 ++++++++----------- .../HealthCheck/Checks/RootFolderCheck.cs | 6 +- .../HealthCheck/Checks/SlackUrlCheck.cs | 7 ++- .../HealthCheck/Checks/SystemTimeCheck.cs | 4 +- 11 files changed, 91 insertions(+), 95 deletions(-) diff --git a/src/NzbDrone.Core/HealthCheck/Checks/DownloadClientRootFolderCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/DownloadClientRootFolderCheck.cs index 5b9212bdc..d001c03bf 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/DownloadClientRootFolderCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/DownloadClientRootFolderCheck.cs @@ -48,13 +48,11 @@ public override HealthCheck Check() try { var status = client.GetStatus(); - var folders = status.OutputRootFolders; + var folders = status.OutputRootFolders.Where(folder => rootFolders.Any(r => r.Path.PathEquals(folder.FullPath))); + foreach (var folder in folders) { - if (rootFolders.Any(r => r.Path.PathEquals(folder.FullPath))) - { - return new HealthCheck(GetType(), HealthCheckResult.Warning, string.Format(_localizationService.GetLocalizedString("DownloadClientCheckDownloadingToRoot"), client.Definition.Name, folder.FullPath), "#downloads-in-root-folder"); - } + return new HealthCheck(GetType(), HealthCheckResult.Warning, string.Format(_localizationService.GetLocalizedString("DownloadClientCheckDownloadingToRoot"), client.Definition.Name, folder.FullPath), "#downloads-in-root-folder"); } } catch (DownloadClientException ex) diff --git a/src/NzbDrone.Core/HealthCheck/Checks/IndexerJackettAllCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/IndexerJackettAllCheck.cs index e73c066ac..35340a15a 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/IndexerJackettAllCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/IndexerJackettAllCheck.cs @@ -23,12 +23,14 @@ public IndexerJackettAllCheck(IIndexerFactory providerFactory, ILocalizationServ public override HealthCheck Check() { - var jackettAllProviders = _providerFactory.All().Where( - i => i.ConfigContract.Equals("TorznabSettings") && - ((i.Settings as TorznabSettings).BaseUrl.Contains("/torznab/all/api", StringComparison.InvariantCultureIgnoreCase) || - (i.Settings as TorznabSettings).BaseUrl.Contains("/api/v2.0/indexers/all/results/torznab", StringComparison.InvariantCultureIgnoreCase) || - (i.Settings as TorznabSettings).ApiPath.Contains("/torznab/all/api", StringComparison.InvariantCultureIgnoreCase) || - (i.Settings as TorznabSettings).ApiPath.Contains("/api/v2.0/indexers/all/results/torznab", StringComparison.InvariantCultureIgnoreCase))); + var jackettAllProviders = _providerFactory.All() + .Where( + i => i.ConfigContract.Equals("TorznabSettings") && + (((TorznabSettings)i.Settings).BaseUrl.Contains("/torznab/all/api", StringComparison.InvariantCultureIgnoreCase) || + ((TorznabSettings)i.Settings).BaseUrl.Contains("/api/v2.0/indexers/all/results/torznab", StringComparison.InvariantCultureIgnoreCase) || + ((TorznabSettings)i.Settings).ApiPath.Contains("/torznab/all/api", StringComparison.InvariantCultureIgnoreCase) || + ((TorznabSettings)i.Settings).ApiPath.Contains("/api/v2.0/indexers/all/results/torznab", StringComparison.InvariantCultureIgnoreCase))) + .ToArray(); if (jackettAllProviders.Empty()) { diff --git a/src/NzbDrone.Core/HealthCheck/Checks/IndexerLongTermStatusCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/IndexerLongTermStatusCheck.cs index 9ba7ffd1c..e647f774f 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/IndexerLongTermStatusCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/IndexerLongTermStatusCheck.cs @@ -28,13 +28,12 @@ public override HealthCheck Check() { var enabledProviders = _providerFactory.GetAvailableProviders(); var backOffProviders = enabledProviders.Join(_providerStatusService.GetBlockedProviders(), - i => i.Definition.Id, - s => s.ProviderId, - (i, s) => new { Provider = i, Status = s }) - .Where(p => p.Status.InitialFailure.HasValue && - p.Status.InitialFailure.Value.Before( - DateTime.UtcNow.AddHours(-6))) - .ToList(); + i => i.Definition.Id, + s => s.ProviderId, + (i, s) => new { Provider = i, Status = s }) + .Where(p => p.Status.InitialFailure.HasValue && + p.Status.InitialFailure.Value.Before(DateTime.UtcNow.AddHours(-6))) + .ToList(); if (backOffProviders.Empty()) { diff --git a/src/NzbDrone.Core/HealthCheck/Checks/IndexerStatusCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/IndexerStatusCheck.cs index f7d6ee541..53049985f 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/IndexerStatusCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/IndexerStatusCheck.cs @@ -26,13 +26,12 @@ public override HealthCheck Check() { var enabledProviders = _providerFactory.GetAvailableProviders(); var backOffProviders = enabledProviders.Join(_providerStatusService.GetBlockedProviders(), - i => i.Definition.Id, - s => s.ProviderId, - (i, s) => new { Provider = i, Status = s }) - .Where(p => p.Status.InitialFailure.HasValue && - p.Status.InitialFailure.Value.After( - DateTime.UtcNow.AddHours(-6))) - .ToList(); + i => i.Definition.Id, + s => s.ProviderId, + (i, s) => new { Provider = i, Status = s }) + .Where(p => p.Status.InitialFailure.HasValue && + p.Status.InitialFailure.Value.After(DateTime.UtcNow.AddHours(-6))) + .ToList(); if (backOffProviders.Empty()) { diff --git a/src/NzbDrone.Core/HealthCheck/Checks/MountCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/MountCheck.cs index 3b41b929b..3c3a10c06 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/MountCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/MountCheck.cs @@ -21,10 +21,10 @@ public override HealthCheck Check() { // Not best for optimization but due to possible symlinks and junctions, we get mounts based on series path so internals can handle mount resolution. var mounts = _movieService.AllMoviePaths() - .Select(p => _diskProvider.GetMount(p.Value)) - .Where(m => m != null && m.MountOptions != null && m.MountOptions.IsReadOnly) - .DistinctBy(m => m.RootDirectory) - .ToList(); + .Select(p => _diskProvider.GetMount(p.Value)) + .Where(m => m is { MountOptions.IsReadOnly: true }) + .DistinctBy(m => m.RootDirectory) + .ToList(); if (mounts.Any()) { diff --git a/src/NzbDrone.Core/HealthCheck/Checks/PTPOldSettingsCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/PTPOldSettingsCheck.cs index b0349cf9a..c1b121a9f 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/PTPOldSettingsCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/PTPOldSettingsCheck.cs @@ -18,10 +18,12 @@ public PTPOldSettingsCheck(IIndexerFactory indexerFactory, ILocalizationService public override HealthCheck Check() { - var ptpIndexers = _indexerFactory.All().Where(i => i.Settings.GetType() == typeof(PassThePopcornSettings)); + var ptpIndexers = _indexerFactory.All() + .Where(i => i.Settings.GetType() == typeof(PassThePopcornSettings)); var ptpIndexerOldSettings = ptpIndexers - .Where(i => (i.Settings as PassThePopcornSettings).APIUser.IsNullOrWhiteSpace()).Select(i => i.Name); + .Where(i => ((PassThePopcornSettings)i.Settings).APIUser.IsNullOrWhiteSpace()).Select(i => i.Name) + .ToList(); if (ptpIndexerOldSettings.Any()) { diff --git a/src/NzbDrone.Core/HealthCheck/Checks/ProxyCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/ProxyCheck.cs index aea1ecf1f..756d2b785 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/ProxyCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/ProxyCheck.cs @@ -31,35 +31,38 @@ public ProxyCheck(IRadarrCloudRequestBuilder cloudRequestBuilder, IConfigService public override HealthCheck Check() { - if (_configService.ProxyEnabled) + if (!_configService.ProxyEnabled) { - var addresses = Dns.GetHostAddresses(_configService.ProxyHostname); - if (!addresses.Any()) - { - return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("ProxyCheckResolveIpMessage"), _configService.ProxyHostname), "#proxy-failed-resolve-ip"); - } + return new HealthCheck(GetType()); + } - var request = _cloudRequestBuilder.Create() - .Resource("/ping") - .Build(); + var addresses = Dns.GetHostAddresses(_configService.ProxyHostname); - try - { - var response = _client.Execute(request); + if (!addresses.Any()) + { + return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("ProxyCheckResolveIpMessage"), _configService.ProxyHostname), "#proxy-failed-resolve-ip"); + } - // We only care about 400 responses, other error codes can be ignored - if (response.StatusCode == HttpStatusCode.BadRequest) - { - _logger.Error("Proxy Health Check failed: {0}", response.StatusCode); - return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("ProxyCheckBadRequestMessage"), response.StatusCode), "#proxy-failed-test"); - } - } - catch (Exception ex) + var request = _cloudRequestBuilder.Create() + .Resource("/ping") + .Build(); + + try + { + var response = _client.Execute(request); + + // We only care about 400 responses, other error codes can be ignored + if (response.StatusCode == HttpStatusCode.BadRequest) { - _logger.Error(ex, "Proxy Health Check failed"); - return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("ProxyCheckFailedToTestMessage"), request.Url), "#proxy-failed-test"); + _logger.Error("Proxy Health Check failed: {0}", response.StatusCode); + return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("ProxyCheckBadRequestMessage"), response.StatusCode), "#proxy-failed-test"); } } + catch (Exception ex) + { + _logger.Error(ex, "Proxy Health Check failed"); + return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("ProxyCheckFailedToTestMessage"), request.Url), "#proxy-failed-test"); + } return new HealthCheck(GetType()); } diff --git a/src/NzbDrone.Core/HealthCheck/Checks/RemotePathMappingCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/RemotePathMappingCheck.cs index 532658807..77d253ad4 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/RemotePathMappingCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/RemotePathMappingCheck.cs @@ -62,6 +62,7 @@ public override HealthCheck Check() { var status = client.GetStatus(); var folders = status.OutputRootFolders; + foreach (var folder in folders) { if (!folder.IsValid) @@ -70,14 +71,13 @@ public override HealthCheck Check() { return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckWrongOSPath"), client.Definition.Name, folder.FullPath, _osInfo.Name), "#bad-remote-path-mapping"); } - else if (_osInfo.IsDocker) + + if (_osInfo.IsDocker) { return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckBadDockerPath"), client.Definition.Name, folder.FullPath, _osInfo.Name), "#docker-bad-remote-path-mapping"); } - else - { - return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckLocalWrongOSPath"), client.Definition.Name, folder.FullPath, _osInfo.Name), "#bad-download-client-settings"); - } + + return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckLocalWrongOSPath"), client.Definition.Name, folder.FullPath, _osInfo.Name), "#bad-download-client-settings"); } if (!_diskProvider.FolderExists(folder.FullPath)) @@ -86,14 +86,13 @@ public override HealthCheck Check() { return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckDockerFolderMissing"), client.Definition.Name, folder.FullPath), "#docker-bad-remote-path-mapping"); } - else if (!status.IsLocalhost) + + if (!status.IsLocalhost) { return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckLocalFolderMissing"), client.Definition.Name, folder.FullPath), "#bad-remote-path-mapping"); } - else - { - return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckGenericPermissions"), client.Definition.Name, folder.FullPath), "#permissions-error"); - } + + return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckGenericPermissions"), client.Definition.Name, folder.FullPath), "#permissions-error"); } } } @@ -122,24 +121,21 @@ public HealthCheck Check(IEvent message) return new HealthCheck(GetType()); } - if (typeof(MovieImportFailedEvent).IsAssignableFrom(message.GetType())) + if (message is MovieImportFailedEvent failureMessage) { - var failureMessage = (MovieImportFailedEvent)message; - // if we can see the file exists but the import failed then likely a permissions issue if (failureMessage.MovieInfo != null) { var moviePath = failureMessage.MovieInfo.Path; + if (_diskProvider.FileExists(moviePath)) { return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckDownloadPermissions"), moviePath), "#permissions-error"); } - else - { - // If the file doesn't exist but MovieInfo is not null then the message is coming from - // ImportApprovedMovies and the file must have been removed part way through processing - return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckFileRemoved"), moviePath), "#remote-path-file-removed"); - } + + // If the file doesn't exist but MovieInfo is not null then the message is coming from + // ImportApprovedMovies and the file must have been removed part way through processing + return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckFileRemoved"), moviePath), "#remote-path-file-removed"); } // If the previous case did not match then the failure occured in DownloadedMovieImportService, @@ -170,14 +166,13 @@ public HealthCheck Check(IEvent message) { return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckFilesWrongOSPath"), client.Definition.Name, dlpath, _osInfo.Name), "#bad-remote-path-mapping"); } - else if (_osInfo.IsDocker) + + if (_osInfo.IsDocker) { return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckFilesBadDockerPath"), client.Definition.Name, dlpath, _osInfo.Name), "#docker-bad-remote-path-mapping"); } - else - { - return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckFilesLocalWrongOSPath"), client.Definition.Name, dlpath, _osInfo.Name), "#bad-download-client-settings"); - } + + return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckFilesLocalWrongOSPath"), client.Definition.Name, dlpath, _osInfo.Name), "#bad-download-client-settings"); } if (_diskProvider.FolderExists(dlpath)) @@ -190,15 +185,14 @@ public HealthCheck Check(IEvent message) { return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckFolderPermissions"), client.Definition.Name, dlpath), "#docker-bad-remote-path-mapping"); } - else if (!status.IsLocalhost) + + if (!status.IsLocalhost) { return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckRemoteDownloadClient"), client.Definition.Name, dlpath), "#bad-remote-path-mapping"); } - else - { - // path mappings shouldn't be needed locally so probably a permissions issue - return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckFilesGenericPermissions"), client.Definition.Name, dlpath), "#permissions-error"); - } + + // path mappings shouldn't be needed locally so probably a permissions issue + return new HealthCheck(GetType(), HealthCheckResult.Error, string.Format(_localizationService.GetLocalizedString("RemotePathMappingCheckFilesGenericPermissions"), client.Definition.Name, dlpath), "#permissions-error"); } catch (DownloadClientException ex) { @@ -215,10 +209,8 @@ public HealthCheck Check(IEvent message) return new HealthCheck(GetType()); } - else - { - return Check(); - } + + return Check(); } } } diff --git a/src/NzbDrone.Core/HealthCheck/Checks/RootFolderCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/RootFolderCheck.cs index 73e4b3f96..b991adfcd 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/RootFolderCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/RootFolderCheck.cs @@ -29,11 +29,11 @@ public RootFolderCheck(IMovieService movieService, IDiskProvider diskProvider, I public override HealthCheck Check() { var rootFolders = _movieService.AllMoviePaths() - .Select(s => _rootFolderService.GetBestRootFolderPath(s.Value)) - .Distinct(); + .Select(s => _rootFolderService.GetBestRootFolderPath(s.Value)) + .Distinct(); var missingRootFolders = rootFolders.Where(s => !_diskProvider.FolderExists(s)) - .ToList(); + .ToList(); if (missingRootFolders.Any()) { diff --git a/src/NzbDrone.Core/HealthCheck/Checks/SlackUrlCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/SlackUrlCheck.cs index 22f94dd4e..9c24b1393 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/SlackUrlCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/SlackUrlCheck.cs @@ -22,7 +22,9 @@ public SlackUrlCheck(INotificationFactory notificationFactory, ILocalizationServ public override HealthCheck Check() { - var discordSlackNotifications = _notificationFactory.GetAvailableProviders().Where(n => n.ConfigContract.Equals("SlackSettings") && (n.Definition.Settings as SlackSettings).WebHookUrl.Contains("discord")); + var discordSlackNotifications = _notificationFactory.GetAvailableProviders() + .Where(n => n.ConfigContract.Equals("SlackSettings") && ((SlackSettings)n.Definition.Settings).WebHookUrl.Contains("discord")) + .ToList(); if (discordSlackNotifications.Empty()) { @@ -31,8 +33,7 @@ public override HealthCheck Check() return new HealthCheck(GetType(), HealthCheckResult.Warning, - string.Format(_localizationService.GetLocalizedString("DiscordUrlInSlackNotification"), - string.Join(", ", discordSlackNotifications.Select(n => n.Name))), + string.Format(_localizationService.GetLocalizedString("DiscordUrlInSlackNotification"), string.Join(", ", discordSlackNotifications.Select(n => n.Name))), "#discord-as-slack-notification"); } } diff --git a/src/NzbDrone.Core/HealthCheck/Checks/SystemTimeCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/SystemTimeCheck.cs index 43ae05686..6bdc96142 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/SystemTimeCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/SystemTimeCheck.cs @@ -24,8 +24,8 @@ public SystemTimeCheck(IHttpClient client, IRadarrCloudRequestBuilder cloudReque public override HealthCheck Check() { var request = _cloudRequestBuilder.Create() - .Resource("/time") - .Build(); + .Resource("/time") + .Build(); var response = _client.Execute(request); var result = Json.Deserialize(response.Content);