01 logo

Serilog Logging in a Nutshell

Serilog is an open source logging library for .NET applications that is easy to configure, has a clean interface, and runs on the latest .NET platforms. NET platform , unlike other logging libraries , Serilog is built on powerful structured event data , support for logging output to the console , files , databases and more . Support for parameterized log templates , very flexible .

By He BobPublished about a year ago 4 min read

I will take you to practice the simple configuration of the Serilog framework. First, use the NuGet console to install the Serilog core libraries, and second, install the console output extension libraries.

If you want to output logs to other storage media, you can install other extension libraries, Serilog supports a lot of extension libraries.

Install Package Serilog

Install Package Serilog.Sinks.Console

Introducing namespaces:

using Serilog;

Initializes the LoggerConfiguration object:

var Therelog = new LoggerConfiguration()

.WriteTo.Console()

.CreateLogger();

Usually to write a log we only need one object

Therelog.Information(“First time, take care, try it out!”) ;

You can also set the object to be global:

//This way the log can be logged anywhere

Log.Logger = Therelog;

Log.Information("Now the global settings are set up ");

Not only that, you can also log to a file! But it requires an extension so...

Install Package Serilog

Configuring the logger in the console is the same as in ASP.NET Core:

using System;

using Serilog;

namespace SerilogExample{

class Program

{

static void Main(){

//Chained method role: 1,Initialization 2,Accept lowest level 3,Output from console 4,Log save location

//5, create a logger

Log.Logger = new LoggerConfiguration()

.MinimumLevel.Debug()

.WriteTo.Console()

.WriteTo.File("logs\\myapp.txt", rollingInterval: RollingInterval.Day)

.CreateLogger();

//cue output

Log.Information("Hello, world!");

int a = 10, b = 0;

try

{

//Reminders of possible places to save

Log.Debug("Dividing {A} by {B}", a, b);

Console.WriteLine(a / b);

}

catch (Exception ex)

{

//Error log output

Log.Error(ex, "Something went wrong");

}

//Reset global settings

Log.CloseAndFlush();

Console.ReadKey();

}

}

}

Other configurations:

Log.Logger = new LoggerConfiguration()

.MinimumLevel.Debug()

.MinimumLevel.Override("Microsoft", LogEventLevel.Information)

.Enrich.FromLogContext()

.WriteTo.Console()

.WriteTo.File(Path.Combine("Logs", @"log.txt"), rollingInterval: RollingInterval.Day)

.CreateLogger();

This article is very brief, you can refer to the official documentation.

Compared to older logging libraries like log4net, the biggest change when using Serilog is thinking in terms of log events rather than log messages. An event is composed of the following components:

  • The timestamp indicating when the event occurred.
  • The level describing the severity of the event.
  • The message content for the event.
  • Named properties describing additional contextual information.
  • Optionally, an Exception object.

You can format log events into readable text for the console, as shown in the first example:

11:33:01 [INF] Hello, Serilog!

Alternatively, the same event can be formatted as JSON and sent to a remote logging server:

{"@t":"2017-11-20T11:33:01.22138","@m":"Hello, Serilog!"}

Behind the scenes, logging statements in your application create LogEvent objects, and the connected sinks know how to record them.

Logging levels

Serilog is fast, but always building and logging detailed events can waste CPU, disk, and network resources. To manage this, Serilog assigns events various levels, like Debug, Information, Warning, and Error. Corresponding Log.*() methods map to these levels.

During development, you might enable debug-level logging:

Log.Logger = new LoggerConfiguration()

.MinimumLevel.Debug() // Set the minimum level

.WriteTo.Console()

.CreateLogger();

// In a tight loop...

Log.Debug("Processing item {ItemNumber} of {ItemCount}", itemNumber, itemCount);

In production, it's common to disable debug logs and set the minimum level to Information to only capture important events. For more details, check the documentation on Serilog Logger Levels.

Tip: Serilog has special handling for Exception objects. Methods like Log.Error() take the exception as the first parameter:

Log.Error(ex, "Task {TaskName} was canceled", task);

Capturing Structured Data

Let's revisit the previous code snippet:

var itemNumber = 10;

var itemCount = 999;

Log.Debug("Processing item {ItemNumber} of {ItemCount}", itemNumber, itemCount);

Notice the {ItemNumber} placeholder in the log message? This isn't a C# interpolated string but a message template. Serilog uses these placeholders to capture properties:

