Appouse.Probes 1.0.3

dotnet add package Appouse.Probes --version 1.0.3
                    
NuGet\Install-Package Appouse.Probes -Version 1.0.3
                    
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="Appouse.Probes" Version="1.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Appouse.Probes" Version="1.0.3" />
                    
Directory.Packages.props
<PackageReference Include="Appouse.Probes" />
                    
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 Appouse.Probes --version 1.0.3
                    
#r "nuget: Appouse.Probes, 1.0.3"
                    
#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 Appouse.Probes@1.0.3
                    
#: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=Appouse.Probes&version=1.0.3
                    
Install as a Cake Addin
#tool nuget:?package=Appouse.Probes&version=1.0.3
                    
Install as a Cake Tool

Appouse.Probes

.NET License: MIT NuGet

Appouse.Probes, .NET uygulamaları için Kubernetes-uyumlu liveness ve readiness probe endpoint'leri sağlayan hafif bir kütüphanedir. Microsoft'un yerleşik HealthChecks altyapısı üzerine inşa edilmiştir; sıfır harici NuGet bağımlılığı ile çalışır.


✨ Özellikler

  • 🏥 Live & Ready Probe — Kubernetes livenessProbe ve readinessProbe desteği
  • 🔌 Pluggable Check SistemiIProbeCheck arayüzü ile özel kontroller yazabilme
  • 🔀 Çoklu Probe Tipi — Tek bir check'i aynı anda hem Live hem Ready probe'larında kullanabilme
  • ⏱️ Per-Check Timeout — Her check için yapılandırılabilir zaman aşımı süresi
  • ⚙️ Configuration-Driven — Host, port ve endpoint path bilgilerini appsettings.json'dan yönetme
  • 🎯 Multi-Targetnet5.0 · net6.0 · net7.0 · net8.0 · net9.0
  • 🪟 Windows Service Desteği — Süreç içi hafif HTTP host ile servis izleme
  • 📊 Detaylı JSON Yanıt — Her check için status, description, duration ve custom data

📦 Kurulum

NuGet ile

dotnet add package Appouse.Probes

Proje referansı ile

<ItemGroup>
  <ProjectReference Include="path/to/Appouse.Probes.csproj" />
</ItemGroup>

🚀 Hızlı Başlangıç

.NET 6+ Minimal API

using Appouse.Probes.Extensions;

var builder = WebApplication.CreateBuilder(args);

// 1) Probe port binding (opsiyonel — ayrı port kullanılacaksa)
builder.UseAppouseProbeBinding();

// 2) Servisleri kaydet
builder.Services.AddAppouseProbes(builder.Configuration);
builder.Services.AddProbeCheck<MyLiveCheck>();
builder.Services.AddProbeCheck<MyReadyCheck>();

var app = builder.Build();

// 3) Endpoint'leri map'le
app.MapAppouseProbes();

app.Run();

.NET 5 Startup Tabanlı

Program.cs

using Appouse.Probes.Extensions;

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        return Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();

                var configuration = new ConfigurationBuilder()
                    .AddJsonFile("appsettings.json", optional: true)
                    .AddEnvironmentVariables()
                    .Build();

                webBuilder.UseAppouseProbeBinding(configuration);
            });
    }
}

Startup.cs

using Appouse.Probes.Extensions;

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();

        // Servisleri kaydet
        services.AddAppouseProbes(Configuration);
        services.AddProbeCheck<MyLiveCheck>();
        services.AddProbeCheck<MyReadyCheck>();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapAppouseProbes(); // Probe endpoint'lerini map'le
        });
    }
}

⚙️ Konfigürasyon

appsettings.json dosyasına Probes bölümünü ekleyin:

{
  "Probes": {
    "Enabled": true,
    "BindHostPort": true,
    "Host": "127.0.0.1",
    "Port": 5055,
    "LivePath": "/health/live",
    "ReadyPath": "/health/ready",
    "CheckTimeoutMs": 5000
  }
}

Konfigürasyon Parametreleri

Parametre Tip Varsayılan Açıklama
Enabled bool true Probe sistemi aktif mi? false ise hiçbir health check register edilmez
BindHostPort bool true Belirtilen Host:Port'a binding yapılsın mı?
Host string "127.0.0.1" Probe endpoint'lerinin dinleyeceği IP adresi
Port int 5055 Probe endpoint'lerinin dinleyeceği port numarası
LivePath string "/health/live" Liveness probe endpoint path'i
ReadyPath string "/health/ready" Readiness probe endpoint path'i
CheckTimeoutMs int 5000 Her bir IProbeCheck için maksimum çalışma süresi (ms)

