Zetian.HealthCheck 1.0.0

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package Zetian.HealthCheck --version 1.0.0
                    
NuGet\Install-Package Zetian.HealthCheck -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Zetian.HealthCheck" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Zetian.HealthCheck" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Zetian.HealthCheck" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Zetian.HealthCheck --version 1.0.0
                    
#r "nuget: Zetian.HealthCheck, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Zetian.HealthCheck@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Zetian.HealthCheck&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Zetian.HealthCheck&version=1.0.0
                    
Install as a Cake Tool

Zetian.HealthCheck - Health Monitoring for SMTP

NuGet-Version NuGet-Download License

A lightweight health monitoring extension for Zetian SMTP Server, providing HTTP endpoints for health checks, liveness probes, readiness checks, and custom health metrics. Perfect for Kubernetes, Docker Swarm, load balancers, and monitoring systems.

⚑ Features

  • πŸ” Multiple Endpoints - /health/, /health/livez, /health/readyz
  • πŸ“Š Detailed Metrics - Server uptime, active sessions, memory usage, utilization
  • 🎯 Custom Checks - Add your own health checks (database, disk, services)
  • 🌐 Flexible Binding - Support for localhost, specific IPs, hostnames, IPv6
  • ☸️ Kubernetes Ready - Built for K8s liveness and readiness probes
  • πŸ”„ Real-time Status - Live server health monitoring
  • πŸ“ˆ JSON Response - Structured health data for monitoring tools
  • πŸš€ Zero Dependencies - Lightweight, uses only .NET built-in HttpListener

πŸ“¦ Installation

# Install Zetian SMTP Server (required)
dotnet add package Zetian

# Install Health Check Extension
dotnet add package Zetian.HealthCheck

πŸš€ Quick Start

Basic Health Check

using Zetian;
using Zetian.HealthCheck.Extensions;

// Create and start SMTP server
var server = SmtpServerBuilder.CreateBasic();
await server.StartAsync();

// Enable health check on port 8080
var healthCheck = server.EnableHealthCheck(8080);
await healthCheck.StartAsync();

// Health check now available at:
// http://localhost:8080/health/
// http://localhost:8080/health/livez
// http://localhost:8080/health/readyz

Start Server with Health Check

// Start both SMTP and health check together
var healthCheck = await server.StartWithHealthCheckAsync(8080);

πŸ› οΈ Advanced Configuration

Custom Port and Path

// Custom port
var healthCheck = server.EnableHealthCheck(9090);

// Custom path (must end with /)
var healthCheck = server.EnableHealthCheck(8080, "/status/");

IP/Hostname Binding

// Bind to specific IP
var healthCheck = server.EnableHealthCheck(IPAddress.Parse("192.168.1.100"), 8080);

// Bind to hostname
var healthCheck = server.EnableHealthCheck("myserver.local", 8080);

// Bind to all interfaces (accessible externally)
var healthCheck = server.EnableHealthCheck("0.0.0.0", 8080);

// IPv6 support
var healthCheck = server.EnableHealthCheck(IPAddress.IPv6Loopback, 8080);

Custom Health Checks

var healthCheck = server.EnableHealthCheck(8080);

// Add database check
healthCheck.AddHealthCheck("database", async (ct) =>
{
    try
    {
        var isConnected = await CheckDatabaseAsync();
        return isConnected 
            ? HealthCheckResult.Healthy("Database connected")
            : HealthCheckResult.Unhealthy("Database connection failed");
    }
    catch (Exception ex)
    {
        return HealthCheckResult.Unhealthy("Database error", ex);
    }
});

// Add disk space check
healthCheck.AddHealthCheck("disk_space", async (ct) =>
{
    var drive = new DriveInfo("C:\\");
    var freePercent = (double)drive.AvailableFreeSpace / drive.TotalSize * 100;
    
    var data = new Dictionary<string, object>
    {
        ["freeSpaceGB"] = drive.AvailableFreeSpace / (1024 * 1024 * 1024),
        ["totalSpaceGB"] = drive.TotalSize / (1024 * 1024 * 1024),
        ["freePercent"] = Math.Round(freePercent, 2)
    };
    
    if (freePercent < 10)
        return HealthCheckResult.Unhealthy($"Critical: {freePercent:F2}% free", data: data);
    if (freePercent < 20)
        return HealthCheckResult.Degraded($"Low space: {freePercent:F2}% free", data: data);
    
    return HealthCheckResult.Healthy($"Disk space OK: {freePercent:F2}% free", data: data);
});

await healthCheck.StartAsync();

Advanced Options

// Custom thresholds for SMTP health
var smtpOptions = new SmtpHealthCheckOptions
{
    DegradedThresholdPercent = 60,   // Degraded at 60% utilization
    UnhealthyThresholdPercent = 85,  // Unhealthy at 85% utilization
    CheckMemoryUsage = true           // Include memory metrics
};

// Custom service options
var serviceOptions = new HealthCheckServiceOptions
{
    Prefixes = new() { "http://+:8080/health/" },  // Listen on all interfaces
    DegradedStatusCode = 218  // Custom HTTP status for degraded (default: 200)
};

var healthCheck = server.EnableHealthCheck(serviceOptions, smtpOptions);
await healthCheck.StartAsync();

πŸ“Š Response Format

Healthy Response (HTTP 200)

{
  "status": "Healthy",
  "timestamp": "2024-10-22T16:30:00Z",
  "checks": {
    "smtp_server": {
      "status": "Healthy",
      "description": "SMTP server is healthy",
      "data": {
        "status": "running",
        "uptime": "2d 3h 15m 42s",
        "activeSessions": 5,
        "maxSessions": 50,
        "utilizationPercent": 10.0,
        "memoryUsageMB": 45.2
      }
    },
    "database": {
      "status": "Healthy",
      "description": "Database connected"
    },
    "disk_space": {
      "status": "Healthy",
      "description": "Disk space OK: 65.3% free",
      "data": {
        "freeSpaceGB": 250,
        "totalSpaceGB": 500,
        "freePercent": 50.0
      }
    }
  }
}

