AsGuard 0.1.6

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

AsGuard

AsGuard is an ASP.NET Core monitoring package for request logging, exception tracking, host ILogger capture, live Server-Sent Events (SSE) updates, and a built-in dashboard.

It is intended for applications that need practical visibility into HTTP traffic and application warnings/errors without wiring a separate observability platform first.

Features

  • HTTP request and response logging.
  • Request log enrichment (UserId, custom searchable Tags, and structured MetadataJson metadata) via claims, DI-based enrichers, or inline options delegates.
  • Persistent storage with SQL Server, PostgreSQL, SQLite, or in-memory storage.
  • Built-in Razor dashboard.
  • Basic Authentication for the dashboard, API, and SSE stream.
  • Live SSE updates for new request logs and exception/log events.
  • Correlation ID propagation with a configurable header.
  • Request logging scopes that enrich host logs with correlation and request data.
  • Host ILogger capture for warnings and errors by default.
  • Unhandled HTTP exception capture.
  • Manual exception logging through IExceptionLogger.
  • Optional request body capture.
  • Optional response body capture.
  • Content-type allow list for body capture.
  • Body and header truncation limits.
  • Sensitive request/response header redaction.
  • Attribute-based request and response JSON body masking.
  • Path exclusions for health checks, metrics, Swagger, the dashboard, API, and stream.
  • Queue-based background persistence.
  • Configurable queue capacity, batch size, and overflow behavior.
  • Configurable live broadcast queue pressure behavior.
  • Summary-only or full-detail live broadcast payloads.
  • Request and exception detail endpoints.
  • Exception summary counts by severity.
  • Exception trend buckets by hour or day.
  • Log deletion APIs.
  • Retention cleanup worker.
  • Queue pressure, exception spike, persistence failure, and broadcast failure alerts.
  • Custom alert sink support.
  • Runtime monitoring stats endpoint.

Requirements

  • .NET 8, .NET 9, or .NET 10.
  • ASP.NET Core application using WebApplication or IApplicationBuilder.

Installation

Install the package in the host application:

dotnet add package AsGuard

For local development from this repository, pack and install the generated package into your host app:

dotnet pack -c Release
dotnet add package AsGuard --source ./bin/Release

Quick Start

using AsGuard.Domain.RequestLogging;
using AsGuard.Extensions;
using AsGuard.Services;
using Microsoft.Extensions.Logging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRequestLogging(options =>
{
    options.DatabaseProvider = LoggingDatabaseProvider.Sqlite;
    options.ConnectionString = "Data Source=AsGuard.db";

    options.DashboardRoute = "/request-logs-ui";
    options.DashboardUsername = builder.Configuration["AsGuard:DashboardUsername"]!;
    options.DashboardPassword = builder.Configuration["AsGuard:DashboardPassword"]!;

    options.EnableExceptionLogging = true;
    options.CaptureHostLogs = true;
    options.HostLogMinimumLevel = LogLevel.Warning;
});

var app = builder.Build();

// If you use ASP.NET Core exception handling, register it before UseRequestLogging().
app.UseExceptionHandler("/error");

app.UseRequestLogging();

app.MapGet("/demo-warning", (ILogger<Program> logger) =>
{
    logger.LogWarning("This warning is captured by AsGuard.");
    return Results.Ok();
});

app.MapGet("/demo-error", () =>
{
    throw new InvalidOperationException("Unhandled sample error.");
});

app.Run();

Open the dashboard:

/request-logs-ui

The dashboard, API, and SSE stream use HTTP Basic Authentication with DashboardUsername and DashboardPassword.

Middleware Order

Call app.UseRequestLogging() after building the app and before the endpoints you want monitored.

var app = builder.Build();

app.UseExceptionHandler("/error");
app.UseRequestLogging();

app.MapControllers();
app.Run();

UseRequestLogging() adds:

  • Correlation middleware.
  • Logging scope middleware.
  • AsGuard exception capture middleware.
  • Basic Auth middleware for AsGuard surfaces.
  • Request/response logging middleware.
  • Dashboard, API, and SSE endpoint mapping.

Complete Configuration Example

