MCV Ingenieros

Agrupación independiente que ofrecemos servicios informáticos y desarrollos claves para el crecimiento empresarial.

La Vila Joiosa, Alicante, España

MCVIngenieros.Healthchecks (0.0.1)

Published 2025-08-30 11:56:04 +02:00 by manuel in MCVIngenieros/MCVIngenieros.Healthchecks

Installation

dotnet nuget add source --name MCVIngenieros --username your_username --password your_token 
dotnet add package --source MCVIngenieros --version 0.0.1 MCVIngenieros.Healthchecks

About this package

A READY-TO-USE HEALTHCHECK AID

MCVIngenieros.Healthchecks

LICENCIA: GNU General Public License v3.0

Librería para la gestión y exposición de healthchecks personalizables en aplicaciones .NET. Permite definir múltiples chequeos de salud, exponerlos vía API y configurarlos fácilmente.

¿Cómo funciona?

  1. Define tus healthchecks implementando la interfaz IHealthCheck.
  2. Regístralos en el contenedor de servicios usando los métodos de extensión.
  3. Opcionalmente, configura las opciones en appsettings.json.
  4. Accede a los resultados mediante los endpoints expuestos por el controlador.

Ejemplo de configuración en appsettings.json

{
    "HealthChecksConfigs": {
        "CacheDuration": "00:30:00",
        "Timeout": "00:00:05",
        "AssembliesToScan": [
            "MyAssembly"
        ],
        "MyCheck": {
            "RetryAttempts": 2,
            "Timeout": "00:05:00",
            "RetryDelay": "00:00:10",
            "Severity": "Info"
        }
    }
}

Ejemplo de configuración en CSharp

builder.Services.AddHealthChecksSupport(); // <--- Usará la configuración de appsettings.json

builder.Services.AddHealthChecksSupport(options => {
    options.AssembliesToScan.Add(typeof(Program).Assembly);
    options.CacheDuration = TimeSpan.FromMinutes(10);
    options.Timeout = TimeSpan.FromSeconds(5);
    options.Threshold = 0.7;
});

Ejemplo de uso en CSharp

// Registro manual de healthchecks
builder.Services.AddHealthChecksSupport()
    .AddCheck<CustomHealthCheck>("Custom");

// Registro automático de healthchecks
builder.Services.AddHealthChecksSupport()
    .DiscoverHealthChecks();

Ejemplo de implementación de un healthcheck personalizado

public class CustomHealthCheck () : HealthCheck
{
    public string Description => "Custom health check";

    public Task<HealthCheckResult> CheckAsync(CancellationToken cancellationToken = default)
    {
        // Lógica de chequeo
        return Task.FromResult(HealthCheckResult.Healthy("Todo OK"));
    }
}
public partial class HealthChecksConfigs : MCVIngenieros.Healthchecks.Options.HealthChecksConfigs
{
    public const string CustomHealthCheckWithOptions = nameof(CustomHealthCheckWithOptions);
}

---

public class CustomHealthCheckWithOptions (IOptionsMonitor<HealthChecksConfigs> healthchecksConfig) : HealthCheck
{
    private readonly HealthChecksConfigs hcConfig = healthchecksConfig.Get(HealthChecksConfigs.CustomHealthCheckWithOptions);
    public string Description => hcConfig.Description;
    public int? RetryAttempts => hcConfig.RetryAttempts ?? 2;
    public TimeSpan? Timeout => hcConfig.Timeout ?? TimeSpan.FromSeconds(5);
    public TimeSpan? RetryDelay => hcConfig.RetryDelay ?? TimeSpan.FromSeconds(1);
    public HealthCheckSeverity? Severity => hcConfig.Severity ?? HealthCheckSeverity.Critical;
    
    public Task<HealthCheckResult> CheckAsync(CancellationToken cancellationToken = default)
    {
        // Lógica de chequeo
        return Task.FromResult(HealthCheckResult.Healthy("Todo OK"));
    }
}

Endpoints disponibles

La librería expone un controlador con endpoints como:

  • GET /health — Estado general de la aplicación con detalle de todos los healthchecks.
  • GET /health/{nombre} — Estado de un healthcheck específico.

Ejemplo de llamada con curl:

curl http://localhost:5000/health
curl http://localhost:5000/health/Database

Si se envia Acept */* o text/html, o se usa un User-Agent compatible, se devolverá un HTML con el estado de los healthchecks y una interfaz interactiva para la consulta y visualización de resultados. También permite ejecutar uno o varios checks al momento

Ejemplos avanzados

{
    "HealthChecksConfigs": {
        "CacheDuration": "00:30:00",
        "Timeout": "00:02:00",
        "AssembliesToScan": [
            "MCVIngenieros.Backend"
        ],
        "MyCheck": {
            "RetryAttempts": 5,
            "Timeout": "00:00:30",
            "RetryDelay": "00:00:10",
            "Severity": "Critical"
        }
    }
}
public partial class HealthChecksConfigs : MCVIngenieros.Healthchecks.Options.HealthChecksConfigs
{
    public const string CustomHealthCheckWithOptions = nameof(CustomHealthCheckWithOptions);
}

---

public class CustomHealthCheckWithOptions (IDistributedCache redis, IOptionsMonitor<HealthChecksConfigs> healthchecksConfig) : HealthCheck
{
    private readonly HealthChecksConfigs hcConfig = healthchecksConfig.Get(HealthChecksConfigs.CustomHealthCheckWithOptions);
    public string Description => hcConfig.Description;
    public int? RetryAttempts => hcConfig.RetryAttempts ?? 2;
    public TimeSpan? Timeout => hcConfig.Timeout ?? TimeSpan.FromSeconds(5);
    public TimeSpan? RetryDelay => hcConfig.RetryDelay ?? TimeSpan.FromSeconds(1);
    public HealthCheckSeverity? Severity => hcConfig.Severity ?? HealthCheckSeverity.Critical;

    public async Task<HealthCheckResult> CheckAsync(CancellationToken cancellationToken = default)
    {
        try
        {
            var result = await redis.GetStringAsync("healthcheck");
            return result != null
                ? HealthCheckResult.Healthy("Todo OK", HealthCheckSeverity.Info)
                : HealthCheckResult.Unhealthy(
                    "No se encontró el estado",
                    HealthCheckSeverity.Critical,
                    Data: new Dictionary<string, object?> {
                        { "CacheKey", "healthcheck" },
                        { "RedisValue", result },
                        { "RedisInstance", redis.InstanceName }
                    });
        }
        catch (Exception ex)
        {
            return HealthCheckResult.Unhealthy(
                "Error",
                HealthCheckSeverity.Critical,
                Exception: ex,
                Data: new Dictionary<string, object?> {
                    { "BaseException", ex.GetBaseException() },
                    { "RedisInstance", redis.InstanceName }
                });
        }
    }
}

Adds a simple support for Healthchecks. Show a simple html if /api/health is checked with a briefing for tests results. Creating and customising tests behavior is easly customizable and isolatable from code. No need of explicit DI using DicoverHealthchecks.

Dependencies

ID Version Target Framework
Microsoft.AspNetCore.Mvc.Core 2.3.0 net9.0