Using Serilog with ASP.NET Core
Serilog is one of the more popular logging packages that integrates with ASP.NET Core. I have recently used Serilog on several RESTFUL API projects and I have found it to work extremely well with most logging needs.
Serilog comes with a dedicated package for ASP.NET Core support. It makes it easier to setup and
provides several options for where to send the logging information. My ‘default’ setup is to store
the configuration information in the appsettings.json
and to send the logging output to the console. Once
this is set up properly, I can start adding more sinks (where the system places log messages).
Here are the packages you will need to install:
dotnet add package Serilog
dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Settings.Configuration
dotnet add package Serilog.Sinks.Console
Once installed, you’ll need to configure Serilog. Place the following in your appsettings.json
:
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Warning"
}
},
"WriteTo": [
{ "Name": "Console" }
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
}
This sets the minimum log level to Debug
so we can see Debug
or higher log messages in the sinks. The
Override
on the Microsoft
namespace restricts the logging in the ASP.NET Core pipeline to Warning
level
messages or higher. I’d recommend you place around with these settings to find what is best for your needs.
Next, you’ll need to initialize Serilog when the application starts. For that, we’ll need to do some surgery to the
Main
routine in the Program.cs
. First change the return type from void
to int
. This allows the program to
return a non-zero value to the console if it exists with an error. this can be very useful in determining if
the application starts/ends successfully.
public static int Main(string[] args)
Next, in the Main
routine, we’ll need to load the configuration data from the settings file. Here
is what I found works for me. It is by no means the best way so feel free to make adjustments here for
your own context.
My typical pattern is use the appsettings.json
to store the settings used by developers on their local
workstations. I always provide a means to override these setting using environment variables. I then use
the appsettings.{Environment}.json
file to override the settings when deployed to the target environment.
To get the target environment, you can use the following:
var h = new WebHostBuilder();
var environment = h.GetSetting("environment"); // Development, Staging, Production, etc.
Now build a configuration instance and use it to configure the logger (using the Log
static class).
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{environment}.json", optional: true)
.AddEnvironmentVariables()
.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
Next, let’s add a try/catch
block around the code that runs the web server. This allows the program
to log any issues that occur during startup.
try
{
Log.Information("Starting web host");
CreateWebHostBuilder(args).Build().Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.Information("Ending web host");
Log.CloseAndFlush();
}
And finally, we modify the CreateWebHostBuilder
routine to use Serilog:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseSerilog()
.UseStartup<Startup>();
When you run your application, you should see something like:
[05:50:13 INF] Starting web host
Hosting environment: Local
Content root path: C:\Users\edgamat\source\repos\RefArch
Now listening on: http://localhost:51715
Application started. Press Ctrl+C to shut down.
[05:50:15 WRN] Failed to determine the https port for redirect.
You can see that the first line contains the INF
message we added in the Main
routine.
Now you should be able to add loggers to you program and see the output in the Console window. I’ll create an additional blog post to demonstrate how that is accomplished.
Using the SQL Server Sink
In case you want to use SQL Server to store your log messages, Serilog includes a package for that:
dotnet add package Serilog.Sinks.MSSqlServer
And here is an example of how to configure it via the appsettings.json
file:
"WriteTo": [
{ "Name": "Console" },
{
"Name": "MSSqlServer",
"Args": {
"connectionString": "Server=localhost;Database=RefArch;Integrated Security=true",
"schemaName": "dbo",
"tableName": "ErrorLog",
"autoCreateSqlTable": true,
"restrictedToMinimumLevel": "Warning"
}
]