serilog code example

April 11, 2026

Sabrina

How to Use Serilog for Effective .NET Logging

🎯 Quick AnswerTo effectively use Serilog, you must first install the necessary NuGet packages and configure your logger. This involves defining your desired log levels, choosing output destinations (sinks) like files or databases, and setting up formatting for readability. Proper Serilog usage transforms raw logs into actionable data.

How to Use Serilog for Effective .NET Logging

Mastering how to use Serilog is essential for any .NET developer seeking deep application visibility. You can gain invaluable insights into your application’s behavior, troubleshoot issues faster, and monitor performance with precision. This guide walks you through practical, real-world implementations to make Serilog a core part of your development workflow.

(Source: serilog.net)

In my experience, the difference between an application that’s easy to debug and one that’s a black box often comes down to the quality of its logging. Serilog, a popular .NET logging library, excels at providing structured, searchable logs that make this process significantly smoother. Let’s dive into how you can leverage its power.

Table of Contents

What is Serilog and Why Use It?

Serilog is an opinionated logging library for .NET applications that makes it easy to write diagnostic logs. Its primary advantage lies in its support for structured logging. Instead of just dumping plain text into a file, Serilog allows you to log events as structured data (like JSON), which is significantly easier for machines to parse and humans to query.

Why is structured logging so important? Imagine trying to find all log entries related to a specific user ID or a particular transaction within millions of lines of unstructured text. With Serilog, you can query for `UserId = ‘user123’` or `TransactionId = ‘abc-123’` directly, making debugging and analysis exponentially faster. This capability is invaluable for maintaining complex applications.

Expert Tip: Think of Serilog not just as a tool for recording errors, but as a way to instrument your application for better understanding. Every log event can carry rich contextual data, turning your logs into a detailed operational journal.

Getting Started: Initial Serilog Setup

To begin using Serilog, you’ll need to add the core Serilog package and any specific sink packages you plan to use via NuGet Package Manager in Visual Studio or the .NET CLI.

The most common starting point is the `Serilog.AspNetCore` package for web applications, which integrates Serilog with ASP.NET Core’s logging infrastructure. You’ll typically configure Serilog early in your application’s startup process.

Here’s a basic setup example for an ASP.NET Core application:

1. Install Packages:

  • `dotnet add package Serilog.AspNetCore`
  • `dotnet add package Serilog.Sinks.Console` (for console output)
  • `dotnet add package Serilog.Sinks.File` (for file output)

2. Configure in Program.cs (or Startup.cs):


// In Program.cs (for .NET 6+)
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information() // Set minimum log level
    .WriteTo.Console()
    .WriteTo.File("logs/myapp-.txt", rollingInterval: RollingInterval.Day)
    .CreateLogger();

try
{
    var builder = WebApplication.CreateBuilder(args);
    builder.Host.UseSerilog(); // Integrate Serilog with the host

    // ... rest of your application setup

    var app = builder.Build();
    // ... middleware pipeline
    app.Run();
}
catch (Exception ex)
{
    Log.Fatal(ex, "Application start-up failed");
}
finally
{
    Log.CloseAndFlush();
}

This code initializes Serilog, sets the minimum level to `Information`, and directs logs to both the console and a daily rolling file. The `UseSerilog()` call integrates Serilog into the ASP.NET Core logging pipeline.

How to Configure Serilog Outputs (Sinks)

Sinks are where your logs go. Serilog supports a vast array of sinks, allowing you to send logs to virtually any destination imaginable. Choosing the right sinks depends on your application’s needs and your team’s workflow.

Common sinks include:

  • Console: Useful for development and simple applications.
  • File: Essential for persistent logging; often configured for rolling intervals (e.g., daily, hourly) to manage file size.
  • Databases: Such as SQL Server, PostgreSQL, or NoSQL databases for centralized log storage and querying. Packages like `Serilog.Sinks.MSSqlServer` are available.
  • Seq: A popular open-source log aggregation and analysis tool.
  • Elasticsearch: For integration with the ELK stack (Elasticsearch, Logstash, Kibana).
  • Application Insights: For Azure cloud monitoring.

You can configure multiple sinks simultaneously. For example, logging to both a file and Seq:


Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.Console()
    .WriteTo.File("logs/app_.txt", rollingInterval: RollingInterval.Hour)
    .WriteTo.Seq("http://localhost:5341") // Replace with your Seq URL
    .CreateLogger();
Important: When using file sinks, always configure a rolling interval to prevent log files from growing indefinitely and consuming excessive disk space. `RollingInterval.Day` or `RollingInterval.Hour` are common choices.

Using Serilog Enrichers for Context

Enrichers add contextual information to every log event automatically. This is where Serilog truly shines for structured logging. Common enrichers include adding machine name, OS version, process ID, thread ID, and application version.

The most powerful enricher for application context is `Serilog.Attributes` or custom enrichers. You can automatically add details like the current user’s identity, request ID, or correlation ID to every log message within a specific scope.

Example using `Serilog.AspNetCore`’s built-in enrichers (often configured via `appsettings.json` or programmatically):


// In Program.cs or Startup.cs
builder.Host.UseSerilog((context, configuration) => configuration
    .Enrich.FromLogContext()
    .Enrich.WithMachineName()
    .Enrich.WithProcessId()
    .Enrich.WithThreadId()
    .WriteTo.Console());

The `.Enrich.FromLogContext()` is particularly important as it allows you to push contextual properties into the log context for specific scopes, such as a web request.

Pros of Using Enrichers:

  • Adds valuable context automatically to every log.
  • Reduces boilerplate code for adding common details.
  • Improves searchability and analysis of logs.
