Skip to content

Commit

Permalink
Add Redis Health Check (OrchardCMS#13589)
Browse files Browse the repository at this point in the history
Co-authored-by: Zoltán Lehóczky <zoltan.lehoczky@lombiq.com>
  • Loading branch information
hishamco and Piedone authored Apr 10, 2024
1 parent c80c5e1 commit 7296191
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using OrchardCore.Redis.HealthChecks;

namespace Microsoft.Extensions.DependencyInjection;

public static class RedisHealthCheckExtensions
{
public static IHealthChecksBuilder AddRedisCheck(this IHealthChecksBuilder healthChecksBuilder)
=> healthChecksBuilder.AddCheck<RedisHealthCheck>("Redis Health Check");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace OrchardCore.Redis.HealthChecks;

public class RedisHealthCheck : IHealthCheck
{
private const int Timeout = 30;

private readonly IServiceProvider _serviceProvider;

public RedisHealthCheck(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider;

public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
try
{
var redisService = _serviceProvider.GetService<IRedisService>();
if (redisService == null)
{
return HealthCheckResult.Unhealthy(description: $"The service '{nameof(IRedisService)}' isn't registered.");
}

if (redisService.Connection == null)
{
await redisService.ConnectAsync();
}

if (redisService.Connection.IsConnected)
{
var time = await redisService.Database.PingAsync();
if (time > TimeSpan.FromSeconds(Timeout))
{
return HealthCheckResult.Unhealthy(description: $"The Redis server couldn't be reached within {Timeout} seconds and might be offline or have degraded performance.");
}
else
{
return HealthCheckResult.Healthy();
}
}
else
{
return HealthCheckResult.Unhealthy(description: "Couldn't connect to the Redis server.");
}
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy("Retrieving the status of the Redis service failed.", ex);
}
}
}
19 changes: 19 additions & 0 deletions src/OrchardCore.Modules/OrchardCore.Redis/HealthChecks/Startup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Microsoft.Extensions.DependencyInjection;
using OrchardCore.Modules;

namespace OrchardCore.Redis.HealthChecks;

[RequireFeatures("OrchardCore.HealthChecks")]
public class Startup : StartupBase
{
// The order of this startup configuration should be greater than zero to register the Redis check early,
// so the health check can be reported alongside with other health checks in the system.
public override int Order => 100;

public override void ConfigureServices(IServiceCollection services)
{
services
.AddHealthChecks()
.AddRedisCheck();
}
}
4 changes: 4 additions & 0 deletions src/docs/reference/modules/Redis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Integrates Redis into Orchard Core. Provides the following features:
- Redis Lock: Distributed Lock using Redis.
- Redis DataProtection: Distributed DataProtection using Redis.

## Health Checks

This module provides a health check to report the status for the Redis server. Refer also to the [Health Checks Section](../HealthChecks/README.md).

## Video

<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/etH6IJOGUe8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

0 comments on commit 7296191

Please sign in to comment.