DEV Community

Cover image for Proper Logging in ASP.NET Core
Mo
Mo

Posted on

1 1 1

Proper Logging in ASP.NET Core

Hey there, fellow code warriors! πŸ‘‹ Today, we're diving deep into proper logging in ASP.NET Core. If you've ever found yourself lost in a sea of mysterious bugs or scratching your head over your application's behaviour, this guide is your lighthouse! 🏝️

Logging details

Why Logging Matters πŸ€”

Before we jump into the code, let's talk about why logging is the unsung hero of software development. Proper logging is like giving your future self (and your team) a roadmap to understand what's happening in your application. It's not just about catching errors; it's about gaining insights, improving performance, and making your development life easier.

Here's why logging is crucial for your projects:

  1. Application Behavior Monitoring: It's like having a 24/7 surveillance camera on your code.
  2. Event Capturing: Every important moment in your app's life, documented.
  3. Performance Insights: Because sometimes, your app needs a health check.

But logging isn't just about writing stuff down. It's part of a trio of concepts that make your applications robust, maintainable, and scalable:

The Holy Trinity of Application Observability πŸ› οΈ

  1. Logging: Your app's diary πŸ“”

    • Records events, errors, and important information
    • Helps debug issues quickly
    • Provides insights into application behaviour
  2. Traceability: Following the breadcrumbs of your code 🍞

    • Tracks the flow of application processes
    • Follows the lifecycle of requests or commands
    • Especially helpful for distributed systems or microservices
    • Facilitates debugging and enhances reliability
  3. Metrics: Measuring what matters πŸ“Š

    • Provides measurable data about application performance
    • Helps make data-driven decisions
    • Enhances user experiences through targeted optimizations

logging is a hero

Implementing Logging with Serilog in ASP.NET Core πŸ› οΈ

Let's roll up our sleeves and get our hands dirty with some code! We'll be using Serilog, a powerful logging library for .NET.

Setting Up Serilog

First, add the Serilog.AspNetCore NuGet package to your project. If you're planning to use Azure Application Insights, grab Serilog.Sinks.AzureApp too.

In your Program.cs, set up Serilog like this:

builder.Logging.ClearProviders();
builder.Host.UseSerilog(((context, configuration) => 
    configuration.ReadFrom.Configuration(context.Configuration)));
Enter fullscreen mode Exit fullscreen mode

This code clears any existing logging providers and tells Serilog to read its configuration from the appsettings.json file.

Configuring Serilog

In your appsettings.json, you can configure Serilog like a boss:

{
    "Serilog": {
    "Using": [
      "Serilog.Sinks.Console",
      "Serilog.Sinks.File"
    ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
          "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
        }
      },
      {
        "Name": "File",
        "Args": {
          "path": "Logs/log-.txt",
          "rollingInterval": "Day",
          "rollOnFileSizeLimit": true,
          "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}",
          "fileSizeLimitBytes": 1073741824
        }
      },
      {
        "Name": "AzureApp",
        "Args": {
          "instrumentationKey": "your_instrumentation_key"
        }
      }
    ],
    "Enrich": [
      "FromLogContext",
      "WithMachineName",
      "WithThreadId"
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

This configuration sets up Serilog to:

  • Use both console and file sinks
  • Set default log levels (Information for production, Debug for development)
  • Write logs to the console and a file
  • Send logs to Azure Application Insights

Logging in Action: GlobalExceptionHandler 🎭

Our GlobalExceptionHandler class is like a superhero for exceptions. It catches them, logs them, and sends back a nicely formatted response to the user.

public async ValueTask TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
{
    // ... (exception handling logic)

    _logger.LogError(exception, "An error occurred while processing the request {DateTime} {Path}", 
        DateTime.UtcNow, httpContext.Request.Path);

    // ... (return problem details)
}
Enter fullscreen mode Exit fullscreen mode

This class inherits from IExceptionHandler and is registered in our dependency injection setup. It formats errors based on their type and logs them in a structured way before returning a user-friendly response.

Request Logging with LoggingBehaviour πŸ•΅οΈ

The LoggingBehaviour class is our secret agent, tracking every request that passes through our application.

public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken)
{
    Stopwatch stopWatch = Stopwatch.StartNew();
    logger.LogInformation("Handling request {Name}, {DateTime} ", request.GetType().Name, DateTime.UtcNow);

    // ... (request handling)

    if (stopWatch.ElapsedMilliseconds > SlowRequestThresholdMilliseconds)
    {
        logger.LogWarning("Request took too long to handle {Name}, {DateTime}, {ElapsedMilliseconds}ms", 
            request.GetType().Name, DateTime.UtcNow, stopWatch.ElapsedMilliseconds);
    }

    if (result.IsSuccess)
    {
        logger.LogInformation("Request handled successfully {Name}, {DateTime}", request.GetType().Name, DateTime.UtcNow);
    }
    else
    {
        logger.LogError("Request failed to handle {Name}, {DateTime}, {@Error}", request.GetType().Name, DateTime.UtcNow, result.Errors);
    }

    // ... (log success or failure)
}
Enter fullscreen mode Exit fullscreen mode

This class implements IPipelineBehavior from the MediatR library, acting as a pipeline for each request. It measures request duration, logs warnings for slow requests, and records the outcome of each request.

Pro Tips for Logging Like a Boss 😎

  1. Use Structured Logging: Always include relevant context in your logs. Serilog makes this easy with templates.
  2. Log Levels Matter: Use the right log level for the right situation. Not everything is an error!
  3. Performance Matters: Logging can impact performance, so use it wisely.
  4. Sensitive Data Alert: Be careful not to log sensitive information. Your logs shouldn't be a security risk!
  5. Use the "@" Symbol: When logging objects with Serilog, use the "@" symbol (e.g., {@Error}) to serialize the entire object. This makes querying logs easier, especially with tools like Seq.

Wrapping Up 🎁

Proper logging is an essential skill for any developer working with ASP.NET Core. It's not just about catching errors; it's about gaining insights, improving performance, and making your development life easier.

Remember, your logs are your best friend when things go wrong (and even when they don't). They're your application's black box, recording every important event and helping you understand what's happening under the hood.

So, the next time you're debugging a tricky issue or trying to understand why your app is behaving weirdly, remember: that your logs are there to help. Happy logging, developers! πŸš€

The source code is available in my Github repo.

Image of Datadog

The Essential Toolkit for Front-end Developers

Take a user-centric approach to front-end monitoring that evolves alongside increasingly complex frameworks and single-page applications.

Get The Kit

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

🌢️ Newest Episode of Leet Heat: A Game Show For Developers!

Contestants face rapid-fire full stack web dev questions. Wrong answers? The spice level goes up. Can they keep cool while eating progressively hotter sauces?

View Episode Post

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❀️