Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 4 Min.

Health Checks für Ressourcen

Wenn externe APIs stocken, Speicher knapp wird oder Ressourcen an Grenzen laufen, reicht ein grüner Gesamtstatus nicht mehr aus. Wie Health Checks näher an die tatsächlichen Betriebsrisiken heranrücken, ohne den Diagnose-Endpunkt unnötig aufzublähen.
© EMGenie

Der zweite Teil der Serie „Health Checks in ASP.NET richtig nutzen“ hat gezeigt, dass sich über die Schnittstelle IHealthCheck verschiedene Health-Check-Klassen implementieren lassen. Beispielsweise für externe Schnittstellen, um diese im Kontext eines Health Checks einer eigenen Endpunkt-Implementierung ebenfalls zu überwachen. Denn wenn ein externer, aber notwendiger Dienst offline ist, dann ist die Wahrscheinlichkeit sehr hoch, dass der eigene Endpunkt beziehungsweise Dienst davon in irgendeiner Weise betroffen ist. Viele Dienste hängen nämlich von externen (RESTful) APIs ab

IHealthCheck und externe APIs

Um externe APIs zu überwachen, lässt sich die Schnittstelle IHealthCheck implementieren und ein HttpClient injizieren. Das hat der zweite Teil dieser Serie an einem Beispiel bereits gezeigt. Das nachfolgende Listing 1 greift diese Demo auf, erweitert aber die interne Protokollierung um einen wichtigen Logger und die Rückgabe um den Status Degraded, wenn das angefragte externe API einen HTTP-Status-Code ungleich 200 OK zurückliefert. Dazu nutzt das Beispiel das fiktive API /api/status und fragt dieses ab. Das ist besser als das Beispiel aus dem zweiten Teil dieser Serie, in dem lediglich ein Aufruf des Endpunkts /ping erfolgte.

Listing 1: Erweiterter Health Check mit besserer Rückgabe und Logging
public async Task<HealthCheckResult> CheckHealthAsync(
    HealthCheckContext context,
    CancellationToken cancellationToken = default)
{
    try
    {
        var response = await _httpClient.GetAsync("/api/status", cancellationToken);
        if (response.IsSuccessStatusCode)
        {
            return HealthCheckResult.Healthy("External API ist erreichbar");
        }
        return HealthCheckResult.Degraded($"External API antwortete mit {response.StatusCode}");
    }
    catch (HttpRequestException ex)
    {
        _logger.LogError(ex, "External API Health Check fehlgeschlagen");
        return HealthCheckResult.Unhealthy("External API ist nicht erreichbar", ex);
    }
} 

Infrastrukturelle Ressourcen

Neben funktionalen Abhängigkeiten spielen infrastrukturelle Ressourcen eine zentrale Rolle bei Health Checks. Zu wenig Speicherplatz, erschöpfter Arbeitsspeicher oder überfüllte Queues können eine Anwendung ebenso unbrauchbar machen wie eine defekte Datenbank. Solche Checks sind oft sehr projektspezifisch, lassen sich aber mit IHealthCheck ebenfalls gut modellieren.

Ein typischer Anwendungsfall ist das Überwachen von freiem Festplattenspeicher, zum Beispiel für Upload-Verzeichnisse oder Log-Ordner. Ein einfacher Disk-Check könnte aussehen wie in Listing 2 gezeigt.

Listing 2: Health-Check-Implementierung für Speicherverbrauch
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace dnp.Healthy
{
    public class DiskSpaceHealthCheck : IHealthCheck
    {
        private const long MinimumFreeMegabytes = 1024; // 1 GB
        public Task<HealthCheckResult> CheckHealthAsync(
            HealthCheckContext context,
            CancellationToken cancellationToken = default)
        {
            var drive = new DriveInfo(Path.GetPathRoot(AppContext.BaseDirectory)!);
            var free = drive.AvailableFreeSpace / (1024 * 1024);
            return Task.FromResult(
                free >= MinimumFreeMegabytes
                    ? HealthCheckResult.Healthy($"Free space: {free} MB")
                    : HealthCheckResult.Unhealthy($"Low disk space: {free} MB"));
        }
    }
} 

Registriert wird der Check wie gewohnt über:

 

builder.Services.AddHealthChecks()
    .AddCheck<DiskSpaceHealthCheck>("disk");

 

Bild 1 zeigt die Ausgabe in Postman. Zu sehen ist der Status des Health Checks mit Namen und den wichtigsten Werten. In einer produktionsreifen Variante wird man hier typischerweise Laufwerk und Schwellenwerte aus der Konfiguration einlesen und nur die für den Service relevanten Pfade prüfen.

Ausgabe des Health Checks für den Speicherverbrauch in Postman (Bild 1)

Ausgabe des Health Checks für den Speicherverbrauch in Postman (Bild 1)

© Autor

Ähnlich lassen sich Checks für Arbeitsspeicher oder Threadpool-Auslastung implementieren, etwa auf Basis von GC.GetTotalMemory oder Performance-Countern. In Containern ist es sinnvoll, sich an den im Pod gesetzten Limits zu orientieren und relative Schwellenwerte, beispielsweise „80% des RAM-Limits“ zu verwenden, statt absolute Werte hart zu codieren. Ein weiteres Muster sind sogenannte Business-Health-Checks wie die nachfolgenden Beispiele:

  • „Gibt es unzustellbare Nachrichten in der Dead-Letter-Queue?“
  • „Seit wann steht der Hintergrundjob zur Rechnungsstellung?“
  • „Ist die interne Feature-Flag-Konfiguration konsistent geladen?“