builder.Services.AddRequestLogging(options =>
{
    // Storage
    options.DatabaseProvider = LoggingDatabaseProvider.SqlServer;
    options.ConnectionString = builder.Configuration.GetConnectionString("AsGuard")!;

    // Request queue and persistence
    options.QueueCapacity = 10_000;
    options.QueueOverflowPolicy = QueueOverflowPolicy.DropNewest;
    options.BatchSize = 100;

    // Exception and host ILogger capture
    options.EnableExceptionLogging = true;
    options.ExceptionQueueCapacity = 5_000;
    options.ExceptionQueueOverflowPolicy = QueueOverflowPolicy.DropNewest;
    options.ExceptionBatchSize = 50;
    options.CaptureHostLogs = true;
    options.HostLogMinimumLevel = LogLevel.Warning;
    options.ExcludedHostLogCategoryPrefixes.Add("Microsoft.");
    options.ExcludedHostLogCategoryPrefixes.Add("System.");

    // In-memory store limit
    options.MaxInMemoryEntries = 10_000;

    // Live broadcast (SSE delivery)
    options.BroadcastQueueCapacity = 2_048;
    options.BroadcastOverflowPolicy = BroadcastOverflowPolicy.DropOldest;
    options.BroadcastDetailMode = BroadcastDetailMode.SummaryOnly;

    // Detail APIs
    options.EnableDetailedLogEndpoint = true;

    // Correlation
    options.CorrelationHeaderName = "X-Correlation-ID";

    // Retention
    options.RequestRetentionDays = 30;
    options.ExceptionRetentionDays = 90;
    options.RetentionCleanupInterval = TimeSpan.FromHours(6);

    // Alerts
    options.QueuePressureAlertThreshold = 0.8;
    options.ExceptionSpikeAlertThreshold = 25;
    options.ExceptionSpikeAlertWindow = TimeSpan.FromMinutes(5);
    options.AlertCooldown = TimeSpan.FromMinutes(5);

    // Body capture
    options.LogRequestBody = false;
    options.LogResponseBody = false;
    options.MaxCapturedBodyBytes = 4_096;
    options.LoggableContentTypes =
    [
        "application/json",
        "application/xml",
        "text/",
        "application/x-www-form-urlencoded"
    ];

    // Redaction
    options.SensitiveHeaders.Add("X-Internal-Token");

    // Path exclusions
    options.ExcludedPathPrefixes.Add("/internal");
    options.ExcludedExactPaths.Add("/ready");

    // Dashboard and protected AsGuard endpoints
    options.DashboardRoute = "/request-logs-ui";
    options.DashboardUsername = builder.Configuration["AsGuard:DashboardUsername"]!;
    options.DashboardPassword = builder.Configuration["AsGuard:DashboardPassword"]!;
});

Storage Providers

Use DatabaseProvider to choose where logs are persisted.

Provider Value Connection string
SQL Server LoggingDatabaseProvider.SqlServer Required
PostgreSQL LoggingDatabaseProvider.PostgreSql Required
SQLite LoggingDatabaseProvider.Sqlite Required
In-memory LoggingDatabaseProvider.InMemory Not used

SQL Server

options.DatabaseProvider = LoggingDatabaseProvider.SqlServer;
options.ConnectionString = builder.Configuration.GetConnectionString("AsGuard")!;

PostgreSQL

options.DatabaseProvider = LoggingDatabaseProvider.PostgreSql;
options.ConnectionString = builder.Configuration.GetConnectionString("AsGuard")!;

SQLite

options.DatabaseProvider = LoggingDatabaseProvider.Sqlite;
options.ConnectionString = "Data Source=AsGuard.db";

In-Memory

options.DatabaseProvider = LoggingDatabaseProvider.InMemory;
options.MaxInMemoryEntries = 10_000;

In-memory storage is process-local and is cleared when the application stops.

Dashboard

The dashboard route is controlled by DashboardRoute.

options.DashboardRoute = "/request-logs-ui";
options.DashboardUsername = builder.Configuration["AsGuard:DashboardUsername"]!;
options.DashboardPassword = builder.Configuration["AsGuard:DashboardPassword"]!;