Degraded Response (HTTP 200 or custom)

{
  "status": "Degraded",
  "timestamp": "2024-10-22T16:30:00Z",
  "checks": {
    "smtp_server": {
      "status": "Degraded",
      "description": "SMTP server utilization is high",
      "data": {
        "activeSessions": 35,
        "maxSessions": 50,
        "utilizationPercent": 70.0
      }
    }
  }
}

Unhealthy Response (HTTP 503)

{
  "status": "Unhealthy",
  "timestamp": "2024-10-22T16:30:00Z",
  "checks": {
    "smtp_server": {
      "status": "Unhealthy",
      "description": "SMTP server is not running"
    }
  }
}

☸️ Kubernetes Integration

Deployment Configuration

apiVersion: apps/v1
kind: Deployment
metadata:
  name: smtp-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: smtp-server
  template:
    metadata:
      labels:
        app: smtp-server
    spec:
      containers:
      - name: smtp-server
        image: myregistry/smtp-server:latest
        ports:
        - containerPort: 25   # SMTP port
        - containerPort: 8080 # Health check port
        livenessProbe:
          httpGet:
            path: /health/livez
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /health/readyz
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 2

Service Configuration

apiVersion: v1
kind: Service
metadata:
  name: smtp-service
spec:
  selector:
    app: smtp-server
  ports:
  - name: smtp
    port: 25
    targetPort: 25
  - name: health
    port: 8080
    targetPort: 8080

🐳 Docker Integration

Dockerfile Example

FROM mcr.microsoft.com/dotnet/runtime:8.0
WORKDIR /app
COPY . .
EXPOSE 25 8080
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:8080/health/ || exit 1
ENTRYPOINT ["dotnet", "MySmtpServer.dll"]

Docker Compose

version: '3.8'
services:
  smtp:
    image: mysmtp:latest
    ports:
      - "25:25"
      - "8080:8080"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health/"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 40s

🎯 Monitoring Integration

Prometheus Metrics

// Add custom metrics check for Prometheus
healthCheck.AddHealthCheck("metrics", async (ct) =>
{
    var data = new Dictionary<string, object>
    {
        ["smtp_connections_active"] = server.SessionCount,
        ["smtp_connections_total"] = server.TotalConnectionsCount,
        ["smtp_messages_received"] = server.MessagesReceivedCount,
        ["smtp_uptime_seconds"] = server.UptimeSeconds
    };
    
    return HealthCheckResult.Healthy("Metrics collected", data: data);
});

Grafana/Datadog

Use the JSON endpoints to collect metrics:

# Collect health data
curl http://localhost:8080/health/ | jq '.checks.smtp_server.data'

# Check liveness
curl -f http://localhost:8080/health/livez

# Check readiness  
curl -f http://localhost:8080/health/readyz

πŸ“ API Reference

Extension Methods

Method Description
EnableHealthCheck(port) Enable health check on localhost
EnableHealthCheck(hostname, port) Enable on specific hostname
EnableHealthCheck(IPAddress, port) Enable on specific IP
EnableHealthCheck(options, healthOptions) Advanced configuration
StartWithHealthCheckAsync(port) Start server and health check
AddHealthCheck(name, checkFunc) Add custom health check

Health Check Results

Status HTTP Code Description
Healthy 200 Everything is working
Degraded 200/218 Working but with issues
Unhealthy 503 Critical problems detected

πŸ”§ Troubleshooting

Common Issues

Port Already in Use

// Check if port is available before starting
var listener = new HttpListener();
try
{
    listener.Prefixes.Add("http://localhost:8080/");
    listener.Start();
    listener.Stop();
    // Port is available
}
catch (HttpListenerException)
{
    // Port is in use
}

Access Denied on Non-Localhost

# Windows: Run as administrator or add URL ACL
netsh http add urlacl url=http://+:8080/health/ user=Everyone

# Linux: Use authbind or run as root
sudo setcap cap_net_bind_service=+ep /usr/bin/dotnet

IPv6 Issues

// Check IPv6 support
if (Socket.OSSupportsIPv6)
{
    var healthCheck = server.EnableHealthCheck(IPAddress.IPv6Any, 8080);
}
else
{
    var healthCheck = server.EnableHealthCheck("0.0.0.0", 8080);
}

πŸ“‹ Requirements

  • Windows, Linux, or macOS
  • Zetian SMTP Server package
  • .NET 6.0, 7.0, 8.0, 9.0, or 10.0
  • Administrator privileges for non-localhost binding (Windows)

πŸ“š Documentation & Support

πŸ™ Acknowledgments

  • Community feedback and contributions
  • Inspired by ASP.NET Core Health Checks
  • Built on top of Zetian SMTP Server

πŸ”’ Security

Best Practices:

  • Configure rate limiting
  • Keep the library updated
  • Implement proper authentication
  • Always use TLS/SSL in production

Report Security Issues: taiizor@vegalya.com

πŸ“„ License

MIT License - see LICENSE


Built with ❀️ for the .NET community

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.8 681 12/1/2025
1.0.7 121 11/1/2025
1.0.6 233 10/29/2025
1.0.5 148 10/25/2025
1.0.4 6,409 10/23/2025
1.0.3 1,814 10/23/2025
1.0.2 6,678 10/22/2025
1.0.1 1,756 10/22/2025
1.0.0 4,864 10/22/2025

All changes are detailed at https://zetian.soferity.com/changelog.