nguyenvanchiens/my-skills · Archived

aspnet-health-checks

Setup ASP.NET Core Health Checks: AddHealthChecks() với probes cho DB (SqlServer/Npgsql), Redis, RabbitMQ, external HTTP, custom check; tách `/healthz/live` (liveness) vs `/healthz/ready` (readiness) cho Kubernetes/Docker; AspNetCore.HealthChecks.UI dashboard; tag-based filtering.

First seen May 9, 2026

Installation

$ npx skills add nguyenvanchiens/my-skills --skill aspnet-health-checks

Summary

  • Setup ASP.NET Core Health Checks: AddHealthChecks() với probes cho DB (SqlServer/Npgsql), Redis, RabbitMQ, external HTTP, custom check; tách `/healthz/live` (liveness) vs `/healthz/ready` (readiness) cho Kubernetes/Docker; AspNetCore.HealthChecks.UI dashboard; tag-based filtering.
  • Use khi deploy lên K8s/Docker, setup load balancer probe, monitor service dependencies, hoặc user nói 'health endpoint', 'liveness/readiness', 'monitor service'.

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from nguyenvanchiens/my-skills · top by installs.

npx skills add nguyenvanchiens/my-skills

Browse all from nguyenvanchiens/my-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

CompatibilityRequires ASP.NET Core. UI dashboard cần `AspNetCore.HealthChecks.UI` (community).

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 9,216 B
  • docs SUMMARY.md 478 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

ASP.NET Core Health Checks

Trigger On

  • deploy lên Kubernetes/Docker — cần livenessProbe, readinessProbe endpoints
  • load balancer (nginx, AWS ALB, Azure App Gateway) cần health endpoint
  • monitor service health (dependencies up/down, latency)
  • separate liveness vs readiness checks
  • thêm probe cho DB, Redis, queue, external API
  • dashboard health visualization (AspNetCore.HealthChecks.UI)

Documentation

Liveness vs Readiness — bắt buộc tách 2

Liveness Readiness
Hỏi gì App có còn alive không? App có sẵn sàng nhận traffic không?
Fail = Restart container Tạm thời ngưng route traffic
Check gì App process responsive (chỉ self-check, KHÔNG check dependencies) DB, Redis, dependencies, init complete
Endpoint /healthz/live /healthz/ready
K8s probe livenessProbe readinessProbe

Quan trọng: liveness KHÔNG check DB. Nếu DB down, app không cần restart — chỉ readiness fail (k8s ngưng route traffic, app vẫn chạy). Liveness check DB → DB down → restart loop vô tận.

Setup cơ bản

// Program.cs
builder.Services.AddHealthChecks()
    .AddSqlServer(
        connectionString: builder.Configuration.GetConnectionString("Default")!,
        name: "sql",
        failureStatus: HealthStatus.Unhealthy,
        tags: ["db", "ready"])
    .AddRedis(
        redisConnectionString: builder.Configuration.GetConnectionString("Redis")!,
        name: "redis",
        tags: ["cache", "ready"])
    .AddUrlGroup(
        new Uri("https://api.partner.com/health"),
        name: "partner-api",
        tags: ["external", "ready"]);

var app = builder.Build();

// Liveness — chỉ check app self (không check tag)
app.MapHealthChecks("/healthz/live", new HealthCheckOptions
{
    Predicate = _ => false,   // không chạy bất kỳ registered check, chỉ trả OK nếu app live
    ResponseWriter = WriteHealthResponse
});

// Readiness — chạy mọi check có tag "ready"
app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
    Predicate = check => check.Tags.Contains("ready"),
    ResponseWriter = WriteHealthResponse
});

app.Run();

static Task WriteHealthResponse(HttpContext context, HealthReport 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(),
            description = e.Value.Description,
            duration = e.Value.Duration.TotalMilliseconds,
            error = e.Value.Exception?.Message
        })
    };
    return context.Response.WriteAsync(JsonSerializer.Serialize(response));
}

Common probes — packages

# Database
dotnet add package AspNetCore.HealthChecks.SqlServer
dotnet add package AspNetCore.HealthChecks.Npgsql       # PostgreSQL
dotnet add package AspNetCore.HealthChecks.MySql

# Cache
dotnet add package AspNetCore.HealthChecks.Redis

# Messaging
dotnet add package AspNetCore.HealthChecks.RabbitMQ
dotnet add package AspNetCore.HealthChecks.Kafka

# External
dotnet add package AspNetCore.HealthChecks.Uris

# Hệ thống
dotnet add package AspNetCore.HealthChecks.System       # disk, memory

Custom Health Check

