Appouse.Probes
1.0.3
dotnet add package Appouse.Probes --version 1.0.3
NuGet\Install-Package Appouse.Probes -Version 1.0.3
<PackageReference Include="Appouse.Probes" Version="1.0.3" />
<PackageVersion Include="Appouse.Probes" Version="1.0.3" />
<PackageReference Include="Appouse.Probes" />
paket add Appouse.Probes --version 1.0.3
#r "nuget: Appouse.Probes, 1.0.3"
#:package Appouse.Probes@1.0.3
#addin nuget:?package=Appouse.Probes&version=1.0.3
#tool nuget:?package=Appouse.Probes&version=1.0.3
Appouse.Probes
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
livenessProbevereadinessProbedesteği - 🔌 Pluggable Check Sistemi —
IProbeCheckarayüzü ile özel kontroller yazabilme - 🔀 Çoklu Probe Tipi — Tek bir check'i aynı anda hem
LivehemReadyprobe'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-Target —
net5.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:
- Check otomatik olarak iptal edilir (
OperationCanceledException) - Sonuç Unhealthy olarak işaretlenir
- Açıklama:
"Timed out after {CheckTimeoutMs}ms"şeklinde log'lanır - Diğer check'ler etkilenmez — çalışmaya devam eder
{
"Probes": {
"CheckTimeoutMs": 3000
}
}
⚡ İpucu:
CheckAsyncimplementasyonunuzdacancellationTokenparametresini 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 | Versions 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. |
-
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 |