Diese Checks sind fachlich getrieben, nutzen aber dieselbe Infrastruktur und tauchen wie alle anderen Checks im /health-Report auf. Der eigentliche Mehrwert eines Health-Systems entsteht genau dort: durch eine Mischung aus generischen Prüfungen, wie denen von Datenbank, Disk und Memory, sowie domänenspezifischen Prüfungen, die gemeinsam ein realistisches Bild der Systemgesundheit zeichnen.

Anpassen der JSON-Antwort

Die Standardausgabe eines Health Checks liefert nur den Gesamtstatus. Für Monitoring-Dashboards sind aber detaillierte Informationen hilfreich. Das Anpassen der Health-Antwort hat bereits der erste Teil dieser Serie über den ResponseWriter gezeigt. Das nachfolgende Beispiel erweitert die Ausgabe um wichtige Informationen wie die Gesamtdauer, mögliche Exceptions und weitere Daten. Listing 3 zeigt ein Beispiel für die Implementierung.

Listing 3: Erweiterte JSON-Ausgabe der Health-Check-Antwort
app.MapHealthChecks("/health", new HealthCheckOptions
{
    ResponseWriter = async (context, report) =>
    {
        context.Response.ContentType = "application/json";
        var response = new
        {
            status = report.Status.ToString(),
            totalDuration = 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,
                exception = e.Value.Exception?.Message,
                data = e.Value.Data
            })
        };
        await context.Response.WriteAsJsonAsync(response);
    }
}); 

Die resultierende JSON-Antwort enthält pro Check den Status, die Dauer und optionale Zusatzdaten, was die Fehlersuche erheblich erleichtert. Bild 2 zeigt eine beispielhafte Antwort in Postman.

Ausgabe des Health Checks für den Speicherverbrauch in Postman mit weiteren Daten im JSON-Format (Bild 2)

Ausgabe des Health Checks für den Speicherverbrauch in Postman mit weiteren Daten im JSON-Format (Bild 2)

© Autor

Fazit

Diese dritte Folge der Serie „Health Checks in ASP.NET richtig nutzen“ hat gezeigt, wie externe Dienste, Dateisysteme und Speicherplatz überwacht werden können und wie sich die individuellen JSON-Antworten erweitern lassen. Die Erkenntnisse verbessern die Transparenz der Anwendung und erleichtern das Monitoring. Besonders bei externen APIs ist es wichtig, Time-outs zu definieren, damit der Health Check nicht hängen bleibt. Beim HttpClient lässt sich beispielsweise ein Time-out setzen, um das zu erreichen. Ebenso lassen sich Schwellenwerte für zum Beispiel Arbeitsspeicher oder Festplattenplatz definieren, um frühzeitig einen Degraded-Status zu melden.

Neueste Beiträge

MessagePack: JSON als Binär-Image - Best of NuGet, Teil 10
Das Serialisierungsformat MessagePack wurde – anders als JSON – konsequent auf die Bedürfnisse von Maschinen und damit auch auf höchstmögliche Kompaktheit optimiert. Der Vorteil: Ein geringeres zu übertragendes Datenvolumen führt vor allem in IoT-nahen Anwendungen direkt zu geringeren Kosten.
6 Minuten
17. Aug 2026
Die Kunst der langen Aufgabenläufe - Kimi K3 – das Modell hinter dem Agenten, Teil 2
Ein guter Code-Generator löst eine klar umrissene Funktion. Ein Coding-Agent muss dagegen ein Repository erkunden, Hypothesen bilden, Werkzeuge auswählen, Tests auswerten und nach Fehlschlägen den Kurs ändern. Kimi K3 zielt auf diese zweite Klasse von Aufgaben.
8 Minuten
Gebaut für lange Läufe - Kimi K3 – das Modell hinter dem Agenten, Teil 1
Kimi K3 kombiniert 2,8 Billionen Parameter, native Bildverarbeitung und ein Kontextfenster mit einer Million Token. Das sind tolle Zahlen. Seine Besonderheit liegt aber darin, dass Architektur, Training und Laufzeitumgebung auf Agenten zielen, die über viele Schritte handeln, Werkzeuge aufrufen und Ergebnisse prüfen.
6 Minuten

Das könnte Dich auch interessieren

Health Checks und Kubernetes - Health Checks in ASP.NET richtig nutzen, Teil 4
In Kubernetes entscheidet ein Health Check nicht nur über Sichtbarkeit im Monitoring, sondern auch darüber, ob Traffic fließt oder ein Container neu startet. Hier zeigen wir, warum saubere Grenzen zwischen Liveness und Readiness in produktiven ASP.NET-Anwendungen so wichtig sind.
4 Minuten
Die Chromium-Engine anbinden - Ein eigenes Steuerelement für Webinhalte, Teil 14
Das Browser-Control wird für den Einbau der Chromium-Engine vorbereitet.
10 Minuten
17. Okt 2022
Grundlagen von Health Checks - Health Checks in ASP.NET richtig nutzen, Teil 1
Ein einfacher Statuscode sagt wenig darüber aus, ob eine Anwendung wirklich betriebsbereit ist. ASP.NET bietet dafür mehr Möglichkeiten, als viele /health-Endpunkte vermuten lassen. Genau dort beginnt der Unterschied zwischen Erreichbarkeit und echter Diagnose.
4 Minuten
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige