Monitoring & Observability
This guide covers monitoring Milvaion in production, including health checks, metrics, logging, and alerting.
Health Checks
API Health Endpoints
| Endpoint | Purpose | Use For |
|---|---|---|
/health/live | Is the process running? | Kubernetes liveness probe |
/health/ready | Are dependencies healthy? | Kubernetes readiness probe |
/health | Full health with details | Debugging, dashboards |
Liveness Check
curl http://localhost:5000/api/v1/healthcheck/live
Response:
{
"status": "Healthy",
"timestamp": "2026-01-14T17:55:12.5466734Z",
"uptime": "16.05:34:46.9359664"
}
Readiness Check
curl http://localhost:5000/api/v1/healthcheck/ready
Response:
{
"status": "Healthy",
"duration": "00:00:00.0015505",
"timestamp": "2026-01-14T17:55:39.7914455Z",
"checks": [
{
"name": "PostgreSQL",
"status": "Healthy",
"description": "PostgreSQL database connection is healthy",
"duration": "00:00:00.0014398",
"tags": [
"database",
"sql"
],
"data": {
"DatabaseName": "MilvaionDb",
"ConnectionStatus": "Connected",
"ProviderName": "Npgsql.EntityFrameworkCore.PostgreSQL"
}
},
{
"name": "Redis",
"status": "Healthy",
"description": "Redis connection is healthy",
"duration": "00:00:00.0004801",
"tags": [
"redis",
"cache"
],
"data": {
"ConnectionStatus": "Connected",
"Database": "0"
}
},
{
"name": "RabbitMQ",
"status": "Healthy",
"description": "RabbitMQ connection is healthy",
"duration": "00:00:00.0000037",
"tags": [
"rabbitmq",
"messaging"
],
"data": {
"ConnectionStatus": "Connected",
"Host": "rabbitmq",
"Port": "5672",
"IsOpen": "True"
}
}
]
}
Kubernetes Probes
spec:
containers:
- name: api
livenessProbe:
httpGet:
path: /api/v1/healthcheck/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /api/v1/healthcheck/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
Worker Health
Workers support two health check approaches: file-based (for Console Workers) and HTTP endpoint-based (for API Workers).
Configuration
Enable health checks in appsettings.json:
{
"Worker": {
"HealthCheck": {
"Enabled": true,
"LiveFilePath": "/tmp/live", // Only for file health check. (for console workers)
"ReadyFilePath": "/tmp/ready", // Only for file health check. (for console workers)
"IntervalSeconds": 30
}
}
}
| Setting | Default | Description |
|---|---|---|
Enabled | false | Enable/disable health checks |
LiveFilePath | /tmp/live | File path for liveness probe |
ReadyFilePath | /tmp/ready | File path for readiness probe |
IntervalSeconds | 30 | Health check interval |
Option 1: Console Worker (File-Based)
For workers without HTTP endpoints, use AddFileHealthCheck():
using Microsoft.Extensions.Hosting;
using Milvasoft.Milvaion.Sdk.Worker;
var builder = Host.CreateApplicationBuilder(args);
// Register Worker SDK
builder.Services.AddMilvaionWorkerWithJobs(builder.Configuration);
// Add file-based health checks (Redis + RabbitMQ)
builder.Services.AddFileHealthCheck(builder.Configuration);
var host = builder.Build();
await host.RunAsync();
Kubernetes probes:
spec:
containers:
- name: worker
livenessProbe:
exec:
command: ["test", "-f", "/tmp/live"]
initialDelaySeconds: 30
periodSeconds: 30
failureThreshold: 3
readinessProbe:
exec:
command: ["test", "-f", "/tmp/ready"]
initialDelaySeconds: 10
periodSeconds: 10
failureThreshold: 3
Docker Compose healthcheck:
worker:
healthcheck:
test: ["CMD", "test", "-f", "/tmp/live"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
Option 2: API Worker (HTTP Endpoints)
For workers with HTTP endpoints, use AddHealthCheckEndpoints() and UseHealthCheckEndpoints():
using Milvasoft.Milvaion.Sdk.Worker;
using Milvasoft.Milvaion.Sdk.Worker.HealthChecks;
var builder = WebApplication.CreateBuilder(args);
// Add health checks (Redis + RabbitMQ)
builder.Services.AddHealthChecks()
.AddCheck<RedisHealthCheck>("Redis", tags: ["redis", "cache"])
.AddCheck<RabbitMQHealthCheck>("RabbitMQ", tags: ["rabbitmq", "messaging"]);
// Register Worker SDK
builder.Services.AddMilvaionWorkerWithJobs(builder.Configuration);
// Register health check endpoint services
builder.Services.AddHealthCheckEndpoints(builder.Configuration);
var app = builder.Build();
// Map health check endpoints
app.UseHealthCheckEndpoints(builder.Configuration);
await app.RunAsync();
Available endpoints:
| Endpoint | Purpose | Response |
|---|---|---|
/health | Simple check | "Ok" |
/health/live | Liveness probe | { status, timestamp, uptime } |
/health/ready | Readiness probe | { status, duration, checks[] } |
/health/startup | Startup probe | { status, timestamp, uptime } |
Kubernetes probes:
spec:
containers:
- name: api-worker
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
startupProbe:
httpGet:
path: /health/startup
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 30
Health Check Behavior
The SDK includes built-in health checks for:
| Check | What it Verifies |
|---|---|
| Redis | Connection status via PING command |
| RabbitMQ | Connection status via IConnectionMonitor |
File-based health check logic:
- Live file exists: Worker process is running and not completely unhealthy
- Ready file exists: All health checks (Redis, RabbitMQ) are healthy
- Files are deleted on graceful shutdown
- Files are updated every
IntervalSeconds