Özel Section Adı Kullanma

Varsayılan "Probes" bölüm adını değiştirebilirsiniz:

services.AddAppouseProbes(configuration, sectionName: "HealthProbes");
builder.UseAppouseProbeBinding(sectionName: "HealthProbes");
{
  "HealthProbes": {
    "Enabled": true,
    "Port": 6060
  }
}

🔌 IProbeCheck ile Özel Check Yazma

Temel Arayüz

public interface IProbeCheck
{
    string Name { get; }
    IReadOnlyCollection<ProbeType> ProbeTypes { get; }
    Task<ProbeCheckResult> CheckAsync(CancellationToken cancellationToken = default);
}
Üye Açıklama
Name Check'in benzersiz adı — JSON yanıtında ve loglarda bu isimle görünür
ProbeTypes Bu check hangi probe tip(ler)inde çalışsın: Live, Ready veya her ikisi
CheckAsync Asıl kontrol mantığı — ProbeCheckResult döndürür

ProbeType Enum

public enum ProbeType
{
    Live = 1,   // Liveness probe — süreç hayatta mı?
    Ready = 2   // Readiness probe — trafik almaya hazır mı?
}

ProbeCheckResult Factory Method'ları

// ✅ Sağlıklı
ProbeCheckResult.Healthy("Database connection is OK.");

// ⚠️ Bozulmuş (degraded) — servis çalışıyor ama performans düşük
ProbeCheckResult.Degraded("Response time is high.", exception);

// ❌ Sağlıksız — servis trafik almamalı
ProbeCheckResult.Unhealthy("Cannot reach database.", exception);

Her factory method opsiyonel data parametresi kabul eder:

ProbeCheckResult.Healthy(
    "Environment is configured.",
    new Dictionary<string, object>
    {
        ["environment"] = "Production",
        ["region"] = "eu-west-1"
    });

📝 Örnek Check Implementasyonları

Basit Liveness Check

Sürecin hayatta olduğunu doğrulayan en temel check:

public sealed class SelfLiveCheck : IProbeCheck
{
    public string Name => "self";

    public IReadOnlyCollection<ProbeType> ProbeTypes =>
        new[] { ProbeType.Live };

    public Task<ProbeCheckResult> CheckAsync(CancellationToken cancellationToken = default)
    {
        return Task.FromResult(ProbeCheckResult.Healthy("Process is alive."));
    }
}

Veritabanı Readiness Check

Veritabanı bağlantısını kontrol eden bir readiness check:

public sealed class DatabaseReadyCheck : IProbeCheck
{
    private readonly IDbConnectionFactory _connectionFactory;

    public DatabaseReadyCheck(IDbConnectionFactory connectionFactory)
    {
        _connectionFactory = connectionFactory;
    }

    public string Name => "database";

    public IReadOnlyCollection<ProbeType> ProbeTypes =>
        new[] { ProbeType.Ready };

    public async Task<ProbeCheckResult> CheckAsync(CancellationToken cancellationToken = default)
    {
        try
        {
            using var connection = _connectionFactory.CreateConnection();
            await connection.OpenAsync(cancellationToken);

            return ProbeCheckResult.Healthy("Database connection is OK.");
        }
        catch (Exception ex)
        {
            return ProbeCheckResult.Unhealthy("Cannot connect to database.", ex);
        }
    }
}

Initialization State Check

Warm-up tamamlanana kadar uygulamanın trafiğe hazır olmadığını bildiren check:

public sealed class InitializationReadyCheck : IProbeCheck
{
    private readonly InitializationState _state;

    public InitializationReadyCheck(InitializationState state)
    {
        _state = state;
    }

    public string Name => "initialization";

    public IReadOnlyCollection<ProbeType> ProbeTypes =>
        new[] { ProbeType.Ready };

    public Task<ProbeCheckResult> CheckAsync(CancellationToken cancellationToken = default)
    {
        if (!_state.IsInitialized)
        {
            return Task.FromResult(
                ProbeCheckResult.Unhealthy("Initialization has not completed yet."));
        }

        return Task.FromResult(
            ProbeCheckResult.Healthy("Initialization completed successfully."));
    }
}