The dashboard supports:

  • Request log browsing.
  • Request details.
  • Exception/log event browsing.
  • Exception/log event details.
  • Severity filtering.
  • Method and status filtering.
  • Search.
  • Correlation ID filtering.
  • UTC date filtering.
  • Summary cards.
  • Live updates.
  • Clearing logs.
  • Light and dark modes.

Dashboard credentials are required when DashboardRoute is enabled. The legacy default credentials admin / admin are rejected at startup.

Host ILogger Capture

AsGuard registers an ILoggerProvider. Host app logs at Warning and above are captured by default and stored with exception/log events.

app.MapGet("/checkout", (ILogger<Program> logger) =>
{
    logger.LogWarning("Payment retry required for order {OrderId}", 123);
    return Results.Ok();
});

Configure the minimum level:

options.CaptureHostLogs = true;
options.HostLogMinimumLevel = LogLevel.Information;

Exclude noisy categories:

options.ExcludedHostLogCategoryPrefixes.Add("Microsoft.");
options.ExcludedHostLogCategoryPrefixes.Add("System.");
options.ExcludedHostLogCategoryPrefixes.Add("MyApp.NoisyWorker");

AsGuard excludes AsGuard. categories by default to avoid capturing its own internal logs.

If your host app calls builder.Logging.ClearProviders(), call it before builder.Services.AddRequestLogging(...). Clearing providers after AddRequestLogging(...) can remove the AsGuard logger provider.

Unhandled Exception Capture

Unhandled HTTP exceptions are captured when EnableExceptionLogging is enabled.

options.EnableExceptionLogging = true;
app.MapGet("/throw", () =>
{
    throw new InvalidOperationException("Captured by AsGuard.");
});

AsGuard rethrows the exception after capturing it, so the host app's normal exception handling still controls the HTTP response.

Manual Exception Logging

Use IExceptionLogger for background jobs, message handlers, scheduled tasks, or exceptions that are handled manually.

app.MapPost("/background-exception", async (IExceptionLogger exceptionLogger) =>
{
    try
    {
        throw new ApplicationException("Manual exception sample.");
    }
    catch (Exception ex)
    {
        await exceptionLogger.LogAsync(
            ex,
            LogLevel.Error,
            new ExceptionLogContext(
                Path: "/background-exception",
                Method: "POST",
                UserId: "user-123",
                Tags: "manual-api",
                MetadataJson: """{"job":"billing-sync"}"""));
    }

    return Results.Ok();
});

ExceptionLogContext supports:

Property Purpose
CorrelationId Existing correlation ID. If omitted, AsGuard uses the current request correlation ID or creates one.
Path Request or operation path.
Method HTTP method or operation verb.
UserId Current user identifier.
ClientIp Client IP address.
RequestId Request identifier.
Tags Searchable labels such as background-job or payment.
MetadataJson Custom JSON metadata.
OccurredOnUtc Override event timestamp.

Request And Response Body Capture

Body capture is disabled by default.

options.LogRequestBody = true;
options.LogResponseBody = true;
options.MaxCapturedBodyBytes = 8_192;

Only configured content types are captured. If LoggableContentTypes is left empty (the default), all content types will be captured:

// Limit body capture to specific content types
options.LoggableContentTypes =
[
    "application/json",
    "text/",
    "application/x-www-form-urlencoded"
];

Unsupported content types are stored as a skipped marker. Captured bodies are truncated when they exceed MaxCapturedBodyBytes.

Use body capture carefully in production. Request and response bodies can contain credentials, tokens, personal data, or regulated data.

Header Redaction

By default, the Set-Cookie response header is always redacted.

Other sensitive headers (such as Authorization, Cookie, or X-Api-Key) are not redacted by default. You should explicitly add them to the SensitiveHeaders collection:

options.SensitiveHeaders.Add("Authorization");
options.SensitiveHeaders.Add("Cookie");
options.SensitiveHeaders.Add("X-Api-Key");
options.SensitiveHeaders.Add("X-Internal-Token");
options.SensitiveHeaders.Add("X-Session-Id");

Set-Cookie response headers are always redacted.

Body Data Masking

You can automatically redact sensitive data (like passwords, tokens, or PII) from captured request and response JSON bodies.

Simply apply the [AsGuardMasked] attribute to the sensitive properties in your models:

