Appouse.RequestLogging 1.5.3

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

Appouse.RequestLogging

NuGet

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çin abortConnect=false kullanmanı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?

  1. İstek geldiğinde middleware ActiveRequestStore.RegisterAsync() ile kaydeder
  2. Arka planda periyodik olarak (CancelCheckInterval) cancel kontrolü yapar
  3. Admin REST/WebSocket ile cancel tetiklediğinde sinyal store'a yazılır
  4. Polling döngüsü sinyali yakalar → CancellationToken iptal edilir → pipeline durur
  5. Log kaydına IsCancelled=true, CancelRequestTime yazılır, HTTP 499 döner
  6. İstek bittiğinde UnregisterAsync() ile listeden çıkar

Correlation / TraceId

  • İstek header'ında X-Correlation-ID varsa korunur, yoksa oluşturulup yanıta da eklenir.
  • IHttpClientFactory ile oluşturulan HttpClient'lere CorrelationHandler otomatik 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 HOSTNAME genelde 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 *_preview kolonlarını boş bırakabilirsiniz.
  • Yetki/çerez gibi header'lar MaskHeaders ile otomatik maske edilir.
  • Performans için writer'ı ChannelLogWriter ile sarmalayın.
  • ActiveRequestStore = null ise aktif istek takibi ve iptal özelliği devre dışıdır (varsayılan).
  • MapRequestLoggingEndpoints() kullanırken app.UseWebSockets() pipeline'da önce çağrılmalıdır.
  • ActiveRequestsAuthorizer = null ise 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 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. 
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.5.3 129 4/13/2026
1.4.3 121 4/11/2026