Click here to Skip to main content
15,888,610 members
Articles / Web Development / HTML

ASP.NET Core 2.0 Structured Logging

Rate me:
Please Sign up or sign in to vote.
1.80/5 (3 votes)
4 Sep 2017CPOL2 min read 11K   2   5
How to work with structured logging in ASP.NET Core and Serilog. Continue reading...

Problem

How to work with structured logging in ASP.NET Core and Serilog.

Solution

Starting from the previous post on logging, add NuGet packages:

  • Serilog.AspNetCore
  • Serilog.Sinks.Literate
  • Serilog.Sinks.Seq

In Program.cs, configure Serilog using its LoggerConfiguration class and storing an instance of ILogger (returned by CreateLogger) in Serilog’s static Log class:

C#
        public static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                        .WriteTo.LiterateConsole()
                        .CreateLogger();

           BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup><startup>()
                .UseSerilog()
                .Build();
</startup>

Using the ILogger is the same as our previous post, however, with Serilog, we can do structured logging:

C#
public async Task Invoke(HttpContext context)
        {
            var message = new
            {
                GreetingTo = "James Bond",
                GreetingTime = "Morning",
                GreetingType = "Good"
            };
            this.logger.LogInformation("Inoke executing {@message}", message);

            await context.Response.WriteAsync("Hello Logging!");

            this.logger.LogInformation(
                "Inoke executed by {developer} at {time}", "Tahir", DateTime.Now);
        }

Running the application will show messages in Console window:

Serilog - Output

Discussion

Structured logging is a technique to include semantic information as part of the messages being logged. This helps ‘machine readability’ of these messages and tools can be written to analyse raw log messages and produce interesting information.

Serilog uses message template, similar to string.Format() in .NET. Few interesting aspects of template syntax are:

  • Use {} to enclose property names e.g. {developer} in the above solution. These will be stored as metadata and can be queried using structured data storage (e.g. Seq, Azure).
  • Use @ to preserve object structure, e.g., in the solution above, the anonymous object is serialised into JSON representation.

Enrichers

In Serilog, enrichers are used to attach information with every log event that can then be used by structured data storage (e.g. Seq, Azure) for viewing and filtering. A simple way to do this is by using .Enrich.WithProperty() when configuring Serilog:

C#
Log.Logger = new LoggerConfiguration()
                                .Enrich.WithProperty("ApiVersion", "1.2.5000")
                                .WriteTo.LiterateConsole()
                                .CreateLogger();

Context

As we saw in the previous post, a category can be attached to the logged messages, which normally is the fully qualified name of the class. This information could be used by structured data storage (e.g. Seq, Azure). Serilog provides this mechanism by attaching Context via ForContext() method:

C#
Log.Logger = new LoggerConfiguration()
                                .Enrich.WithProperty("ApiVersion", "1.2.5000")
                                .WriteTo.LiterateConsole()
                                .CreateLogger()
                                .ForContext<HelloLoggingMiddleware>();

Sinks

Sinks in Serilog refer to destination of log messages, e.g., file, database or console (in our example). There are several sinks available (refer to the link below). I’ll use Seq as an example sink to show how all the metadata we’ve added is available in a structured storage:

C#
Log.Logger = new LoggerConfiguration()
                                .Enrich.WithProperty("ApiVersion", "1.2.5000")
                                .WriteTo.LiterateConsole()
                                .WriteTo.Seq("http://localhost:5341")
                                .CreateLogger()
                                .ForContext<HelloLoggingMiddleware>();

Serilog - Output2

Notice how data we added via enricher, context and custom object appears as key/value pairs. This can now be used for filtering data and creating dashboards within Seq.

Note: Refer to Seq website (link below) for installation instructions (it’s very simple!).

Update (04-Sep-2017): I've updated the article and source code to use the new Serilog.AspNetCore package for ASP.NET Core 2.0 (Thank you Nicholas Blumhardt for bringing this to my attention).

Useful Links

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
SuggestionUseSerilog() in the new Serilog.AspNetCore package Pin
Nicholas Blumhardt3-Sep-17 18:22
Nicholas Blumhardt3-Sep-17 18:22 
GeneralRe: UseSerilog() in the new Serilog.AspNetCore package Pin
User 10432643-Sep-17 22:27
User 10432643-Sep-17 22:27 
GeneralRe: UseSerilog() in the new Serilog.AspNetCore package Pin
Nicholas Blumhardt4-Sep-17 11:50
Nicholas Blumhardt4-Sep-17 11:50 
GeneralRe: UseSerilog() in the new Serilog.AspNetCore package Pin
User 10432644-Sep-17 12:42
User 10432644-Sep-17 12:42 
GeneralRe: UseSerilog() in the new Serilog.AspNetCore package Pin
Nicholas Blumhardt4-Sep-17 12:46
Nicholas Blumhardt4-Sep-17 12:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.