using AsGuard.Domain.RequestLogging;

public class LoginRequest
{
    public string Username { get; set; }
    
    [AsGuardMasked]
    public string Password { get; set; }
}

AsGuard scans your assemblies at startup to discover these attributes (respecting [JsonPropertyName]). When it captures a JSON body containing these keys, it automatically replaces their values with "[REDACTED]" before saving the log. The actual response returned to the client is completely unaffected.

You can also manually add keys to be masked via options:

options.SensitiveBodyKeys.Add("creditCardNumber");

Request Log Enrichment

AsGuard supports enriching request logs with additional context, enabling you to extract and store:

  • UserId: The identifier of the logged-in user making the request.
  • Tags: Custom searchable tags (e.g. "api,public,v2").
  • MetadataJson: Structured JSON metadata (e.g. {"tenant":"emea", "clientId":"mobile-app"}).

These fields are persistent, fully searchable via the dashboard/API, and indexable in SQL databases.

1. Default Claims-Based UserId

By default, AsGuard automatically populates the UserId property by searching the request user's claims for common claim types:

  • ClaimTypes.NameIdentifier
  • sub (Subject claim)

If found, these are mapped automatically without any extra configuration.

2. Inline Option-Based Enrichment

For quick and simple enrichment, use the EnrichLog delegate option inside AddRequestLogging:

builder.Services.AddRequestLogging(options =>
{
    options.DatabaseProvider = LoggingDatabaseProvider.Sqlite;
    options.ConnectionString = "Data Source=AsGuard.db";

    options.EnrichLog = (context, log) =>
    {
        // Custom UserId extraction
        if (context.Request.Headers.TryGetValue("X-Client-Id", out var clientId))
        {
            log.UserId = clientId;
        }

        // Add custom searchable tags
        log.Tags = "custom-tag,v2";

        // Add structured custom metadata using the Metadata dictionary
        log.Metadata["region"] = "eu-west-1";
        log.Metadata["environment"] = "production";
    };
});

3. Dependency Injection-Based Enrichment

For more complex enrichment requiring external services (such as looking up database records, caching, or resolving configuration), define an enrichment service by implementing IAsGuardRequestEnricher:

using AsGuard.Domain.RequestLogging;
using AsGuard.Services;
using Microsoft.AspNetCore.Http;

public class TenantRequestEnricher : IAsGuardRequestEnricher
{
    private readonly ITenantService _tenantService;

    public TenantRequestEnricher(ITenantService tenantService)
    {
        _tenantService = tenantService;
    }

    public void Enrich(HttpContext context, RequestLog log)
    {
        var tenantInfo = _tenantService.GetCurrentTenant();
        if (tenantInfo != null)
        {
            log.Tags = string.IsNullOrEmpty(log.Tags) 
                ? tenantInfo.Code 
                : $"{log.Tags},{tenantInfo.Code}";

            // Enrich with custom structured metadata using the Metadata dictionary
            log.Metadata["tenantId"] = tenantInfo.Id;
            log.Metadata["tier"] = tenantInfo.SubscriptionTier;
        }
    }
}

Then, register your enricher in the Dependency Injection container:

builder.Services.AddScoped<IAsGuardRequestEnricher, TenantRequestEnricher>();

Performance Guidance: Log enrichment runs inside the HTTP request middleware pipeline context to ensure all request details (route data, headers, claims) are fully available. Keep all custom enricher operations fast and non-blocking to prevent adding latency to API requests.

Correlation IDs

AsGuard reads and writes the configured correlation header. The default is X-Correlation-ID.

options.CorrelationHeaderName = "X-Correlation-ID";

If the incoming request has a valid correlation ID, AsGuard uses it. Otherwise it creates a new one. The value is assigned to HttpContext.TraceIdentifier and returned on the response header.

Accepted incoming correlation IDs contain only letters, digits, hyphens, and underscores, and must be 128 characters or shorter.

Path Exclusions

AsGuard skips common operational endpoints by default:

  • Prefixes: /health, /swagger, /metrics
  • Exact paths: /health, /metrics, /swagger, /favicon.ico

The dashboard route, /request-logs-api, and /request-logs-stream are also skipped automatically.

