ASP.NET Core  

Unified Logging and Diagnostics in ASP.NET Core

Modern web applications need more than just features — they need visibility. Without proper logging and diagnostics, identifying failures, understanding user behavior, and measuring system health becomes nearly impossible. ASP.NET Core provides a unified logging and diagnostics system that brings consistency, performance, and extensibility into application monitoring.

The goal of unified logging is simple: log once in your application and route the log output anywhere — console, files, cloud services, databases, or observability platforms — without changing your application code.

ilogger-diagram

Why Logging Matters in Production

Logging is essential for:

  • Diagnosing production issues

  • Auditing user actions

  • Monitoring health and uptime

  • Performance analysis

  • Tracing failures

  • Debugging live systems

  • Security analysis

Without logging, you’re blind.

Logging Architecture in ASP.NET Core

ASP.NET Core uses a provider-based logging architecture. You write logs using ILogger, and the framework sends those logs to multiple logging providers such as:

  • Console

  • Debug window

  • Event Viewer

  • File-based logs (Serilog, NLog)

  • Cloud providers (Azure App Insights, AWS CloudWatch)

  • Centralized log systems (ELK, Datadog)

Basic Logging Example

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;

    public HomeController(ILogger<HomeController> logger)
    {
        _logger = logger;
    }

    public IActionResult Index()
    {
        _logger.LogInformation("Home page accessed");
        return View();
    }
}

ASP.NET Core automatically injects ILogger<T> via dependency injection.

Log Severity Levels

ASP.NET Core supports standard log levels:

LevelPurpose
TraceDetailed debugging
DebugDeveloper diagnostics
InformationNormal events
WarningUnexpected but handled
ErrorFailures
CriticalApplication crash

Example:

_logger.LogError("Payment failed for UserId: {UserId}", userId);

Structured Logging

Instead of writing plain strings, ASP.NET Core promotes structured logging, allowing logs to contain key-value data.

_logger.LogInformation("Order {OrderId} processed for {Customer}", orderId, customerName);

This produces searchable and filterable logs in centralized systems.

Configuring Logging in appsettings.json

{"Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }}}

Change log level without redeploying your app.

Logging Providers

Console Logging

Enabled by default:

builder.Logging.ClearProviders();
builder.Logging.AddConsole();

Debug Output

builder.Logging.AddDebug();

File Logging (Using Serilog)

Install:

dotnet add package Serilog.AspNetCore

Configure:

builder.Host.UseSerilog((ctx, config) =>
{
    config.WriteTo.File("logs/app.log");
});

Middleware-Based Logging

Log every incoming request:

app.Use(async (context, next) =>
{
    var logger = context.RequestServices
                        .GetRequiredService<ILogger<Program>>();

    logger.LogInformation("Request: {method} {url}",
        context.Request.Method, context.Request.Path);

    await next();
});

Centralized Exception Logging

Global error handling:

app.UseExceptionHandler(errorApp =>
{
    errorApp.Run(async context =>
    {
        var exception = context.Features.Get<IExceptionHandlerFeature>()?.Error;
        var logger = context.RequestServices.GetRequiredService<ILogger<Program>>();

        logger.LogError(exception, "Unhandled exception");
        await context.Response.WriteAsync("Something went wrong");
    });
});

Diagnostic Tools

ASP.NET Core provides advanced diagnostic tools:

Built-In Metrics

Use .NET counters:

dotnet counters monitor

Health Checks

builder.Services.AddHealthChecks();

app.MapHealthChecks("/health");

Distributed Tracing

Logs alone are not enough in microservices. ASP.NET Core supports distributed tracing.

OpenTelemetry Example

builder.Services.AddOpenTelemetryTracing(builder =>
{
    builder.AddAspNetCoreInstrumentation()
           .AddHttpClientInstrumentation()
           .AddJaegerExporter();
});

Traces flow across services.

Application Insights (Azure)

builder.Services.AddApplicationInsightsTelemetry();

Instant visibility into:

  • Errors

  • Performance

  • Dependencies

  • CPU / memory usage

  • Request flow

Correlation IDs

Trace requests across systems:

app.Use(async (context, next) =>
{
    var correlationId = Guid.NewGuid().ToString();
    context.Items["CID"] = correlationId;

    var logger = context.RequestServices.GetRequiredService<ILogger<Program>>();
    logger.LogInformation("CorrelationId: {CID}", correlationId);

    await next();
});

Diagnostics with Activity API

using System.Diagnostics;

var activity = new Activity("DatabaseCall");
activity.Start();

// perform work

activity.Stop();

Logging Best Practices

✅ Never log secrets
✅ Always use structured logging
✅ Log exceptions with stack trace
✅ Use correlation IDs
✅ Enable metrics
✅ Centralize log storage
✅ Set log level per environment
✅ Avoid excessive logging
✅ Automate alerting

Logging Strategy in SaaS

Production SaaS systems log:

  • Authentication events

  • Business transactions

  • API calls

  • Invoices

  • Performance metrics

  • Abuse attempts

Modern SaaS systems combine:

  • Logs + Metrics + Traces = Observability

Performance Considerations

Keep logging efficient:

  • Avoid logging large objects

  • Do not log in tight loops

  • Prefer async logging

  • Use sampling

  • Use centralized logging system

Conclusion

Unified logging and diagnostics in ASP.NET Core is one of its strongest enterprise features. It gives developers a single logging abstraction that works across all environments and platforms.

With proper logging, you can:

  • Predict failures

  • Debug faster

  • Scale confidently

  • Maintain visibility

  • Improve reliability

If your application has users, traffic, and data — logging is not optional. It is infrastructure, just as important as code.