Çoklu Probe Tipi — Hem Live Hem Ready

Tek bir check'i birden fazla probe tipinde çalıştırabilirsiniz:

public sealed class EnvironmentCheck : IProbeCheck
{
    private readonly IConfiguration _configuration;

    public EnvironmentCheck(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public string Name => "environment";

    // Hem Live hem Ready probe'larında çalışır
    public IReadOnlyCollection<ProbeType> ProbeTypes =>
        new[] { ProbeType.Live, ProbeType.Ready };

    public Task<ProbeCheckResult> CheckAsync(CancellationToken cancellationToken = default)
    {
        var env = _configuration["ASPNETCORE_ENVIRONMENT"];

        if (string.IsNullOrWhiteSpace(env))
        {
            return Task.FromResult(
                ProbeCheckResult.Degraded("ASPNETCORE_ENVIRONMENT is not set."));
        }

        return Task.FromResult(
            ProbeCheckResult.Healthy(
                "Environment configuration is available.",
                new Dictionary<string, object>
                {
                    ["environment"] = env
                }));
    }
}

External Service Health Check

Harici bir API'nin erişilebilirliğini doğrulayan check:

public sealed class PaymentGatewayCheck : IProbeCheck
{
    private readonly HttpClient _httpClient;

    public PaymentGatewayCheck(IHttpClientFactory httpClientFactory)
    {
        _httpClient = httpClientFactory.CreateClient("PaymentGateway");
    }

    public string Name => "payment-gateway";

    public IReadOnlyCollection<ProbeType> ProbeTypes =>
        new[] { ProbeType.Ready };

    public async Task<ProbeCheckResult> CheckAsync(CancellationToken cancellationToken = default)
    {
        try
        {
            var response = await _httpClient.GetAsync("/health", cancellationToken);

            return response.IsSuccessStatusCode
                ? ProbeCheckResult.Healthy("Payment gateway is reachable.")
                : ProbeCheckResult.Degraded($"Payment gateway returned {response.StatusCode}.");
        }
        catch (Exception ex)
        {
            return ProbeCheckResult.Unhealthy("Payment gateway is unreachable.", ex);
        }
    }
}

📋 Check Kayıt Yöntemleri

Generic Tip ile (DI Container Resolve Eder)

services.AddProbeCheck<DatabaseReadyCheck>();
services.AddProbeCheck<PaymentGatewayCheck>();

Check sınıfı DI container tarafından resolve edilir. Constructor injection tam desteklenir.

Instance ile (Önceden Oluşturulmuş)

var staticCheck = new SelfLiveCheck();
services.AddProbeCheck(staticCheck);

📡 Endpoint Yanıt Formatı

Probe endpoint'leri detaylı JSON yanıt döndürür.

✅ Healthy Yanıt — HTTP 200 OK

GET http://127.0.0.1:5055/health/live
{
  "status": "Healthy",
  "totalDurationMs": 1.23,
  "entries": {
    "appouse_probe_live": {
      "status": "Healthy",
      "description": "Live probe healthy.",
      "durationMs": 0.89,
      "data": {
        "self": {
          "status": "Healthy",
          "description": "Process is alive.",
          "data": null
        },
        "environment": {
          "status": "Healthy",
          "description": "Environment configuration is available.",
          "data": {
            "environment": "Production"
          }
        }
      }
    }
  }
}

❌ Unhealthy Yanıt — HTTP 503 Service Unavailable

GET http://127.0.0.1:5055/health/ready
{
  "status": "Unhealthy",
  "totalDurationMs": 5012.45,
  "entries": {
    "appouse_probe_ready": {
      "status": "Unhealthy",
      "description": "Ready probe failed. database: Cannot connect to database.",
      "durationMs": 5010.12,
      "data": {
        "database": {
          "status": "Unhealthy",
          "description": "Cannot connect to database."
        }
      }
    }
  }
}

HTTP Durum Kodları

Durum HTTP Kodu
Healthy 200 OK
Degraded 200 OK
Unhealthy 503 Service Unavailable

🪟 Windows Service Kullanımı

Appouse.Probes, Windows Service olarak çalışan uygulamalarda süreç içinde küçük bir HTTP host açarak probe endpoint'lerini dışarıya sunar:

using Appouse.Probes.Extensions;

var builder = WebApplication.CreateBuilder(args);

// Ayrı port üzerinde probe host aç
builder.UseAppouseProbeBinding();

// Windows Service olarak çalıştır
builder.Services.AddWindowsService(options =>
{
    options.ServiceName = "MyBackgroundService";
});

// Background worker'ları kaydet
builder.Services.AddHostedService<MyWorker>();

// Probe sistemini kaydet
builder.Services.AddAppouseProbes(builder.Configuration);
builder.Services.AddProbeCheck<SelfLiveCheck>();
builder.Services.AddProbeCheck<InitializationReadyCheck>();

var app = builder.Build();

// Probe endpoint'lerini map'le
app.MapAppouseProbes();

await app.RunAsync();
{
  "Probes": {
    "Enabled": true,
    "BindHostPort": true,
    "Host": "127.0.0.1",
    "Port": 6060,
    "LivePath": "/health/live",
    "ReadyPath": "/health/ready"
  }
}

Servisimiz artık http://127.0.0.1:6060/health/live ve http://127.0.0.1:6060/health/ready adreslerinden izlenebilir.


☸️ Kubernetes Entegrasyonu

Pod Tanımı

apiVersion: v1
kind: Pod
metadata:
  name: my-api
spec:
  containers:
    - name: my-api
      image: my-api:latest
      ports:
        - containerPort: 8080
          name: http
        - containerPort: 5055
          name: probes
      livenessProbe:
        httpGet:
          path: /health/live
          port: probes
        initialDelaySeconds: 5
        periodSeconds: 10
        timeoutSeconds: 5
        failureThreshold: 3
      readinessProbe:
        httpGet:
          path: /health/ready
          port: probes
        initialDelaySeconds: 10
        periodSeconds: 5
        timeoutSeconds: 5
        failureThreshold: 3

Docker Compose Health Check

services:
  my-api:
    image: my-api:latest
    ports:
      - "8080:8080"
      - "5055:5055"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:5055/health/live"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 15s

⏱️ Timeout Davranışı

Her IProbeCheck çalıştırılırken CheckTimeoutMs süresi kadar bekler. Süre aşılırsa:

  1. Check otomatik olarak iptal edilir (OperationCanceledException)
  2. Sonuç Unhealthy olarak işaretlenir
  3. Açıklama: "Timed out after {CheckTimeoutMs}ms" şeklinde log'lanır
  4. Diğer check'ler etkilenmez — çalışmaya devam eder
{
  "Probes": {
    "CheckTimeoutMs": 3000
  }
}

İpucu: CheckAsync implementasyonunuzda cancellationToken parametresini dinlediğinizden emin olun. Timeout mekanizması bu token üzerinden çalışır.


🔧 Port Binding Davranışı

BindHostPort = true (Varsayılan)

Uygulama belirtilen Host:Port üzerinden dinlemeye başlar. Bu özellikle probe'ların ana uygulamadan farklı bir port üzerinde çalışması istendiğinde kullanılır.

BindHostPort = false

Mevcut uygulamanın port ayarına dokunulmaz. Probe endpoint'leri uygulamanın mevcut portunda çalışır. Web API uygulamalarında servis portu ve probe portu aynı olacaktır.

{
  "Probes": {
    "Enabled": true,
    "BindHostPort": false,
    "LivePath": "/health/live",
    "ReadyPath": "/health/ready"
  }
}

Enabled = false

Probe sistemi tamamen devre dışı kalır. Hiçbir health check register edilmez, endpoint mapping yapılmaz.


📂 Proje Yapısı

Appouse.HealthProbe/
├── src/
│   └── Appouse.Probes/                     # Ana kütüphane
│       ├── Abstractions/
│       │   ├── IProbeCheck.cs              # Tüketici arayüzü
│       │   ├── ProbeCheckResult.cs         # Check sonuç modeli
│       │   ├── ProbeCheckStatus.cs         # Healthy / Degraded / Unhealthy
│       │   └── ProbeType.cs               # Live / Ready
│       ├── Extensions/
│       │   ├── ServiceCollectionExtensions.cs      # AddAppouseProbes(), AddProbeCheck<T>()
│       │   ├── WebApplicationBuilderExtensions.cs  # Minimal API binding (.NET 6+)
│       │   ├── WebHostBuilderExtensions.cs         # Generic Host binding (.NET 5+)
│       │   └── EndpointRouteBuilderExtensions.cs   # MapAppouseProbes()
│       ├── Internal/
│       │   ├── ProbeTypeHealthCheckBase.cs         # Template Method — check motoru
│       │   ├── LiveProbeHealthCheck.cs             # Live probe IHealthCheck
│       │   ├── ReadyProbeHealthCheck.cs            # Ready probe IHealthCheck
│       │   ├── ProbeHealthResponseWriter.cs        # JSON response writer
│       │   └── ProbeRegistrationNames.cs           # Registration sabitleri
│       └── Options/
│           └── ProbeOptions.cs                     # Konfigürasyon sınıfı
├── samples/
│   ├── Sample.ProbeWebApi.Net5/            # Startup tabanlı Web API örneği
│   └── Sample.ProbeWindowsService.Net8/    # Windows Service + HTTP host örneği
└── Appouse.Probes.sln

🏗️ Mimari

┌──────────────────┐     ┌──────────────────────────────────────────────────┐
│  Consumer App    │     │              Appouse.Probes                      │
│                  │     │                                                  │
│  AddAppouseProbes├────►│  ServiceCollectionExtensions                     │
│  AddProbeCheck   │     │    → Live/ReadyProbeHealthCheck (singleton)      │
│                  │     │    → IOptions<ProbeOptions> (configuration)      │
│  UseAppouseProbe │     │                                                  │
│    Binding       ├────►│  WebApplicationBuilder / WebHostBuilder          │
│                  │     │    → UseUrls(Host:Port)                          │
│  MapAppouseProbes├────►│  EndpointRouteBuilderExtensions                  │
│                  │     │    → MapHealthChecks(LivePath)                   │
│                  │     │    → MapHealthChecks(ReadyPath)                  │
└──────────────────┘     └──────────────────────────────────────────────────┘
                                            │
                                            ▼
                          ┌──────────────────────────────┐
                          │   ProbeTypeHealthCheckBase    │
                          │   (Template Method Pattern)   │
                          │                              │
                          │   foreach IProbeCheck:       │
                          │     1. Filter by ProbeType   │
                          │     2. Apply timeout (CTS)   │
                          │     3. CheckAsync()          │
                          │     4. Aggregate results     │
                          └──────────────────────────────┘
                                            │
                                            ▼
                          ┌──────────────────────────────┐
                          │   IProbeCheck (your checks)   │
                          │                              │
                          │   DatabaseReadyCheck         │
                          │   SelfLiveCheck              │
                          │   CacheReadyCheck            │
                          │   ...                        │
                          └──────────────────────────────┘

🔗 API Referansı

Extension Method'lar

Method Açıklama
services.AddAppouseProbes(configuration) Probe altyapısını DI container'a kayıt eder
services.AddAppouseProbes(configuration, sectionName) Özel section adı ile kayıt eder
services.AddProbeCheck<TCheck>() Generic tip ile IProbeCheck kayıt eder (singleton)
services.AddProbeCheck(instance) Önceden oluşturulmuş instance'ı kayıt eder
builder.UseAppouseProbeBinding() .NET 6+ — Probe portuna binding yapar
builder.UseAppouseProbeBinding(sectionName) .NET 6+ — Özel section adı ile binding
webBuilder.UseAppouseProbeBinding(configuration) .NET 5+ — Generic Host binding
endpoints.MapAppouseProbes() Live ve Ready endpoint'lerini IEndpointRouteBuilder'a map'ler

Abstractions

Tip Açıklama
IProbeCheck Check sözleşmesi — Name, ProbeTypes, CheckAsync()
ProbeCheckResult Check sonucu — Healthy(), Degraded(), Unhealthy() factory method'ları
ProbeCheckStatus Enum — Healthy = 1, Degraded = 2, Unhealthy = 3
ProbeType Enum — Live = 1, Ready = 2

Konfigürasyon

Tip Açıklama
ProbeOptions Enabled, BindHostPort, Host, Port, LivePath, ReadyPath, CheckTimeoutMs

📄 Lisans

Bu proje MIT lisansı altında lisanslanmıştır.

Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  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 was computed.  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.
  • net5.0

    • No dependencies.
  • net6.0

    • No dependencies.
  • net7.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

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.3 134 4/15/2026