Add exclusions:

options.ExcludedPathPrefixes.Add("/internal");
options.ExcludedPathPrefixes.Add("/jobs");
options.ExcludedExactPaths.Add("/ready");

Prefix exclusions are case-insensitive and use path-prefix matching. Exact exclusions are case-insensitive exact matches.

Advanced Sampling & Filtering

By default, AsGuard logs 100% of the non-excluded requests. For high-traffic applications, you can reduce storage and queue pressure by configuring sampling and filtering logic.

// 1. Request Sampling (e.g., log only 10% of traffic)
options.SamplingRate = 0.1;

// 2. Threshold-Based Logging (e.g., log requests taking longer than 500ms)
options.LogRequestsSlowerThan = TimeSpan.FromMilliseconds(500);

// 3. Status Code Specific Logging (e.g., log only 400 and 500 responses)
options.LoggableStatusCodes.Add(400);
options.LoggableStatusCodes.Add(500);

Note: Any request that throws an unhandled exception will always be logged, bypassing these sampling and filtering rules.

Queues And Persistence

AsGuard queues logs in memory and persists them from background workers.

options.QueueCapacity = 10_000;
options.BatchSize = 100;
options.QueueOverflowPolicy = QueueOverflowPolicy.DropNewest;

options.ExceptionQueueCapacity = 5_000;
options.ExceptionBatchSize = 50;
options.ExceptionQueueOverflowPolicy = QueueOverflowPolicy.DropNewest;

Overflow policies:

Policy Behavior
DropNewest Drop the new item when the queue is full.
DropOldest Remove the oldest queued item and enqueue the new item.

Use larger queues for bursty systems. Use smaller queues when memory pressure is more important than retaining every monitoring event.

Live SSE Updates

The SSE stream endpoint is:

/request-logs-stream

The stream uses the same Basic Auth credentials as the dashboard.

Optional groups query parameter:

/request-logs-stream?groups=logs,exceptions

If omitted, both groups are streamed.

SSE payloads are JSON envelopes with:

Field Meaning
method NewLogs or NewExceptions
payload Array of newly persisted request logs or exception/log events

Configure broadcast pressure behavior:

options.BroadcastQueueCapacity = 2_048;
options.BroadcastOverflowPolicy = BroadcastOverflowPolicy.DropOldest;
options.BroadcastDetailMode = BroadcastDetailMode.SummaryOnly;

Broadcast detail modes:

Mode Behavior
SummaryOnly Sends compact live rows without large details.
Full Includes metadata, stack traces, and inner exception data in live events.

Retention Cleanup

Configure automatic deletion of old logs:

options.RequestRetentionDays = 30;
options.ExceptionRetentionDays = 90;
options.RetentionCleanupInterval = TimeSpan.FromHours(6);

Set a retention value to null to disable cleanup for that log type.

Alerts

AsGuard publishes alerts for:

  • Request queue pressure.
  • Exception queue pressure.
  • Exception spikes.
  • Request persistence failures.
  • Exception persistence failures.
  • Live broadcast failures.

Configure alert thresholds:

options.QueuePressureAlertThreshold = 0.8;
options.ExceptionSpikeAlertThreshold = 25;
options.ExceptionSpikeAlertWindow = TimeSpan.FromMinutes(5);
options.AlertCooldown = TimeSpan.FromMinutes(5);

Set QueuePressureAlertThreshold or ExceptionSpikeAlertThreshold to null to disable those alerts.

By default, alerts are written through ILogger.

Custom Alert Sink

Register your own IAsGuardAlertSink after AddRequestLogging to send alerts to email, Slack, Teams, webhooks, or another monitoring system.

builder.Services.AddRequestLogging(options =>
{
    // options...
});

builder.Services.AddSingleton<IAsGuardAlertSink, WebhookAsGuardAlertSink>();
using AsGuard.Services;

public sealed class WebhookAsGuardAlertSink : IAsGuardAlertSink
{
    public async ValueTask PublishAsync(AsGuardAlert alert, CancellationToken cancellationToken)
    {
        // Send alert.Type, alert.Message, alert.Properties, alert.OccurredOnUtc.
        await Task.CompletedTask;
    }
}

