mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-11 15:56:05 -07:00
Finished healthchecks
This commit is contained in:
parent
db2e3bd08c
commit
c20c16b7a0
13 changed files with 280 additions and 56 deletions
53
src/Ombi.HealthChecks/Checks/CouchPotatoHealthCheck.cs
Normal file
53
src/Ombi.HealthChecks/Checks/CouchPotatoHealthCheck.cs
Normal file
|
@ -0,0 +1,53 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Ombi.Api.CouchPotato;
|
||||
using Ombi.Api.Emby;
|
||||
using Ombi.Api.Emby.Models;
|
||||
using Ombi.Api.Plex;
|
||||
using Ombi.Api.Plex.Models.Status;
|
||||
using Ombi.Core.Settings;
|
||||
using Ombi.Core.Settings.Models.External;
|
||||
using Ombi.Settings.Settings.Models.External;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ombi.HealthChecks.Checks
|
||||
{
|
||||
public class CouchPotatoHealthCheck : BaseHealthCheck
|
||||
{
|
||||
public CouchPotatoHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory)
|
||||
{
|
||||
}
|
||||
public override async Task<HealthCheckResult> CheckHealthAsync(
|
||||
HealthCheckContext context,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
using (var scope = CreateScope())
|
||||
{
|
||||
var settingsProvider = scope.ServiceProvider.GetRequiredService<ISettingsService<CouchPotatoSettings>>();
|
||||
var api = scope.ServiceProvider.GetRequiredService<ICouchPotatoApi>();
|
||||
var settings = await settingsProvider.GetSettingsAsync();
|
||||
if (!settings.Enabled)
|
||||
{
|
||||
return HealthCheckResult.Healthy("CouchPotato is not configured.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var result = await api.Status(settings.ApiKey, settings.FullUri);
|
||||
if (result != null)
|
||||
{
|
||||
return HealthCheckResult.Healthy();
|
||||
}
|
||||
return HealthCheckResult.Degraded("Couldn't get the status from CouchPotato");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy("Could not communicate with CouchPotato", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
47
src/Ombi.HealthChecks/Checks/OmbiPingHealthCheck.cs
Normal file
47
src/Ombi.HealthChecks/Checks/OmbiPingHealthCheck.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
using HealthChecks.Network;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ombi.HealthChecks.Checks
|
||||
{
|
||||
public class OmbiPingHealthCheck
|
||||
: IHealthCheck
|
||||
{
|
||||
private readonly OmbiPingHealthCheckOptions _options;
|
||||
public OmbiPingHealthCheck(OmbiPingHealthCheckOptions options)
|
||||
{
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var configuredHosts = _options.ConfiguredHosts.Values;
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var (host, timeout, status) in configuredHosts)
|
||||
{
|
||||
using (var ping = new Ping())
|
||||
{
|
||||
var pingReply = await ping.SendPingAsync(host, timeout);
|
||||
|
||||
if (pingReply.Status != IPStatus.Success)
|
||||
{
|
||||
return new HealthCheckResult(status, description: $"Ping check for host {host} is failed with status reply:{pingReply.Status}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HealthCheckResult.Healthy();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new HealthCheckResult(context.Registration.FailureStatus, exception: ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
16
src/Ombi.HealthChecks/Checks/OmbiPingHealthCheckOptions.cs
Normal file
16
src/Ombi.HealthChecks/Checks/OmbiPingHealthCheckOptions.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.HealthChecks.Checks
|
||||
{
|
||||
public class OmbiPingHealthCheckOptions
|
||||
{
|
||||
internal Dictionary<string, (string Host, int TimeOut, HealthStatus status)> ConfiguredHosts { get; } = new Dictionary<string, (string, int, HealthStatus)>();
|
||||
|
||||
public OmbiPingHealthCheckOptions AddHost(string host, int timeout, HealthStatus status)
|
||||
{
|
||||
ConfiguredHosts.Add(host, (host, timeout, status));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
54
src/Ombi.HealthChecks/Checks/SickrageHealthCheck.cs
Normal file
54
src/Ombi.HealthChecks/Checks/SickrageHealthCheck.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Ombi.Api.CouchPotato;
|
||||
using Ombi.Api.Emby;
|
||||
using Ombi.Api.Emby.Models;
|
||||
using Ombi.Api.Plex;
|
||||
using Ombi.Api.Plex.Models.Status;
|
||||
using Ombi.Api.SickRage;
|
||||
using Ombi.Core.Settings;
|
||||
using Ombi.Core.Settings.Models.External;
|
||||
using Ombi.Settings.Settings.Models.External;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ombi.HealthChecks.Checks
|
||||
{
|
||||
public class SickrageHealthCheck : BaseHealthCheck
|
||||
{
|
||||
public SickrageHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory)
|
||||
{
|
||||
}
|
||||
public override async Task<HealthCheckResult> CheckHealthAsync(
|
||||
HealthCheckContext context,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
using (var scope = CreateScope())
|
||||
{
|
||||
var settingsProvider = scope.ServiceProvider.GetRequiredService<ISettingsService<SickRageSettings>>();
|
||||
var api = scope.ServiceProvider.GetRequiredService<ISickRageApi>();
|
||||
var settings = await settingsProvider.GetSettingsAsync();
|
||||
if (!settings.Enabled)
|
||||
{
|
||||
return HealthCheckResult.Healthy("SickRage is not configured.");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var result = await api.Ping(settings.ApiKey, settings.FullUri);
|
||||
if (result != null)
|
||||
{
|
||||
return HealthCheckResult.Healthy();
|
||||
}
|
||||
return HealthCheckResult.Degraded("Couldn't get the status from SickRage");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy("Could not communicate with SickRage", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Ombi.HealthChecks.Checks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.HealthChecks
|
||||
{
|
||||
|
@ -12,8 +15,41 @@ namespace Ombi.HealthChecks
|
|||
builder.AddCheck<LidarrHealthCheck>("Lidarr", tags: new string[] { "DVR" });
|
||||
builder.AddCheck<SonarrHealthCheck>("Sonarr", tags: new string[] { "DVR" });
|
||||
builder.AddCheck<RadarrHealthCheck>("Radarr", tags: new string[] { "DVR" });
|
||||
builder.AddCheck<CouchPotatoHealthCheck>("CouchPotato", tags: new string[] { "DVR" });
|
||||
builder.AddCheck<SickrageHealthCheck>("SickRage", tags: new string[] { "DVR" });
|
||||
builder.AddOmbiPingHealthCheck(options =>
|
||||
{
|
||||
options.AddHost("www.google.co.uk", 5000, HealthStatus.Unhealthy);
|
||||
options.AddHost("www.google.com", 3000, HealthStatus.Degraded);
|
||||
}, "External Ping", tags: new string[] { "System" });
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a health check for network ping.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IHealthChecksBuilder"/>.</param>
|
||||
/// <param name="setup">The action to configure the ping parameters.</param>
|
||||
/// <param name="name">The health check name. Optional. If <c>null</c> the type name 'ping' will be used for the name.</param>
|
||||
/// <param name="failureStatus">
|
||||
/// The <see cref="HealthStatus"/> that should be reported when the health check fails. Optional. If <c>null</c> then
|
||||
/// the default status of <see cref="HealthStatus.Unhealthy"/> will be reported.
|
||||
/// </param>
|
||||
/// <param name="tags">A list of tags that can be used to filter sets of health checks. Optional.</param>
|
||||
/// <param name="timeout">An optional System.TimeSpan representing the timeout of the check.</param>
|
||||
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns></param>
|
||||
public static IHealthChecksBuilder AddOmbiPingHealthCheck(this IHealthChecksBuilder builder, Action<OmbiPingHealthCheckOptions> setup, string name = default, HealthStatus? failureStatus = default, IEnumerable<string> tags = default, TimeSpan? timeout = default)
|
||||
{
|
||||
var options = new OmbiPingHealthCheckOptions();
|
||||
setup?.Invoke(options);
|
||||
|
||||
return builder.Add(new HealthCheckRegistration(
|
||||
name,
|
||||
sp => new OmbiPingHealthCheck(options),
|
||||
failureStatus,
|
||||
tags,
|
||||
timeout));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,18 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.HealthChecks.Network" Version="3.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
|
||||
<PackageReference Include="System.Collections" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ombi.Api.CouchPotato\Ombi.Api.CouchPotato.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Emby\Ombi.Api.Emby.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Lidarr\Ombi.Api.Lidarr.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Plex\Ombi.Api.Plex.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Radarr\Ombi.Api.Radarr.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.SickRage\Ombi.Api.SickRage.csproj" />
|
||||
<ProjectReference Include="..\Ombi.Api.Sonarr\Ombi.Api.Sonarr.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
public bool IgnoreCertificateErrors { get; set; }
|
||||
public bool DoNotSendNotificationsForAutoApprove { get; set; }
|
||||
public bool HideRequestsUsers { get; set; }
|
||||
public bool DisableHealthChecks { get; set; }
|
||||
public string DefaultLanguageCode { get; set; } = "en";
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ export interface IOmbiSettings extends ISettings {
|
|||
doNotSendNotificationsForAutoApprove: boolean;
|
||||
hideRequestsUsers: boolean;
|
||||
defaultLanguageCode: string;
|
||||
disableHealthChecks: boolean;
|
||||
}
|
||||
|
||||
export interface IUpdateSettings extends ISettings {
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
<div class="form-group">
|
||||
<label for="ApiKey" class="control-label">Api Key</label>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control form-control-custom" id="ApiKey" name="ApiKey" formControlName="apiKey"
|
||||
readonly="readonly" #apiKey>
|
||||
<input type="text" class="form-control form-control-custom" id="ApiKey" name="ApiKey" formControlName="apiKey" readonly="readonly" #apiKey>
|
||||
|
||||
<div class="input-group-addon">
|
||||
<div (click)="refreshApiKey()" id="refreshKey" class="fa fa-refresh" title="Reset API Key" pTooltip="This will invalidate the old API key"></div>
|
||||
|
@ -33,19 +32,27 @@
|
|||
<div>
|
||||
<mat-checkbox formControlName="doNotSendNotificationsForAutoApprove">
|
||||
Do not send Notifications if a User has the Auto Approve permission</mat-checkbox>
|
||||
</div><div>
|
||||
</div>
|
||||
<div>
|
||||
<mat-checkbox formControlName="hideRequestsUsers">
|
||||
Hide requests from other users
|
||||
</mat-checkbox>
|
||||
</div><div>
|
||||
</div>
|
||||
<div>
|
||||
<mat-checkbox formControlName="ignoreCertificateErrors" matTooltip="Enable if you are having connectivity problems over SSL">
|
||||
Ignore any certificate errors
|
||||
</mat-checkbox>
|
||||
</div><div>
|
||||
</div>
|
||||
<div>
|
||||
<mat-checkbox formControlName="collectAnalyticData" matTooltip="This will allow us to have a better understanding of the userbase so we know what we should be supporting">
|
||||
Allow us to collect anonymous analytical data e.g. browser used
|
||||
</mat-checkbox>
|
||||
</div><div>
|
||||
</div>
|
||||
<div>
|
||||
<mat-checkbox formControlName="disableHealthChecks">
|
||||
Disable the health checks page <a href="/healthchecks-ui" target="_blank">/healthchecks-ui</href></mat-checkbox>
|
||||
</div>
|
||||
<div>
|
||||
<mat-form-field *ngIf="langauges">
|
||||
<mat-select placeholder="Language" formControlName="defaultLanguageCode">
|
||||
<mat-option>--</mat-option>
|
||||
|
|
|
@ -29,6 +29,7 @@ export class OmbiComponent implements OnInit {
|
|||
doNotSendNotificationsForAutoApprove: [x.doNotSendNotificationsForAutoApprove],
|
||||
hideRequestsUsers: [x.hideRequestsUsers],
|
||||
defaultLanguageCode: [x.defaultLanguageCode],
|
||||
disableHealthChecks: [x.disableHealthChecks]
|
||||
});
|
||||
});
|
||||
this.langauges = <ILanguageRefine[]><any>languageData;
|
||||
|
|
|
@ -11,3 +11,4 @@
|
|||
#outer-container > aside > nav > a:nth-child(2) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,10 +79,11 @@ namespace Ombi
|
|||
var hcBuilder = services.AddHealthChecks();
|
||||
hcBuilder.AddOmbiHealthChecks();
|
||||
services.ConfigureDatabases(hcBuilder);
|
||||
services.AddHealthChecksUI(setupSettings: setup =>
|
||||
{
|
||||
setup.AddHealthCheckEndpoint("Ombi", "http://localhost:3577/healthz");
|
||||
});
|
||||
// Need to wait until https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/issues/410 is resolved
|
||||
//services.AddHealthChecksUI(setupSettings: setup =>
|
||||
//{
|
||||
// setup.AddHealthCheckEndpoint("Ombi", "/health");
|
||||
//});
|
||||
services.AddMemoryCache();
|
||||
|
||||
services.AddJwtAuthentication(Configuration);
|
||||
|
@ -115,7 +116,7 @@ namespace Ombi
|
|||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
|
||||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
|
||||
{
|
||||
app.UseForwardedHeaders(new ForwardedHeadersOptions
|
||||
{
|
||||
|
@ -212,8 +213,9 @@ namespace Ombi
|
|||
{
|
||||
endpoints.MapControllers();
|
||||
endpoints.MapHub<NotificationHub>("/hubs/notification");
|
||||
endpoints.MapHealthChecks("/health");
|
||||
endpoints.MapHealthChecks("/healthz", new HealthCheckOptions
|
||||
if (!settings.DisableHealthChecks)
|
||||
{
|
||||
endpoints.MapHealthChecks("/health", new HealthCheckOptions
|
||||
{
|
||||
Predicate = _ => true,
|
||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||
|
@ -222,14 +224,15 @@ namespace Ombi
|
|||
{
|
||||
opts.AddCustomStylesheet("HealthCheck.css");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
app.UseSpa(spa =>
|
||||
{
|
||||
//#if DEBUG
|
||||
// spa.Options.SourcePath = "ClientApp";
|
||||
// spa.UseProxyToSpaDevelopmentServer("http://localhost:3578");
|
||||
//#endif
|
||||
#if DEBUG
|
||||
spa.Options.SourcePath = "ClientApp";
|
||||
spa.UseProxyToSpaDevelopmentServer("http://localhost:3578");
|
||||
#endif
|
||||
});
|
||||
|
||||
}
|
||||
|
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue