DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • How To Build Web Service Using Spring Boot 2.x
  • Step-by-Step Guide: Application Using NestJs and Angular
  • Migrate Mule 3 to Mule 4 Using MMA (Mule Migration Assistant)
  • Rails 6: Multiple DB Support

Trending

  • Distributed Consensus: Paxos vs. Raft and Modern Implementations
  • Simpler Data Transfer Objects With Java Records
  • Implementing Explainable AI in CRM Using Stream Processing
  • How to Introduce a New API Quickly Using Micronaut
  1. DZone
  2. Data Engineering
  3. Databases
  4. Serilog Tutorial for .NET Logging: 16 Best Practices and Tips

Serilog Tutorial for .NET Logging: 16 Best Practices and Tips

Let's run through using Serilog for your .NET logging needs (with a comparison of Stackify's Retrace along the way) to discover some best practices.

By 
Matt Watson user avatar
Matt Watson
·
Aug. 20, 18 · Opinion
Likes (1)
Comment
Save
Tweet
Share
90.1K Views

Join the DZone community and get the full member experience.

Join For Free

Serilog is a newer logging framework for .NET. It was built with structured logging in mind. It makes it easy to record custom object properties and even output your logs to JSON.

Note: You can actually check out our other tutorials for NLog and log4net to learn how to do structured logging with them also!

In this article, we are going to review some of the key features, benefits, and best practices of Serilog.

What Is Serilog? Why Should You Use It, or Any C# Logging Framework?

Logging is one of the most basic things that every application needs. It is fundamental to troubleshoot any application problems.

Logging frameworks make it easy to send your logs to different places via simple configurations. Serilog uses what are called sinks to send your logs to a text file, database, or log management solutions, or potentially dozens of other places, all without changing your code.

How to Install Serilog via Nuget and Get Started

Starting with Serilog is as easy as installing a Serilog Nuget package. You will also want to pick some logging sinks to direct where your log messages should go, including the console and a text file.

If you are new to Serilog, check out their website: Serilog.net

Install-Package Serilog
Install-Package Serilog.Sinks.Console


Logging Sinks: What They Are and Common Sinks You Need to Know

Sinks are how you direct where you want your logs sent. The most popular of the standard sinks are the File and Console targets. I would also try the Debug sink if you want to see your log statements in the Visual Studio Debug window so you don’t have to open a log file.

Serilog’s sinks are configured in code when your application first starts. Here is an example:

using (var log = new LoggerConfiguration()
    .WriteTo.Console()
    .CreateLogger())
{
    log.Information("Hello, Serilog!");
    log.Warning("Goodbye, Serilog.")
}


If you are using a Console, you should check out the ColoredConsole sink:

Serilog colored console target

How to Enable Serilog’s Own Internal Debug Logging

If you are having any problems with Serilog, you can subscribe to its internal events and write them to your debug window or a console.

Serilog.Debugging.SelfLog.Enable(msg => Debug.WriteLine(msg));
Serilog.Debugging.SelfLog.Enable(Console.Error);


Please note that the internal logging will not write to any user-defined sinks.

Make Good Use of Multiple Serilog Logging Levels and Filter by Them

Be sure to use verbose, debug, information, warning, error, and fatal logging levels as appropriate.

This is really valuable if you want to specify only certain levels to be logged to specific logging sinks or to reduce logging in production.

If you are using a central logging solution, you can easily search for logs by the logging level. This makes it easy to find warnings, errors, and fatals quickly.

How to Do Structured Logging, or Log an Object or Properties With a Message

When Serilog was first released, this was one of the biggest reasons to use it. It was designed to easily log variables in your code.

As you can see in his example, it is easy to use these custom variables:

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


Serilog takes it to the next level because those same variables can also easily be recorded as JSON or sent to a log management solution like Retrace.

If you want to really get the value of structured logging, you will want to send your logs to a log management tool that can index all the fields and enable powerful searching and analytics capabilities.

Warning: Saving logs to a database doesn't scale


Querying a SQL database for logging data is a terrible idea if aren’t using full-text indexing. It is also an expensive place to save logging data.

You are much better off sending your logs to a log management service that can provide full-text indexing and more functionality with your logs.

Do Not Send Emails on Every Exception

Everyone has made this mistake only once. Sending an email every time an exception happens quickly leads to all the emails being ignored, or your inbox gets flooded when a spike in errors occurs.

If you love getting flooded with emails, there is an email sink you can use.

How to Send Alerts for Exceptions

If you want to send alerts when a new exception occurs, send your exceptions to an error reporting solution, like Stackify Retrace, that is designed for this. Retrace can deduplicate your errors so you can figure out when an error is truly new or regressed. You can also track its history, error rates, and a bunch of other cool things.

