<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mahmood Al Sarraj</title>
    <description>The latest articles on DEV Community by Mahmood Al Sarraj (@mahmood-alsarraj).</description>
    <link>https://dev.to/mahmood-alsarraj</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3946589%2F3bb3060e-112c-486a-9c8f-169c67dc4b9d.png</url>
      <title>DEV Community: Mahmood Al Sarraj</title>
      <link>https://dev.to/mahmood-alsarraj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mahmood-alsarraj"/>
    <language>en</language>
    <item>
      <title>Stop Flying Blind in Production: Add a Live Observability Dashboard to Your ASP.NET Core App in 5 Minutes</title>
      <dc:creator>Mahmood Al Sarraj</dc:creator>
      <pubDate>Wed, 27 May 2026 21:59:23 +0000</pubDate>
      <link>https://dev.to/mahmood-alsarraj/stop-flying-blind-in-production-add-a-live-observability-dashboard-to-your-aspnet-core-app-in-5-3i19</link>
      <guid>https://dev.to/mahmood-alsarraj/stop-flying-blind-in-production-add-a-live-observability-dashboard-to-your-aspnet-core-app-in-5-3i19</guid>
      <description>&lt;p&gt;&lt;em&gt;No Grafana. No Datadog. No YAML. Just visibility.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;You've shipped your ASP.NET Core API. It's live. And then your product manager pings you: &lt;em&gt;"Something seems slow — can you check?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You open the logs. Wall of text. No correlation IDs. No timing. No idea which request threw that exception at 2 AM.&lt;/p&gt;

&lt;p&gt;Sound familiar?&lt;/p&gt;

&lt;p&gt;That's the problem &lt;strong&gt;AsGuard&lt;/strong&gt; solves.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is AsGuard?
&lt;/h2&gt;

&lt;p&gt;AsGuard is a lightweight NuGet package that plugs directly into your ASP.NET Core middleware pipeline and gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full HTTP request/response logging&lt;/strong&gt; with timing, method, status, and body capture&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exception tracking&lt;/strong&gt; with stack traces, severity, and trends — no Sentry account required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Host &lt;code&gt;ILogger&lt;/code&gt; capture&lt;/strong&gt; — your existing &lt;code&gt;LogWarning&lt;/code&gt; and &lt;code&gt;LogError&lt;/code&gt; calls get stored and searchable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A built-in live dashboard&lt;/strong&gt; with dark/light mode, SSE-powered real-time updates, and filtering&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APM trace timelines&lt;/strong&gt; — auto-tracks EF Core queries and &lt;code&gt;HttpClient&lt;/code&gt; calls with Gantt charts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alerting&lt;/strong&gt; for queue pressure, exception spikes, and persistence failures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sensitive data masking&lt;/strong&gt; via &lt;code&gt;[AsGuardMasked]&lt;/code&gt; attributes and configurable header redaction&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The entire thing runs inside your app. No external services. No Docker compose file with six containers. No licensing tiers. Just a NuGet package and four lines of configuration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting It Running (For Real, Under 5 Minutes)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1 — Install the package
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package AsGuard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 — Configure in &lt;code&gt;Program.cs&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;AsGuard.Extensions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;AsGuard.Domain.RequestLogging&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRequestLogging&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DatabaseProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LoggingDatabaseProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sqlite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConnectionString&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Data Source=asguard.db"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DashboardRoute&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/logs"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DashboardUsername&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"AsGuard:Username"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DashboardPassword&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"AsGuard:Password"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="s"&gt;"change-me"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableExceptionLogging&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CaptureHostLogs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3 — Register the middleware
&lt;/h3&gt;

&lt;p&gt;The placement matters. Add &lt;code&gt;UseRequestLogging()&lt;/code&gt; after HTTPS/CORS but &lt;em&gt;before&lt;/em&gt; auth and your endpoints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseHttpsRedirection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseRequestLogging&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ← right here&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthentication&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4 — Hit the dashboard
&lt;/h3&gt;

&lt;p&gt;Run your app, open a browser, and navigate to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://localhost:&amp;lt;port&amp;gt;/logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbd3muqwcw59uw0nct6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbd3muqwcw59uw0nct6c.png" alt="AsGuard Dashboard" width="799" height="623"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter your credentials and you'll see a live dashboard with every request your app has handled. That's it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Middleware Order Actually Matters
&lt;/h2&gt;

&lt;p&gt;One gotcha worth knowing upfront: where you place &lt;code&gt;UseRequestLogging()&lt;/code&gt; in the pipeline determines what gets captured.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[HTTP Request In]
       │
       ▼
┌──────────────────────┐
│ Exception Handler    │  ← register first so AsGuard can intercept exceptions
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│ HTTPS / CORS / HSTS  │
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│  UseRequestLogging() │  ← HERE: correlation IDs generated, body stream opened
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│  Auth &amp;amp; Authorization│  ← 401s and 403s will still be logged
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│  Your Endpoints      │
└──────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Placing it after auth means you lose logs for unauthorized requests. Placing it before exception handlers means unhandled exceptions won't have their HTTP context correctly linked. The order shown above gets you everything.&lt;/p&gt;




&lt;h2&gt;
  
  
  Choosing a Database
&lt;/h2&gt;

&lt;p&gt;AsGuard supports four providers out of the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; — zero setup, file-based; perfect for local dev, small apps, and quick demos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQL Server&lt;/strong&gt; — the natural fit for production on Azure or Windows-hosted workloads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL&lt;/strong&gt; — ideal for Linux environments and cloud-native stacks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In-Memory&lt;/strong&gt; — no persistence, no config; great for integration tests and ephemeral environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Switching is one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// PostgreSQL&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DatabaseProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LoggingDatabaseProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PostgreSql&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConnectionString&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Host=localhost;Database=asguard;Username=postgres;Password=pass"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// In-Memory (no persistence, great for tests)&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DatabaseProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LoggingDatabaseProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InMemory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MaxInMemoryEntries&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No migrations to run manually. AsGuard auto-creates its tables on startup.&lt;/p&gt;




&lt;h2&gt;
  
  
  Masking Sensitive Data
&lt;/h2&gt;

&lt;p&gt;If you capture request bodies (and you should, for debugging), you don't want passwords or card numbers showing up in your log viewer. AsGuard gives you two ways to handle this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per-property attribute:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginRequest&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Username&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AsGuardMasked&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Password&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// stored as "[REDACTED]"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Global key list in config:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SensitiveBodyKeys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"creditCardNumber"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SensitiveBodyKeys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ssn"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SensitiveBodyKeys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"token"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs at the middleware level before anything hits the database — you're never storing what you shouldn't.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You'll Actually Use It For
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Debugging slow requests in development
&lt;/h3&gt;

&lt;p&gt;The request log view shows method, path, status code, and duration for every call. You can filter by status, search by path, and click into any row to see the full request/response bodies, headers, and the correlation ID chain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tracking down production exceptions
&lt;/h3&gt;

&lt;p&gt;Exception logging captures the full stack trace, the HTTP context it occurred in, the severity, and when it happened. The dashboard includes trend charts so you can see if your error rate just spiked after a deploy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Capturing &lt;code&gt;ILogger&lt;/code&gt; output
&lt;/h3&gt;

&lt;p&gt;With &lt;code&gt;CaptureHostLogs = true&lt;/code&gt;, any &lt;code&gt;LogWarning&lt;/code&gt; or &lt;code&gt;LogError&lt;/code&gt; your existing services emit gets stored alongside the HTTP logs. You don't need to change a single line of your existing logging code — AsGuard just intercepts the host &lt;code&gt;ILogger&lt;/code&gt; pipeline.&lt;/p&gt;

&lt;h3&gt;
  
  
  APM for EF Core and HttpClient
&lt;/h3&gt;

&lt;p&gt;AsGuard auto-instruments EF Core queries and outbound &lt;code&gt;HttpClient&lt;/code&gt; calls, showing them as Gantt-style trace timelines per request. If one endpoint is slow because it's firing 12 database queries, you'll see exactly which ones and how long each took.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdsgnyshz7imko67pvkit.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdsgnyshz7imko67pvkit.png" alt="Request Details — APM" width="728" height="835"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Seeing what's live, right now
&lt;/h3&gt;

&lt;p&gt;The dashboard uses Server-Sent Events for real-time updates — no page refresh, no polling interval to configure. While you're load testing or manually poking an endpoint, the request log updates in front of you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Production Notes
&lt;/h2&gt;

&lt;p&gt;A few things to know before deploying:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Change the default credentials.&lt;/strong&gt; AsGuard actively rejects the literal string &lt;code&gt;"admin"&lt;/code&gt; as a username. Store credentials in environment variables or user secrets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# environment variable approach&lt;/span&gt;
&lt;span class="nv"&gt;ASGUARD__USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_secure_user
&lt;span class="nv"&gt;ASGUARD__PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_secure_password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The write path is non-blocking.&lt;/strong&gt; AsGuard uses a queue-based architecture — logs are written to an in-process channel and flushed asynchronously. Your API response times are not affected by database write latency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Set up retention policies.&lt;/strong&gt; For high-traffic apps, configure auto-cleanup so the log table doesn't grow unbounded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RetentionDays&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;SQLite is fine for low-to-medium traffic.&lt;/strong&gt; For anything handling hundreds of requests per second in production, switch to PostgreSQL or SQL Server.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;Most .NET teams reach for Sentry for exceptions, Datadog or Azure Monitor for metrics, and a custom Kibana setup for logs. That's three services, three SDKs, three dashboards, and three monthly bills.&lt;/p&gt;

&lt;p&gt;AsGuard doesn't replace that stack for large-scale production systems. But for the majority of apps — internal tools, SaaS products under 100k requests/day, staging environments, side projects — it gives you 80% of the observability value at 0% of the infrastructure overhead.&lt;/p&gt;