API Reference

All API routes are protected by the same Basic Auth credentials as the dashboard.

Get Request Logs

GET /request-logs-api

Query parameters:

Name Type Default Description
PageIndex int 1 1-based page number.
PageSize int 20 Page size from 1 to 100.
Search string Search text.
Method string HTTP method filter.
StatusCode int HTTP status code filter.
FromUtc DateTime Start UTC timestamp filter.
ToUtc DateTime End UTC timestamp filter.
UserId string Filter request logs by user ID.
ExceptionsOnly bool false Return only requests with captured exceptions.
IncludeDetails bool false Include headers, bodies, and stack traces.
SkipTotalCount bool false Skip total-count calculation for faster paging.

Example:

GET /request-logs-api?PageIndex=1&PageSize=20&Method=POST&StatusCode=500

Get Request Log Details

GET /request-logs-api/{id}

Returns full request log details. Disabled when EnableDetailedLogEndpoint is false.

Delete Request Logs

DELETE /request-logs-api

Query parameters:

Name Type Description
FromUtc DateTime Delete logs on or after this UTC timestamp.
ToUtc DateTime Delete logs on or before this UTC timestamp.
Search string Delete matching logs.
Method string Delete by HTTP method.
StatusCode int Delete by HTTP status code.
ExceptionsOnly bool Delete only requests with exceptions.

Calling this endpoint without filters clears the request queue and all persisted request logs.

Get Runtime Stats

GET /request-logs-api/stats

Returns:

  • Request queue depth, enqueued count, and dropped count.
  • Exception queue depth, enqueued count, and dropped count.
  • Persisted request and exception/log event counts.
  • Persistence failure counts.
  • Broadcast failure count.
  • Active SSE connection count (property name remains activeSignalRConnections).

Get Exception And Log Events

GET /request-logs-api/exceptions

This endpoint returns unhandled exceptions, manually logged exceptions, and captured host ILogger events.

Query parameters:

Name Type Default Description
PageIndex int 1 1-based page number.
PageSize int 20 Page size from 1 to 100.
FromUtc DateTime Start UTC timestamp.
ToUtc DateTime End UTC timestamp.
Level LogLevel Trace, Debug, Information, Warning, Error, or Critical.
CorrelationId string Correlation ID filter.
Search string Search text.
IncludeDetails bool false Include stack trace, inner exception, and metadata.
SkipTotalCount bool false Skip total-count calculation for faster paging.

Example:

GET /request-logs-api/exceptions?Level=Warning&PageSize=50

Get Exception Or Log Event Details

GET /request-logs-api/exceptions/{id}

Returns full exception/log event details. Disabled when EnableDetailedLogEndpoint is false.

Get Exception Summary

GET /request-logs-api/exceptions/summary

Query parameters:

Name Type Description
FromUtc DateTime Start UTC timestamp.
ToUtc DateTime End UTC timestamp.

Returns total, critical, error, warning, information, debug, and trace counts.

GET /request-logs-api/exceptions/trends

Query parameters:

Name Type Default Description
FromUtc DateTime Start UTC timestamp.
ToUtc DateTime End UTC timestamp.
Interval string hour hour or day.

Delete Exception And Log Events

DELETE /request-logs-api/exceptions

Query parameters:

Name Type Description
FromUtc DateTime Delete events on or after this UTC timestamp.
ToUtc DateTime Delete events on or before this UTC timestamp.
Level LogLevel Delete by severity.
CorrelationId string Delete by correlation ID.
Search string Delete matching events.

Calling this endpoint without filters clears the exception queue and all persisted exception/log events.

Options Reference