public class StripeHealthCheck(IStripeClient stripe) : IHealthCheck
{
    public async Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        try
        {
            var sw = Stopwatch.StartNew();
            await stripe.GetService<AccountService>().GetSelfAsync(cancellationToken: cancellationToken);
            sw.Stop();

            // Degraded nếu chậm
            if (sw.ElapsedMilliseconds > 2000)
                return HealthCheckResult.Degraded($"Stripe slow: {sw.ElapsedMilliseconds}ms");

            return HealthCheckResult.Healthy($"Stripe OK ({sw.ElapsedMilliseconds}ms)");
        }
        catch (Exception ex)
        {
            return HealthCheckResult.Unhealthy("Stripe API unreachable", ex);
        }
    }
}

// Register
builder.Services.AddHealthChecks()
    .AddCheck<StripeHealthCheck>("stripe", tags: ["external", "ready"]);

Health Status — 3 levels

Status Khi dùng Effect
Healthy Working bình thường LB route traffic
Degraded Working nhưng chậm/limited LB route nhưng có thể alert
Unhealthy Không serve được LB ngưng route, k8s restart (nếu liveness)

Health Check UI Dashboard

dotnet add package AspNetCore.HealthChecks.UI
dotnet add package AspNetCore.HealthChecks.UI.Client
dotnet add package AspNetCore.HealthChecks.UI.InMemory.Storage   # hoặc SQLite/SqlServer
builder.Services.AddHealthChecksUI(opt =>
{
    opt.SetEvaluationTimeInSeconds(30);
    opt.MaximumHistoryEntriesPerEndpoint(60);
    opt.AddHealthCheckEndpoint("My App", "/healthz/ready");
}).AddInMemoryStorage();

app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
    Predicate = check => check.Tags.Contains("ready"),
    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse   // format cho UI
});

app.MapHealthChecksUI(opt => opt.UIPath = "/healthz/ui");

Truy cập /healthz/ui → dashboard với history, charts.

Kubernetes Probe Config

# deployment.yaml
spec:
  containers:
  - name: myapp
    livenessProbe:
      httpGet:
        path: /healthz/live
        port: 8080
      initialDelaySeconds: 10
      periodSeconds: 30
      timeoutSeconds: 5
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /healthz/ready
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
      timeoutSeconds: 5
      failureThreshold: 2

Tag Strategy

.AddSqlServer(..., tags: ["db", "ready", "critical"])
.AddRedis(..., tags: ["cache", "ready"])
.AddUrlGroup(..., tags: ["external", "ready", "non-critical"])

// Multiple endpoints với filter khác nhau
app.MapHealthChecks("/healthz/critical", new()
{
    Predicate = c => c.Tags.Contains("critical")
});
app.MapHealthChecks("/healthz/full", new()
{
    Predicate = _ => true
});

Anti-patterns

Anti-pattern Vấn đề Fix
Liveness check DB DB down → k8s restart loop Liveness Predicate = _ => false (chỉ self)
Single endpoint cho cả 2 Không tách behavior /healthz/live + /healthz/ready riêng
No timeout trong custom check Probe hang → k8s tưởng app dead Pass cancellationToken, set timeout
Check external API trong liveness Network blip → restart External checks chỉ ở readiness
Health endpoint không protected nhưng leak detail Info disclosure (DB version, schema) Filter response, hoặc require auth cho /healthz/full
Predicate = _ => true cho liveness Chạy mọi check (slow) Chỉ readiness chạy full
Quên handle exception trong custom check IHealthCheck lib auto wrap nhưng custom logic dễ throw Try/catch return Unhealthy(ex)
Probe interval quá ngắn (1s) Spam DB periodSeconds: 10-30

Performance

  • Cache health result: nếu probe heavy (full DB query), cache 5-10s tránh hammer DB
  • Parallel execution: built-in HealthCheckService chạy parallel — đặt timeout reasonable cho mỗi check
  • Lazy register: probe chỉ chạy khi endpoint hit, không background

Validate

  • Tách /healthz/live (no deps) và /healthz/ready (full deps)
  • Liveness KHÔNG check DB/Redis/external
  • Readiness include all critical deps với tags
  • Custom check có exception handling, return Unhealthy(ex)
  • K8s probe config với initialDelay, period, timeout, failureThreshold reasonable
  • Health endpoint không leak sensitive info (DB connection string, schema)
  • Timeout trong custom check honor CancellationToken
  • (Optional) UI dashboard cho ops monitoring

Hand off to

  • Logging health events → aspnet-logging
  • Hosting/middleware order → aspnet-core
  • DB connection management → entity-framework-core
  • Background task health → background-jobs