&lt;p&gt;Install it in your existing app today and you'll have a searchable, live view of every request and exception by the time your coffee's ready.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/mahmood-alsarraj/asguard" rel="noopener noreferrer"&gt;mahmood-alsarraj/asguard&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NuGet:&lt;/strong&gt; &lt;code&gt;dotnet add package AsGuard&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If this saved you a debugging session, give the repo a star — it helps.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>aspnetcore</category>
      <category>devops</category>
      <category>obervability</category>
    </item>
    <item>
      <title>ASP.NET Core Request &amp; Exception Logging with a Built-In Dashboard</title>
      <dc:creator>Mahmood Al Sarraj</dc:creator>
      <pubDate>Fri, 22 May 2026 18:39:32 +0000</pubDate>
      <link>https://dev.to/mahmood-alsarraj/aspnet-core-request-exception-logging-with-a-built-in-dashboard-3pbc</link>
      <guid>https://dev.to/mahmood-alsarraj/aspnet-core-request-exception-logging-with-a-built-in-dashboard-3pbc</guid>
      <description>&lt;p&gt;Most ASP.NET Core logging setups tell you &lt;em&gt;that&lt;/em&gt; something failed — but not what actually happened during the request lifecycle.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://www.nuget.org/packages/AsGuard/" rel="noopener noreferrer"&gt;AsGuard&lt;/a&gt; to provide lightweight request + exception logging with a built-in dashboard and minimal setup.&lt;/p&gt;

&lt;p&gt;GitHub Repository:&lt;br&gt;
&lt;a href="https://github.com/mahmood-alsarraj/asguard" rel="noopener noreferrer"&gt;https://github.com/mahmood-alsarraj/asguard&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Why AsGuard?
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;centralized request + exception visibility&lt;/li&gt;
&lt;li&gt;built-in dashboard&lt;/li&gt;
&lt;li&gt;minimal setup&lt;/li&gt;
&lt;li&gt;easier inspection during debugging&lt;/li&gt;
&lt;li&gt;lightweight integration&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🚀 &lt;strong&gt;Queue-based persistence&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Non-blocking async writes - your API never waits for database&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📊 &lt;strong&gt;Built-in dashboard&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Beautiful Razor UI with dark/light mode and live updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔒 &lt;strong&gt;Sensitive data masking&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;[AsGuardMasked]&lt;/code&gt; attribute + configurable header redaction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📝 &lt;strong&gt;Body capture&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Request/response bodies with content-type allowlist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔗 &lt;strong&gt;Correlation IDs&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Distributed tracing with configurable headers (default: &lt;code&gt;X-Correlation-ID&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⚡ &lt;strong&gt;Live SSE updates&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Real-time push notifications without SignalR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🗄️ &lt;strong&gt;Multiple databases&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;SQL Server, PostgreSQL, SQLite, or In-Memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📈 &lt;strong&gt;Exception analytics&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Trends, severity summaries, and configurable alerts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🎯 &lt;strong&gt;Host ILogger capture&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Automatically captures &lt;code&gt;ILogger&amp;lt;T&amp;gt;&lt;/code&gt; warnings/errors&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔔 &lt;strong&gt;Alerting system&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Queue pressure, exception spikes, persistence failures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📡 &lt;strong&gt;REST API&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Full programmatic access to logs and stats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🧹 &lt;strong&gt;Retention policies&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Auto-cleanup with configurable intervals&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nglnhbnerpfex3dwrh8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nglnhbnerpfex3dwrh8.png" alt=" " width="800" height="1120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Quick Setup
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="k"&gt;add&lt;/span&gt; &lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="n"&gt;AsGuard&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRequestLogging&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DatabaseProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LoggingDatabaseProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sqlite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConnectionString&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Data Source=AsGuard.db"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DashboardRoute&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/request-logs-ui"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DashboardUsername&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DashboardPassword&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"admin123"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableExceptionLogging&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogRequestBody&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogResponseBody&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/error"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// After the exception handler&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseRequestLogging&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to &lt;strong&gt;"/request-logs-ui"&lt;/strong&gt;, enter your credentials, and watch your application’s heartbeat in real-time.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;Modern applications need visibility.&lt;/p&gt;

&lt;p&gt;Sometimes you don’t need a massive observability platform — you just need a fast and practical way to inspect requests and exceptions.&lt;/p&gt;

&lt;p&gt;That’s the problem AsGuard aims to solve for ASP.NET Core developers.&lt;/p&gt;

&lt;h1&gt;
  
  
  Resources:
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;a href="https://www.nuget.org/packages/AsGuard" rel="noopener noreferrer"&gt;NuGet&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📚 &lt;a href="https://github.com/mahmood-alsarraj/AsGuard" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐛 &lt;a href="https://github.com/mahmood-alsarraj/AsGuard/issues" rel="noopener noreferrer"&gt;Issues&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⭐ Star the repo if AsGuard helps you!&lt;/p&gt;

</description>
      <category>dotnetcore</category>
      <category>aspnetcore</category>
      <category>logging</category>
      <category>observability</category>
    </item>
  </channel>
</rss>
