Author : HASSAN MD TAREQ

Installing packages

Install-Package Serilog.AspNetCore

Serilog.AspNetCore already has references to the following packages:

Install-Package Serilog.Settings.Configuration
Install-Package Serilog.Sinks.Console
Install-Package Serilog.Sinks.File
Install-Package Serilog.Formatting.Compact

Extra packages (if you want/need):

Install-Package Serilog.Sinks.Async

Install-Package Serilog.Enrichers.Environment
Install-Package Serilog.Enrichers.Process
Install-Package Serilog.Enrichers.Thread

appsettings json

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Warning"
    },
    "Enrich": [
      "FromLogContext"
    ],
    "Properties": {
      "Application": "HovermindApp"
    },
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Exception}",
          "theme": "Serilog.Sinks.SystemConsole.Themes.SystemConsoleTheme::Literate, Serilog.Sinks.Console"
        }
      },
      {
        "Name": "Async",
        "Args": {
          "configure": [
            {
              "Name": "File",
              "Args": {
                "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
                "path": "D:/home/LogFiles/Application/HovermindApp.ndjson",
                "shared": "true",
                "fileSizeLimitBytes": "1000000",
                "rollOnFileSizeLimit": true,
                "flushToDiskInterval": "1"
              }
            }
          ]
        }
      }
    ]
  }
}

Logger initialization in Program class

Program.cs

public class Program
{
	public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
		.SetBasePath(Directory.GetCurrentDirectory())
		.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
		.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
		.AddEnvironmentVariables()
		.Build();

	public static int Main(string[] args)
	{
		Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(Configuration).CreateLogger();

		try
		{
			Log.Information("Getting the motors running...");

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

			return 0;
		}
		catch (Exception ex)
		{
			Log.Fatal(ex, "Host terminated unexpectedly");
			return 1;
		}
		finally
		{
			Log.CloseAndFlush();
		}
	}

	public static IHostBuilder CreateHostBuilder(string[] args){
	
		// Serilog in ASP.NET Core 3 plugs into the generic host and not webBuilder
		
		return Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => {
				webBuilder.UseStartup<Startup>();
			})
			.UseSerilog(); // <- Plug Serilog into the pipeline;
	}
}

Another way:

public class Program
{


	public static int Main(string[] args)
	{
		CreateHostBuilder(args).Build().Run();
	}

	public static IHostBuilder CreateHostBuilder(string[] args){
	
		// Serilog in ASP.NET Core 3 plugs into the generic host and not webBuilder
		return Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => {
			webBuilder.UseStartup<Startup>();
		})
        .UseSerilog((context, config) =>
        {
            config.ReadFrom.Configuration(context.Configuration);
        })
	}
}


Logging section in appsettings json

Logging in Controller

Using Dependency Injection

HomeController.cs

using Serilog;

public class HomeController : Controller
{
	private ILogger<HomeController> _logger;
	
    private static IFooService _fs;
    
    public HomeController(ILogger<HomeController> logger, IFooService fs, ...)
    {
		_logger = logger;
        _fs = fs;
		
		// ... ... ...
    }
    
    public IActionResult Index()
    {

        var foo = new Foo { Id = 2, FooName = "FooTwo" };
		
        _logger.Information("Object: {@FooMan}", foo); // @ : destructuring operator
        
        return View();
    }
}

Using static Log

HomeController.cs

using Serilog;

public class HomeController : Controller
{
    private static IFooService _fs;
    
    public HomeController(IFooService fs)
    {
        _fs = fs;
    }
    
    public IActionResult Index()
    {

        var foo = new Foo { Id = 2, FooName = "FooTwo" };
		
        Log.Information("Object: {@FooMan}", foo); // @ : destructuring operator
        
        return View();
    }
}

seq sink

seq in docker: Running seq in docker

seq sink package installation

Install-Package Serilog.Sinks.Seq

configuration for seq in appsettings.json

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "Enrich": [
      "FromLogContext"
    ],
    "Properties": {
      "Application": "HoverApp"
    },
    "WriteTo": [
      // ... ... ...
      {
        "Name": "Seq",
        "Args": {
          "serverUrl": "http://localhost:5341",
          "compact": true
        }
      }
    ]
  }
}

Request logging

To enable the middleware, first change the minimum level for Microsoft.AspNetCore to Warning

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft.AspNetCore": "Warning"
      }
    },
    // ... ... ...
}

In Startup.cs, add the middleware with UseSerilogRequestLogging()

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
	if (env.IsDevelopment())
	{
		app.UseDeveloperExceptionPage();
	}
	else
	{
		app.UseExceptionHandler("/Home/Error");
	}

	app.UseSerilogRequestLogging(); // <-- Add this line

	// Other app configuration
	// ... ... ...
}

options callback on UseSerilogRequestLogging() (modify message template, events, properties etc.)

// ... ... ...

app.UseSerilogRequestLogging(options =>
{
    // Customize the message template
    options.MessageTemplate = "Handled {RequestPath}";
    
    // Emit debug-level events instead of the defaults
    options.GetLevel = (httpContext, elapsed, ex) => LogEventLevel.Debug;
    
    // Attach additional properties to the request completion event
    options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
    {
        diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value);
        diagnosticContext.Set("RequestScheme", httpContext.Request.Scheme);
    };
});

// ... ... ...

Response logging

Logging to Azure Blob Storage

/aspnet-core/logging#logging-to-azure-blob-storage-using-serilog