Appouse.RequestLogging
1.5.3
dotnet add package Appouse.RequestLogging --version 1.5.3
NuGet\Install-Package Appouse.RequestLogging -Version 1.5.3
<PackageReference Include="Appouse.RequestLogging" Version="1.5.3" />
<PackageVersion Include="Appouse.RequestLogging" Version="1.5.3" />
<PackageReference Include="Appouse.RequestLogging" />
paket add Appouse.RequestLogging --version 1.5.3
#r "nuget: Appouse.RequestLogging, 1.5.3"
#:package Appouse.RequestLogging@1.5.3
#addin nuget:?package=Appouse.RequestLogging&version=1.5.3
#tool nuget:?package=Appouse.RequestLogging&version=1.5.3
Appouse.RequestLogging
HTTP istek/yanıt loglama, korelasyon, aktif istek takibi ve istek iptal yönetimi kütüphanesi.
Özellikler
- 🔍 Request/Response Loglama — Header, body, durum kodu, süre, hata bilgisi
- 🔗 Correlation/Trace — X-Correlation-ID, OpenTelemetry TraceId/SpanId
- 🐳 K8s Desteği — Pod, Namespace, Node, Container bilgileri otomatik
- 📦 Arşivleme — Günlük/aylık/yıllık arşiv tablosu desteği
- 🚫 İstek İptali — Aktif istekleri takip edip dışarıdan cancel edebilme
- 🧩 Pluggable Store — InMemory veya Redis ile aktif istek takibi
- 🌐 Built-in REST Endpoint'ler — Aktif istek listesi ve iptal API'si (controller yazmaya gerek yok)
- ⚡ WebSocket Live Feed — Anlık aktif istek listesi broadcast desteği
- 🔒 Pluggable Authorization — Endpoint erişim kontrolü (IActiveRequestsAuthorizer)
- 🗄️ Çoklu DB — PostgreSQL, SQL Server, MySQL, Oracle
Kurulum
dotnet add package Appouse.RequestLogging
Temel Kullanım
// Program.cs / Startup.cs
var cs = "Host=127.0.0.1;Username=app;Password=***;Database=logs";
var writer = new ChannelLogWriter(new PostgresLogWriter(cs));
services.AddRequestLogging(new RequestLoggingOptions
{
Application = "Portal",
Environment = "Prod",
Writer = writer,
// Properties – opsiyonel provider(lar)
PropertyProviders = { ctx => new[] {
new KeyValuePair<string,string>("appVersion","1.2.3"),
new KeyValuePair<string,string>("region","eu-central")
}},
// Arşivleme
EnableArchiver = true,
ArchiveMode = ArchiveMode.Daily, // Never/Daily/Monthly/Yearly
HotRetention = TimeSpan.FromDays(7), // aktif tabloda 7 gün kalsın
ArchiveInterval = TimeSpan.FromMinutes(5),
ArchiveBatchSize = 5000,
ArchiveStore = new PostgresArchiveStore(cs)
});
// Middleware
app.UseWebSockets(); // WebSocket live feed için gerekli
app.UseRequestLogging();
app.MapRequestLoggingEndpoints(); // Aktif istek REST + WebSocket endpoint'leri
Diğer DB'ler için sadece PostgresLogWriter yerine SqlServerLogWriter / OracleLogWriter / MySqlLogWriter verebilirsiniz.
Aynı şekilde arşivleme tarafında da ilgili ArchiveStore sınıflarını kullanabilirsiniz.
Aktif İstek Takibi ve İptal Yönetimi
Aktif istekleri takip edip dışarıdan (admin panel, API, WebSocket) cancel edebilirsiniz.
TraceIdentifier ile tanımlanan her istek, store'a kaydedilir ve istendiğinde iptal edilebilir.
InMemory (tek instance)
services.AddRequestLogging(new RequestLoggingOptions
{
Application = "MyApp",
Writer = writer,
ActiveRequestStore = new InMemoryActiveRequestStore(),
CancelCheckInterval = TimeSpan.FromSeconds(2)
});
Redis (dağıtık / multi-pod)
var redis = ConnectionMultiplexer.Connect("localhost:6379,abortConnect=false");
services.AddRequestLogging(new RequestLoggingOptions
{
Application = "MyApp",
Writer = writer,
ActiveRequestStore = new RedisActiveRequestStore(redis, ttl: TimeSpan.FromHours(1)),
CancelCheckInterval = TimeSpan.FromSeconds(1)
});
Not: Redis bağlantısı sağlanamasa bile sistem patlamaz. Middleware içinde tüm store çağrıları try/catch ile korunur. Ancak
ConnectionMultiplexer.Connect()anında bağlantı hatası almamak içinabortConnect=falsekullanmanız önerilir.
Built-in Endpoint'ler
MapRequestLoggingEndpoints() çağrıldığında aşağıdaki endpoint'ler otomatik oluşturulur:
| Method | Route | Açıklama |
|---|---|---|
GET |
/request-logging/active-requests |
Aktif istek listesi (JSON) |
POST |
/request-logging/active-requests/cancel |
İstek iptal et |
GET |
/request-logging/active-requests/live |
WebSocket live feed |
Route prefix'i özelleştirilebilir:
app.MapRequestLoggingEndpoints("/api/monitoring");
// → GET /api/monitoring/active-requests
// → POST /api/monitoring/active-requests/cancel
// → GET /api/monitoring/active-requests/live
REST ile Kullanım
# Aktif istekleri listele
curl http://localhost:5000/request-logging/active-requests
# İstek iptal et
curl -X POST http://localhost:5000/request-logging/active-requests/cancel \
-H "Content-Type: application/json" \
-d '{"traceIdentifier": "0HN4ABC123"}'
JSON Response Örneği
[
{
"traceIdentifier": "0HN4ABC123",
"method": "POST",
"path": "/api/orders",
"host": "api.example.com",
"startedAt": "2026-04-13T17:00:00.000Z",
"elapsedMs": 4523,
"application": "OrderService",
"environment": "Production",
"podName": "order-api-7b4f9-xk2m",
"isCancelRequested": false,
"correlationId": "abc-123-def",
"traceId": "d4cda95b652f4a1592b449d5929fda1b"
}
]
WebSocket Live Feed
Frontend'de anlık aktif istek listesi almak için WebSocket bağlantısı kullanabilirsiniz.
Sunucu, WebSocketBroadcastInterval (varsayılan 1 saniye) aralıkla güncel listeyi push eder.
// Opsiyonel: broadcast aralığını ayarla
services.AddRequestLogging(new RequestLoggingOptions
{
// ...
WebSocketBroadcastInterval = TimeSpan.FromSeconds(1)
});
JavaScript Client:
const ws = new WebSocket('ws://localhost:5000/request-logging/active-requests/live');
ws.onmessage = (event) => {
const activeRequests = JSON.parse(event.data);
activeRequests.forEach(req => {
console.log(`${req.method} ${req.path} — ${req.elapsedMs}ms (since ${req.startedAt})`);
});
};
// WebSocket üzerinden iptal tetiklemek:
ws.send('cancel:0HN4ABC123');
Endpoint Yetki Kontrolü (IActiveRequestsAuthorizer)
Endpoint'lere erişimi kısıtlamak için IActiveRequestsAuthorizer implementasyonu verin.
null ise tüm isteklere açık erişim sağlanır (varsayılan).
public class AdminOnlyAuthorizer : IActiveRequestsAuthorizer
{
public Task<bool> AuthorizeAsync(HttpContext context)
{
var isAdmin = context.User.IsInRole("Admin");
return Task.FromResult(isAdmin);
}
}
// Konfigürasyon
services.AddRequestLogging(new RequestLoggingOptions
{
// ...
ActiveRequestsAuthorizer = new AdminOnlyAuthorizer()
});
Yetki reddedildiğinde varsayılan olarak 403 Forbidden döner.
Kendi response'unuzu yazmak isterseniz AuthorizeAsync içinde context.Response kullanabilirsiniz:
public class CustomAuthorizer : IActiveRequestsAuthorizer
{
public async Task<bool> AuthorizeAsync(HttpContext context)
{
if (!context.User.Identity?.IsAuthenticated ?? true)
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("{\"error\":\"Unauthorized\"}");
return false;
}
return context.User.IsInRole("Admin");
}
}
ActiveRequestEntry Alanları
| Alan | Tip | Açıklama |
|---|---|---|
TraceIdentifier |
string | HTTP istek tanımlayıcısı (cancel için anahtar) |
CorrelationId |
string? | X-Correlation-ID |
TraceId / SpanId |
string? | OpenTelemetry izleme kimlikleri |
Scheme |
string? | http / https |
Host / Port |
string? / int? | Hedef host bilgisi |
Method |
string? | HTTP metodu (GET, POST, vb.) |
Path |
string? | İstek yolu |
RouteTemplate |
string? | MVC route pattern (ör: api/users/{id}) |
QueryString |
string? | URL sorgu parametreleri |
RequestContentType |
string? | İçerik tipi |
RequestContentLength |
long? | Body boyutu |
ClientIp |
string? | İstemci IP adresi |
ClientUserAgent |
string? | Tarayıcı / istemci bilgisi |
StartedAt |
DateTimeOffset | İstek başlangıç zamanı |
ElapsedMs |
long | Geçen süre (ms, hesaplanmış) |
Application |
string? | Uygulama adı |
Environment |
string? | Ortam (Prod, Staging, vb.) |
MachineId |
string? | Makine kimliği |
PodName |
string? | Kubernetes pod adı |
IsCancelRequested |
bool | İptal istendi mi? |
CancelRequestedAt |
DateTimeOffset? | İptal istek zamanı |
Nasıl Çalışır?
- İstek geldiğinde middleware
ActiveRequestStore.RegisterAsync()ile kaydeder - Arka planda periyodik olarak (
CancelCheckInterval) cancel kontrolü yapar - Admin REST/WebSocket ile
canceltetiklediğinde sinyal store'a yazılır - Polling döngüsü sinyali yakalar →
CancellationTokeniptal edilir → pipeline durur - Log kaydına
IsCancelled=true,CancelRequestTimeyazılır, HTTP 499 döner - İstek bittiğinde
UnregisterAsync()ile listeden çıkar
Correlation / TraceId
- İstek header'ında
X-Correlation-IDvarsa korunur, yoksa oluşturulup yanıta da eklenir. IHttpClientFactoryile oluşturulan HttpClient'lereCorrelationHandlerotomatik eklenir.- Mikroservisler arası Correlation ID yayılımı otomatiktir.
// IHttpClientFactory ile kullanım (CorrelationHandler otomatik eklenir)
var client = httpClientFactory.CreateClient("MyApiClient");
var response = await client.GetAsync("https://api.hedef.com/endpoint");
Attribute Kullanım Örneği
[LogFlatten]
public class LoginRequest
{
public string UserName { get; set; }
[LogMask("******", keepLast:2)] public string Password { get; set; }
[LogIgnore] public byte[]? AvatarBytes { get; set; }
[LogRename("phone")] public string? PhoneNumber { get; set; }
}
Custom Property Ekleme
RequestLogProperties.Add(HttpContext, "orderId", orderId.ToString());
RequestLogProperties.Add(HttpContext, "featureFlag", flag);
DB Desteği
| Veritabanı | Writer | ArchiveStore |
|---|---|---|
| PostgreSQL | PostgresLogWriter |
PostgresArchiveStore |
| SQL Server | SqlServerLogWriter |
SqlServerArchiveStore |
| MySQL | MySqlLogWriter |
MySqlArchiveStore |
| Oracle | OracleLogWriter |
OracleArchiveStore |
İpuçları
- K8s'de
HOSTNAMEgenelde pod adıdır.KUBERNETES_*env değişkenlerini Downward API ile enjekte edip otomatik toplanır. - Büyük gövde/loglarda sadece hash tutup
*_previewkolonlarını boş bırakabilirsiniz. - Yetki/çerez gibi header'lar
MaskHeadersile otomatik maske edilir. - Performans için writer'ı
ChannelLogWriterile sarmalayın. ActiveRequestStore = nullise aktif istek takibi ve iptal özelliği devre dışıdır (varsayılan).MapRequestLoggingEndpoints()kullanırkenapp.UseWebSockets()pipeline'da önce çağrılmalıdır.ActiveRequestsAuthorizer = nullise endpoint'lere herkes erişebilir; production'da mutlaka yetki kontrolü ekleyin.- Retention için ayrı bir cron job ile
DELETE FROM request_log_archive WHERE timestamp_utc < now() - interval '30 days'benzeri bir temizlik çalıştırın. Log tablosu 7 gün, arşiv tablosu 1 ay tutabilir. Cron job arşiv tablosundan eski kayıtları siler.
Paketleme
# Otomatik versiyon artırım + NuGet paketi oluşturma
.\pack.bat
.\pack.bat # varsayılan: --patch (1.4.2 → 1.4.3)
.\pack.bat --patch # sadece patch (1.4.2 → 1.4.3)
.\pack.bat --minor # sadece minor (1.4.2 → 1.5.2)
.\pack.bat --major # sadece major (1.4.2 → 2.4.2)
.\pack.bat --major --minor # ikisi birden (1.4.2 → 2.5.2)
.\pack.bat --minor --patch # ikisi birden (1.4.2 → 1.5.3)
.\pack.bat --major --minor --patch # hepsi (1.4.2 → 2.5.3)
| 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 was computed. 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 was computed. 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 was computed. 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
- Microsoft.Data.SqlClient (>= 6.1.1)
- MySql.Data (>= 8.4.0)
- Npgsql (>= 7.0.10)
- Oracle.ManagedDataAccess.Core (>= 3.21.4)
- StackExchange.Redis (>= 2.8.24)
-
net6.0
- Microsoft.Data.SqlClient (>= 6.1.1)
- MySql.Data (>= 9.4.0)
- Npgsql (>= 9.0.3)
- Oracle.ManagedDataAccess.Core (>= 3.21.4)
- StackExchange.Redis (>= 2.8.24)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.