Integrate logging in a asp.net core application using Serilog and Seq

4 minute read

Overview
Serilog is a newer logging framework for .NET and now has been the most used and preferred framework for .NET Application. Seq is the intelligent search, analysis, and alerting server built specifically for modern structured log data. Here I will show you a how to integrate serilog and seq in a simple asp.net core application.

Tools and Technology used The following tools and technologies has been used for this application

  • Visual Studio 2019
  • Visual C#
  • ASP.NET Core Web API
  • .NET Framework 5.0
  • Serilog
  • Seq

Step 1: Create a asp.net core web api project

  • Create a new project using visual studio 2019
  • Choose the C# ASP.NET Web API (.NET Core) project template
  • Create a web api project name - “Catalog.API”

For Cosole Logging

Step 2: Install nuget package Serilog.Asp.NetCore

Install-Package Serilog.AspNetCore

Step 3: Enable console logging

Modify Program.cs as follows

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Serilog;

namespace Catalog.API
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .Enrich.FromLogContext() // To get some key information like user id/request id 
                .WriteTo.Console()
                .CreateLogger();

            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .UseSerilog()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

Step 4: Modify appsettings.json
Modify appsettings.json as follows, if required.

{  
  "AllowedHosts": "*"  
}

Step 5: Add logging information in WeatherForecastController
Modify default WeatherForecastController as follows for logging

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Catalog.API.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            _logger.LogInformation("HTTP GET: Called get method of WeatherForecast contorller");
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

Step 6: Run your application to see the log

  • Run the application (not in iis express)
  • You will see the log in console window.

Note: If you want to change the output format to JSON. Just change

.WriteTo.Console(new RenderedCompactJsonFormatter())  

File Logging

Step 7: Install Package Serilog.Sinks.File

PM> Install-Package Serilog.Sinks.File

Step 8: Modify Main method of Program class as follows Program.cs

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Formatting.Compact;
using System;

namespace Catalog.API
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .Enrich.FromLogContext() // To get some key information like user id/request id 
                .WriteTo.Console(new RenderedCompactJsonFormatter())
                .WriteTo.Debug(outputTemplate: DateTime.Now.ToString())
                .WriteTo.File("catalogLog.txt", rollingInterval: RollingInterval.Day)
                .CreateLogger();

            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .UseSerilog()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

Step 9: Run your application to see the log in file

  • Run the application (not in iis express)
  • You will see the log in file name catalogLogYYYYMMDD.txt in the root folder

View log in Seq
Step 10: Run docker image for Seq

  • Start docker in your machine
  • Run the following command to pull and run Seq in docker
docker pull datalust/seq
docker run --name seq -d --restart unless-stopped -e ACCEPT_EULA=Y -p 6171:80 datalust/seq:latest
  • Browse http://localhost:6171/ to see Seq is running or not

_Step 11: Install Serilog.Sinks.Seq

PM> Install-Package Serilog.Sinks.Seq  

Step 12: Configure Seq
Now configure Seq end point in Program class as follows

 using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Formatting.Compact;
using System;

namespace Catalog.API
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .Enrich.FromLogContext() // To get some key information like user id/request id 
                .WriteTo.Console(new RenderedCompactJsonFormatter())
                .WriteTo.Debug(outputTemplate: DateTime.Now.ToString())
                .WriteTo.File("catalogLog.txt", rollingInterval: RollingInterval.Day)
                .WriteTo.Seq("http://localhost:6171/")
                .CreateLogger();

            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .UseSerilog()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

Step 13: Run your application to see the log in Seq

  • Run the application (not in iis express)
  • Browse http://localhost:6171/#/events
  • You will see the log in Seq.

Details logging

Step 14: Add a model class name CatalogItem in Model folder

CatalogItem.cs

namespace Catalog.API.Model
{
    public class CatalogItem
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public string Description { get; set; }

        public decimal Price { get; set; }

        // Quantity in stock
        public int AvailableStock { get; set; }

        // Available stock at which we should reorder
        public int RestockThreshold { get; set; }

    }
}

Step 15: Add a Controller class name CatalogContoller CatalogController.cs

using Catalog.API.Model;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Catalog.API.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class CatalogController : ControllerBase
    {
        private readonly ILogger<CatalogController> _logger;

        public CatalogController(ILogger<CatalogController> logger)
        {
            _logger = logger;
        }
        //GET api/<CatalogController>/1/110
        [HttpGet("{catalogId}/{quantity}")]
        public string GetItem(int catalogId, int quantity)
        {
            try
            {
                CatalogItem item = GetItems(catalogId);

                if (item.AvailableStock < quantity)
                {
                    _logger.LogInformation("Stock quantity {0} is lower than requested quantity {1}", item.AvailableStock, quantity);
                    return "Stock quantity is lower than requested quantity.";
                }
            }
            catch(Exception exp)
            {
                var logMsg = new StringBuilder();
                logMsg.AppendLine($"Error message:{exp.Message}");
                logMsg.AppendLine($"Error stack trace:{exp.StackTrace}");
                _logger.LogError(logMsg.ToString());
            }
            return "Your order has been submitted";
        }


        private CatalogItem GetItems(int catalogId)
        {
            List<CatalogItem> catalogRepository = new List<CatalogItem>();
            catalogRepository.Add(new CatalogItem { Id = 1, Name = "Asus ZenBook", Price = 150000, AvailableStock = 25, RestockThreshold = 5 });
            catalogRepository.Add(new CatalogItem { Id = 2, Name = "Dell 4345", Price = 110000, AvailableStock = 25, RestockThreshold = 5 });
            catalogRepository.Add(new CatalogItem { Id = 3, Name = "Lenovo ThinkPad", Price = 180000, AvailableStock = 25, RestockThreshold = 5 });
            catalogRepository.Add(new CatalogItem { Id = 4, Name = "Microsoft Surface", Price = 250000, AvailableStock = 25, RestockThreshold = 5 });

            CatalogItem item = new CatalogItem();
            try
            {
                item = catalogRepository.Where(p => p.Id == catalogId).FirstOrDefault();
            }
            catch(Exception exp)
            {
                throw new Exception(exp.Message);
            }

            return item;
        }
    }
}

Step 16: Again run your application to see the log in Seq

  • Run the application (not in iis express)
  • Browse your application as http://localhost:5000/api/Catalog/1/110
  • Browse Seq http://localhost:6171/#/events
  • You will see the log in Seq.
  • Now cheers

Source Code