{

"@t": "2017-11-20T11:33:01.22138",

"@l": "Debug",

"@m": "Processing item 10 of 999",

"ItemNumber": 10,

"ItemCount": 999

}

This allows you to filter logs based on properties, like ItemNumber > 900, without regex.

Further, using the @ capture operator, you can log full objects:

var user = new { Name = "Nick", Id = "nblumhardt" };

Log.Information("Logged on user {@User}", user);

This logs structured data that can be queried:

{

"@t": "2017-11-20T11:33:01.22138",

"@m": "Logged on user {\"Name\": \"Nick\", \"Id\": \"nblumhardt\"}",

"User": {"Name": "Nick", "Id": "nblumhardt"}

}

Tip: Install the Serilog Analyzer from Visual Studio Marketplace for assistance with message template types and code configuration.

Writing JSON Logs

If you need simple log management, you can write JSON to a file and query it using JSON-compatible tools. Serilog's file sink and compact JSON formatter make this easy:

dotnet add package Serilog

dotnet add package Serilog.Sinks.File

dotnet add package Serilog.Formatting.Compact

In the Main function:

Log.Logger = new LoggerConfiguration()

.MinimumLevel.Debug()

.WriteTo.File(new CompactJsonFormatter(), "log.clef")

.CreateLogger();

var itemCount = 99;

for (var itemNumber = 0; itemNumber < itemCount; ++itemNumber)

Log.Debug("Processing item {ItemNumber} of {ItemCount}", itemNumber, itemCount);

Log.CloseAndFlush();

The log file will contain JSON-formatted logs:

{

"@t": "2024-11-20T11:33:01.22138",

"@l": "Debug",

"@m": "Processing item 10 of 99",

"ItemNumber": 10,

"ItemCount": 99

}

Tip: The CLEF-tool can be used to query CLEF logs.

Logging to a Server

Sending logs from multiple applications to a centralized server can simplify monitoring. Serilog supports various logging servers, many of which handle structured data.

Filtering and Enriching Events

You can enrich log events by adding context:

Log.Logger = new LoggerConfiguration()

.Enrich.WithProperty("Application", "Demo")

.WriteTo.Seq("http://localhost:5341")

.CreateLogger();

To log properties only for specific contexts:

var orderLog = Log.ForContext("OrderId", order.Id);

orderLog.Information("Looking up product codes");

orderLog.Information("Product lookup took {Elapsed} ms", elapsed.TotalMilliseconds);

For class-specific logging:

private readonly ILogger _log = Log.ForContext<HomeController>();

This attaches a SourceContext property to log events.

Advanced Logging with LogContext

You can enrich all events within a context using LogContext:

Log.Logger = new LoggerConfiguration()

.Enrich.FromLogContext()

// ...

And use it like this:

using (LogContext.PushProperty("MessageId", message.Id))

{

Log.Debug("Dispatching message of type {MessageType}", message.GetType());

await handler.HandleAsync(message);

}

Tip: The LogContext is stack-based and should be disposed when done.

Finding Needles in the Haystack

You can filter by message templates to quickly identify specific types of events:

@MessageTemplate <> 'Processing item {ItemNumber} of {ItemCount}'

Or zoom in on all events of a certain type.

Custom Enrichment

For environments lacking support for message templates, custom enrichers can add event types:

class EventTypeEnricher : ILogEventEnricher

{

public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)

{

var murmur = MurmurHash.Create32();

var bytes = Encoding.UTF8.GetBytes(logEvent.MessageTemplate.Text);

var hash = murmur.ComputeHash(bytes);

var numericHash = BitConverter.ToUInt32(hash, 0);

var eventType = propertyFactory.CreateProperty("EventType", numericHash);

logEvent.AddPropertyIfAbsent(eventType);

}

}

Next Steps

Serilog has a broad ecosystem of plugins and tools. We've only covered the basics; depending on your needs and platform, there's much more to explore!

appstech news

About the Creator

Reader insights

Nice work

Very well written. Keep up the good work!

Top insights

  1. Compelling and original writing

    Creative use of language & vocab

  2. Easy to read and follow

    Well-structured & engaging content

  3. Masterful proofreading

    Zero grammar & spelling mistakes

  1. On-point and relevant

    Writing reflected the title & theme

Add your insights

Comments (1)

Sign in to comment
  • Alyssa wilkshoreabout a year ago

    Thanks for sharing

Find us on social media

Miscellaneous links

  • Explore
  • Contact
  • Privacy Policy
  • Terms of Use
  • Support

© 2026 Creatd, Inc. All Rights Reserved.