💻 Développement

health-check-monitor

Implémentation de health checks ASP.NET Core, readiness/liveness probes et intégration Kubernetes.

⚡ Installation & lancement en 1 commande

Copiez-collez dans votre terminal : le skill s'installe dans ~/.claude/skills et Claude Code se lance directement dessus.

macOS / Linux
curl -fsSL https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.sh | sh -s -- health-check-monitor --launch
Windows (PowerShell)
iex "& { $(iwr -useb https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.ps1) } health-check-monitor -Launch"

🚀 Déjà installé ?

claude "/health-check-monitor"

Ou tapez /health-check-monitor dans une session Claude Code, ou décrivez simplement votre besoin — le skill se déclenche automatiquement via le skill-router.

🔑 Déclencheurs automatiques

Le skill s'active automatiquement quand votre demande contient :

health checkliveness probereadiness probeendpoint santéhealth endpointASP.NET healthmonitoring applicatif

📦 Installation manuelle

git clone https://github.com/khalilbenaz/claude-skills-collection.git cp -r claude-skills-collection/dev-skills/health-check-monitor ~/.claude/skills/

Source : dev-skills/health-check-monitor

📖 Manuel

Health Checks & Monitoring

Workflow

  1. Identifier les dépendances : base de données, cache, services externes, file queues.
  2. Implémenter les checks : un check par dépendance critique.
  3. Configurer les probes : liveness (l'app est vivante) et readiness (l'app peut servir du trafic).
  4. Intégrer : Kubernetes probes, dashboard, alertes.

Configuration ASP.NET Core

Setup de base

// Program.cs
builder.Services.AddHealthChecks()
    // Base de données
    .AddSqlServer(
        connectionString,
        name: "sqlserver",
        tags: new[] { "db", "ready" },
        timeout: TimeSpan.FromSeconds(5))

    // Redis
    .AddRedis(
        redisConnectionString,
        name: "redis",
        tags: new[] { "cache", "ready" },
        timeout: TimeSpan.FromSeconds(3))

    // RabbitMQ
    .AddRabbitMQ(
        rabbitConnectionString,
        name: "rabbitmq",
        tags: new[] { "messaging", "ready" },
        timeout: TimeSpan.FromSeconds(5))

    // Service externe
    .AddUrlGroup(
        new Uri("https://api.partner.com/health"),
        name: "partner-api",
        tags: new[] { "external" },
        timeout: TimeSpan.FromSeconds(10))

    // Check custom
    .AddCheck<DiskSpaceHealthCheck>("disk-space",
        tags: new[] { "infrastructure" });

// Endpoints
app.MapHealthChecks("/health/live", new HealthCheckOptions
{
    Predicate = _ => false, // Aucun check — juste "l'app répond"
    ResponseWriter = WriteMinimalResponse
});

app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
    Predicate = check => check.Tags.Contains("ready"),
    ResponseWriter = WriteDetailedResponse
});

app.MapHealthChecks("/health/full", new HealthCheckOptions
{
    ResponseWriter = WriteDetailedResponse
});

Health Check personnalisé

public class DiskSpaceHealthCheck : IHealthCheck
{
    private const long MinimumFreeBytes = 1_073_741_824; // 1 GB

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken ct = default)
    {
        var drive = new DriveInfo("/");
        var freeSpace = drive.AvailableFreeSpace;

        if (freeSpace < MinimumFreeBytes)
        {
            return Task.FromResult(HealthCheckResult.Unhealthy(
                $"Espace disque faible : {freeSpace / 1_048_576} MB restants"));
        }

        return Task.FromResult(HealthCheckResult.Healthy(
            $"Espace disque OK : {freeSpace / 1_073_741_824} GB disponibles"));
    }
}

Réponse JSON détaillée

static async Task WriteDetailedResponse(HttpContext context, HealthReport report)
{
    context.Response.ContentType = "application/json";

    var result = new
    {
        status = report.Status.ToString(),
        duration = report.TotalDuration.TotalMilliseconds,
        checks = report.Entries.Select(e => new
        {
            name = e.Key,
            status = e.Value.Status.ToString(),
            duration = e.Value.Duration.TotalMilliseconds,
            description = e.Value.Description,
            error = e.Value.Exception?.Message
        })
    };

    await context.Response.WriteAsJsonAsync(result);
}

Intégration Kubernetes

Probes

# deployment.yaml
spec:
  containers:
    - name: payment-api
      ports:
        - containerPort: 8080
      livenessProbe:
        httpGet:
          path: /health/live
          port: 8080
        initialDelaySeconds: 15
        periodSeconds: 10
        failureThreshold: 3
        # Si 3 échecs → K8s redémarre le pod
      readinessProbe:
        httpGet:
          path: /health/ready
          port: 8080
        initialDelaySeconds: 5
        periodSeconds: 5
        failureThreshold: 3
        # Si 3 échecs → K8s retire le pod du service
      startupProbe:
        httpGet:
          path: /health/live
          port: 8080
        initialDelaySeconds: 0
        periodSeconds: 3
        failureThreshold: 30
        # Laisse 90s au pod pour démarrer

Différences entre probes

ProbeQuestionConséquence si échec
LivenessL'app est-elle vivante ?Pod redémarré
ReadinessL'app peut-elle servir du trafic ?Pod retiré du load balancer
StartupL'app a-t-elle fini de démarrer ?Liveness/readiness suspendues

Bonnes pratiques

À faire

À éviter

Règles