Cons of Using Enrichers:

  • Can add slight overhead if overused or configured improperly.
  • Requires careful management of context to avoid unnecessary data.

Mastering Serilog Filtering and Log Levels

Controlling which log messages get written is critical for performance and manageability. Serilog provides robust filtering capabilities based on log levels and custom criteria.

Log Levels:

  • Verbose: The most detailed logs, typically used only during intense debugging.
  • Debug: Diagnostic information, useful during development.
  • Information: General operational messages, tracking the flow of the application.
  • Warning: Indicates a potential problem or an unexpected event that didn’t stop the application.
  • Error: Indicates a failure that prevented an operation from completing.
  • Fatal: Indicates a severe error that will likely cause the application to terminate.

You set a `MinimumLevel` when configuring Serilog. Any message logged with a level below this minimum will be ignored. You can also apply minimum levels per sink or use sophisticated filtering rules.

Example: Only write `Information` level and above to the console, but `Debug` and above to a file:


Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Verbose() // Overall minimum level
    .WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Information)
    .WriteTo.File("logs/debug_.txt", rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Debug)
    .CreateLogger();

Beyond levels, Serilog’s filtering allows you to include or exclude logs based on properties, message templates, or even custom conditions. This is incredibly powerful for production environments where you might want to exclude verbose logs but still capture specific errors.

According to a 2023 survey by TechBeacon, 77% of developers find debugging the most time-consuming part of their job, highlighting the critical need for effective logging tools like Serilog.

Practical Serilog Use Cases and Examples

Let’s look at how you might use Serilog in common scenarios.

Scenario 1: Tracking a User’s Journey in a Web Application

In an e-commerce application, you want to trace a user’s path from browsing to checkout. You can use Serilog’s `LogContext` to add user and session IDs.


// In an ASP.NET Core controller or middleware
public class MyController : ControllerBase
{
    public IActionResult GetProduct(int productId)
    {
        var userId = User.Identity.IsAuthenticated ? User.Identity.Name : "Anonymous";
        using (LogContext.PushProperty("UserId", userId))
        using (LogContext.PushProperty("Action", "GetProductView"))
        {
            _logger.LogInformation("User {UserId} is viewing product {ProductId}", userId, productId);
            // ... business logic
            return Ok(product);
        }
    }
}

The resulting log entry might look like this (in JSON format):


{
  "@t": "2026-04-15T10:30:00.1234567Z",
  "@mt": "User {UserId} is viewing product {ProductId}",
  "@l": "Information",
  "UserId": "user123",
  "Action": "GetProductView",
  "ProductId": 42,
  "SourceContext": "MyApp.Controllers.MyController",
  "ProcessId": 1234,
  "ThreadId": 5
}

Scenario 2: Logging Background Service Activity

A background service processing orders needs to log its progress and any errors reliably.


public class OrderProcessorService : BackgroundService
{
    private readonly ILogger _logger;

    public OrderProcessorService(ILogger logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Order processing service running at: {Time}", DateTimeOffset.Now);
            try
            {
                // ... process orders ...
                _logger.LogDebug("Processed {Count} orders.", processedCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "An error occurred during order processing.");
            }
            await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
        }
    }
}

This ensures that both successful operations (Information level) and failures (Error level) are captured, along with timestamps.

Scenario 3: Integrating with Seq for Centralized Logging

For larger applications or microservices architectures, sending logs to a centralized system like Seq is highly recommended. Seq provides a powerful web UI for searching, filtering, and analyzing logs.

The configuration is straightforward, as shown in the earlier sink examples. Once configured, you can open the Seq UI and see logs from all your Serilog-enabled applications flowing in, tagged with context properties you’ve defined.

The ability to filter by `UserId` or `RequestId` in Seq, thanks to Serilog’s structured output, transforms troubleshooting from a chore into a streamlined process. I’ve personally found Seq invaluable for debugging distributed systems.

Frequently Asked Questions

What is the basic setup for Serilog in .NET Core?

The basic setup involves installing `Serilog.AspNetCore` and configuring `Log.Logger` early in `Program.cs` (or `Startup.cs`). You define minimum log levels and specify output sinks like the console or files using `WriteTo` methods.

How do I control log verbosity with Serilog?

You control log verbosity primarily through log levels (`Verbose`, `Debug`, `Information`, `Warning`, `Error`, `Fatal`). Set a `MinimumLevel` for the logger or specific sinks. Messages below this level are discarded.

Can Serilog log to a database?

Yes, Serilog can log to various databases. You’ll need to install a specific sink package, such as `Serilog.Sinks.MSSqlServer` for SQL Server, and configure it with your connection string and table details.

What are Serilog enrichers used for?

Serilog enrichers automatically add contextual information to every log event. Common examples include adding machine name, process ID, thread ID, or custom properties like `UserId` or `CorrelationId` to make logs more informative.

How can Serilog help with application performance?

By providing structured logs and effective filtering, Serilog helps developers quickly identify performance bottlenecks. Analyzing logs can reveal slow database queries, inefficient code paths, or high resource utilization, enabling targeted optimization.

Conclusion and Next Steps

Learning how to use Serilog effectively is a foundational skill for any .NET developer committed to building maintainable and observable applications. By embracing structured logging, configuring appropriate sinks, and leveraging enrichers and filters, you transform your logs from mere records into powerful diagnostic tools.

Start by implementing a basic Serilog setup in your current project. Experiment with different sinks like Seq or Elasticsearch for better analysis. Continue to refine your logging strategy by adding custom enrichers that capture the most critical context for your application’s domain. Happy logging!

Editorial TeamOur team creates thoroughly researched, helpful content. Every article is fact-checked and updated regularly.
🔗 Share this article