Option Default Description
DatabaseProvider SqlServer Storage provider.
ConnectionString "" Connection string for SQL Server, PostgreSQL, or SQLite.
QueueCapacity 10_000 Request log queue capacity.
QueueOverflowPolicy DropNewest Request queue overflow behavior.
BatchSize 100 Request log persistence batch size.
EnableExceptionLogging true Enables exception/log event persistence.
ExceptionQueueCapacity 5_000 Exception/log event queue capacity.
ExceptionQueueOverflowPolicy DropNewest Exception queue overflow behavior.
ExceptionBatchSize 50 Exception/log event persistence batch size.
MaxInMemoryEntries 10_000 Maximum retained rows for in-memory stores.
BroadcastQueueCapacity 2_048 Live broadcast queue capacity.
BroadcastOverflowPolicy DropOldest Broadcast queue overflow behavior.
BroadcastDetailMode SummaryOnly Live payload detail level for SSE events.
EnableDetailedLogEndpoint true Enables detail endpoints.
CaptureHostLogs true Captures host ILogger events.
HostLogMinimumLevel Warning Minimum host ILogger level captured.
ExcludedHostLogCategoryPrefixes AsGuard. Host logger categories excluded from capture.
CorrelationHeaderName X-Correlation-ID Incoming/outgoing correlation header.
RequestRetentionDays null Request log retention period.
ExceptionRetentionDays null Exception/log event retention period.
RetentionCleanupInterval 6 hours Cleanup worker interval.
QueuePressureAlertThreshold 0.8 Queue depth ratio for pressure alerts.
ExceptionSpikeAlertThreshold null Event count that triggers spike alerts.
ExceptionSpikeAlertWindow 5 minutes Spike alert rolling window.
AlertCooldown 5 minutes Minimum time between repeated alerts of the same type.
MaxCapturedBodyBytes 4_096 Maximum captured body/header characters before truncation.
LogRequestBody false Captures request bodies.
LogResponseBody false Captures response bodies.
ExcludedPathPrefixes /health, /swagger, /metrics Case-insensitive path prefixes skipped by request logging.
ExcludedExactPaths /health, /metrics, /swagger, /favicon.ico Case-insensitive exact paths skipped by request logging.
LoggableContentTypes empty Content types eligible for body capture. If empty (default), all content types are captured.
SensitiveHeaders empty Headers redacted from request/response logs. The Set-Cookie header is always redacted.
SensitiveBodyKeys empty JSON keys whose values should be redacted in request/response bodies.
SamplingRate null Sample rate for request logging (0.0 to 1.0). Null means 100% logged.
LogRequestsSlowerThan null Only requests slower than this threshold are logged.
LoggableStatusCodes empty If populated, only these HTTP status codes will be logged.
DashboardRoute /request-logs-ui Dashboard route. Empty disables dashboard route mapping.
DashboardUsername "" Basic Auth username.
DashboardPassword "" Basic Auth password.

Production Notes

  • Store dashboard credentials in configuration, user secrets, environment variables, or your production secret store.
  • Do not use admin / admin; AsGuard rejects those credentials.
  • Keep request and response body capture disabled unless you have reviewed privacy and security requirements.
  • Add custom sensitive headers before enabling body/header capture in production.
  • Use persistent storage for production. In-memory storage is for development, tests, and short-lived diagnostics.
  • Size queue capacities based on traffic bursts and available memory.
  • Exclude high-volume endpoints such as health checks, metrics, and static assets.
  • If the host app clears logging providers, do it before AddRequestLogging.

Troubleshooting

ILogger.LogWarning does not show in the dashboard

Check:

  • CaptureHostLogs is true.
  • HostLogMinimumLevel is Warning or lower.
  • The logger category is not excluded by ExcludedHostLogCategoryPrefixes.
  • The host app did not call builder.Logging.ClearProviders() after AddRequestLogging.
  • EnableExceptionLogging is true, because host logs use the exception/log event pipeline.

Dashboard returns 401

Check:

  • DashboardUsername and DashboardPassword are configured.
  • The request sends HTTP Basic Authentication.
  • The credentials are not admin / admin.

Request or response bodies are missing

Check:

  • LogRequestBody or LogResponseBody is enabled.
  • The request/response content type starts with a value in LoggableContentTypes.
  • The body was not empty.
  • The captured text was not truncated by MaxCapturedBodyBytes.

Logs are being dropped

Check:

  • /request-logs-api/stats for queue depth and dropped counts.
  • Increase QueueCapacity or ExceptionQueueCapacity.
  • Increase persistence throughput by tuning BatchSize or ExceptionBatchSize.
  • Review storage latency and connection string health.
Product Compatible and additional computed target framework versions.
.NET 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.