# Logging in .NET

# Structured Logging

When logging and using a provider that supports structured/semantic logging, we should provide parameters the following way:

_logger.LogInformation("User {userId} logged in", userId);

// BAD
_logger.logInformation($"User {userId} logged in");

The first way stores both the value of the parameter (the actual user identifier) and the name of this parameter. In the second approach, the name is lost, so we are not able to filter based on the named parameter (userId).


The structured logging information is stored as JSON. For example:

    "eventLevel": "Information",
    "category": "Device.IoTHubService",
    "eventId": "1543",
    "messageTemplate": "Device {deviceId} has connected to IoT Hub",
    "message": "Device 123 has connected to IoT Hub",
    "deviceId": "123"

# Log Storage

Structured logs can be stored in systems like:

  • Elasticsearch
  • Seq

# Serilog

Using Serilog:

  1. Install NuGet packages:

    dotnet add package Serilog.Sinks.Console # Console sink
    dotnet add package Serilog.Settings.Configuration # allows reading settings from a file
    dotnet add package Serilog.Extensions.Logging # DI
  2. Use Serilog with DI

    var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((host, services) =>
        services.AddLogging(builder =>
            var logger = new LoggerConfiguration()
                .ReadFrom.Configuration(host.Configuration) // Serilog.Settings.Configuration
            builder.ClearProviders(); // removes the default logger
        // Other services...
  3. Configure

    In appsettings.json:

        "Serilog": {
            "Using":  [ "Serilog.Sinks.Console" ],
            "MinimumLevel": "Debug",
            "WriteTo": [ "Console" ]

    More information can be found here (opens new window).


Sometimes Rider may display logs in black font color on the dark background. To change that, got to the "Preferences -> Editor -> Color Scheme -> Console Colors" and change "Bright White" color to #FFFFFF.

# Usage without Dependency Injection

Log.Logger = new LoggerConfiguration()

    // Run the app...
catch(Exception e) 
    Log.Fatal(e, "Host terminated unexpectedly");

# Logging to files with Serilog

public static void AddLogging(this IServiceCollection services, AppConfiguration appConfiguration)
    services.AddLogging(services, builder => {
        builder.AddSerilog(builder, GetSerilogLogger(appConfiguration), true);

private static Serilog.Core.Logger GetSerilogLogger(AppConfiguration appConfiguration)
    var configuration = Serilog.ConsoleLoggerConfigurationExtensions.Console(
        new Serilog.LoggerConfiguration()

        Serilog.FileLoggerConfigurationExtensions.File(configuration.WriteTo, appConfiguration.LogPath);

    return configuration.CreateLogger();
Last Updated: 10/5/2022, 6:26:29 PM