How to Search Logs Across Servers

Capturing logs and logging them to a file on disk is great, but it doesn’t scale and isn’t practical on large apps. If you want to search your logs across multiple servers and applications, you need to send all of your logs to a centralized logging server.

You can easily send your logs to Stackify with our custom sink:

var log = new LoggerConfiguration()
    .WriteTo.Stackify()
    .CreateLogger();


Products like Stackify Retrace make it easy to view all of your logs in one place and search across all of them. They also support things like log monitoring, alerts, structured logging, and much more.

Screenshot of Retrace’s log viewer:

Retrace Log Management

If you want to query all your text files on disk, consider using VisualLogParser.

Use Filters to Suppress Certain Logging Statements

Serilog has the ability to specify log levels to send to specific sinks or suppress all log messages. Use the restrictedToMinimumLevel parameter.

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.File("log.txt")
    .WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Information)
    .CreateLogger();


You Can Make Your Own Custom Sinks

If you want to do something that the standard Serilog sinks do not support, you can search online for one or write your own.

One example could be a target for writing to Azure Storage.

As an example of a custom target, you can review the source code for our Serilog sink for sending logs to Retrace.

Customize the Output Format of Your Logs

With Serilog you can control the format of your logs, such as which fields you include, their order, and etc.

Here is a simple example:

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console(outputTemplate:
        "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
    .CreateLogger();


The following fields can be used in a custom output template:

  • Exception
  • Level
  • Message
  • NewLine
  • Properties
  • Timestamp

If that isn’t enough, you can implement ITextFormatter to have even more control of the output format.

Serilog has also great support from writing your log files as JSON. It has a built-in JSON formatter that you can use.

Log.Logger = new LoggerConfiguration()
    .WriteTo.File(new CompactJsonFormatter(), "log.txt")
    .CreateLogger();


Enrich Your Logs With More Context

Most logging frameworks provide some way to log additional context values across all logging statements. This is perfect for setting something like a UserId at the beginning for a request and having it included in every log statement.

Serilog implements this by what they call enrichment.

Below is a simple example of how to add the current thread id to the logging data captured.

var log = new LoggerConfiguration()
    .Enrich.WithThreadId()
    .WriteTo.Console()
    .CreateLogger();


To really use enrichment with your own app, you will want to use the LogContext.

var log = new LoggerConfiguration()
    .Enrich.FromLogContext()


After configuring the log context, you can then use it to push properties into the context of the request. Here is an example:

log.Information("No contextual properties");
using (LogContext.PushProperty("A", 1))
{
    log.Information("Carries property A = 1");
    using (LogContext.PushProperty("A", 2))
    using (LogContext.PushProperty("B", 1))
    {
        log.Information("Carries A = 2 and B = 1");
    }
    log.Information("Carries property A = 1, again");
}


How to Correlate Log Messages by Qeb Request Transaction

One of the toughest things about logging is correlating multiple log messages to the same web request. This is especially hard in async code.

You can use one of the enrichment libraries to add various ASP.NET values to each of your log messages.

var log = new LoggerConfiguration()
    .WriteTo.Console()
    .Enrich.WithHttpRequestId()
    .Enrich.WithUserName()
    .CreateLogger();


It also has some cool options to add things like WithHttpRequestRawUrl, WithHttpRequestClientHostIP, and other properties.

If you are using .NET full framework or .NET Core, check out these enrichment libraries:

  • Full .NET Framework
  • ASP.NET Core

Note: There are also some other enrichment libraries for other various ASP.NET frameworks.

How to View Serilog Logs by ASP.NET Web Request

Log files can quickly become a spaghetti mess of log messages. Especially with web apps that have lots of AJAX requests going on that all do logging.

I highly recommend using Prefix, Stackify’s free .NET Profiler to view your logs per web request along with SQL queries, HTTP calls, and much more.

transaction trace annotated

Summary

In this tutorial about Serilog, we covered best practices, benefits, and features of Serilog that you should know about. We also showed you how can use Stackify Prefix (for free) to view your logs while testing your application on your development machine. We also briefly showed the power of Stackify Retrace for centralizing all of your logs in one easy to use log management solution.

Database application Requests Framework .NET Property (programming) Debug (command) app

Published at DZone with permission of Matt Watson, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How To Build Web Service Using Spring Boot 2.x
  • Step-by-Step Guide: Application Using NestJs and Angular
  • Migrate Mule 3 to Mule 4 Using MMA (Mule Migration Assistant)
  • Rails 6: Multiple DB Support

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!