In this example I am using .NET Core 3.1 version which has LTS from Microsoft.
1) Installing Serilog
Get Serilog to your solution using the Nuget package "Serilog.AspNetCore".
2) Removing the default logging
In the appsettingss.json you will get a configuration setting section for the built in logging which gets created for each ASP.NET Core project. Since we are not using it anymore we can remove that section.
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
3) Adding Serilog to the solution
In the program.cs file set the Serilog configurations
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.File("C:\\ProgramData\\MyWebApplication\\MyLog.txt",
rollOnFileSizeLimit: true,
fileSizeLimitBytes: 2000,
retainedFileCountLimit: 5)
.CreateLogger();
try
{
Log.Information("Starting up");
CreateHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application start-up failed");
}
finally
{
Log.CloseAndFlush();
}
}
You may have to use the following using directives:
using Serilog;
using Serilog.Events;
using Serilog.Formatting.Compact;
Now, specify that you will be using serilog when the HostBuilder is created.
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
4) Add logger to your controller class
Example:
[Route("api/[controller]/[action]")]
[ApiController]
public class MySampleController : ControllerBase
{
private readonly ILogger<MySampleController> _logger;
//constructor
public MySampleController (
ILogger<MySampleController> logger)
{
_logger = logger;
}
//sample Action
[HttpPost]
public async Task<ActionResult<Payload>> PostEmployeeInfo([FromBody]JObject notification)
{
try
{
_logger.LogInformation("Post Employee Info Success for :{0} {1}", paramOne, paramTwo);
}
catch(Exception ex)
{
_logger.LogError("Error - Post Employee: Message: {0} StackTrace: {1}", ex.Message, ex.StackTrace);
}
}
}
How is the rolling file implemented ?
In the above code we have already specified it in the Log configuration section. See below code block:
.WriteTo.File("C:\\ProgramData\\MyWebApplication\\MyLog.txt",
rollOnFileSizeLimit: true,
fileSizeLimitBytes: 2000,
retainedFileCountLimit: 5)
This states that we are rolling the files based on a maximum file size limit. In this example I have specified the size to be only 2KB, But in a practical scenario a 5MB file size would be fine. I have set the number of rolling files to 5. So there will be a maximum of 5 files at a given time. The file containing the oldest logs will be removed when a new file is created.
How is the Noise removed ?
Serilog has many log levels:
[Reference: GitHub Serilog Configuration Basics]
Normally you would set the logs minimum level to Information.
Example:
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
There is a catch here. Serilog starts to log all Information level logs. It logs information generated related to AspNetCore. I also have the Entity Framework Core in the solution. So now I also get Information level logs generated regarding EntityFrameworkCore. A sample log would look like:
But we don't need all this noise in he log all the time. So we have to specify it when we configure the logging. The following lines overrides the default settings.
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
It sets the logs generated regarding AspNetCore and EntityFrameworkCore to a higher level which is "Warning". So you would get only the warning and Fatal information from these two components. Now the log will be clearer and you can easily spot the information logs which you place in the Controller using the _logger.LogInformation() method.
Resulting file structure:
MyLog_003.txt
MyLog_004.txt
MyLog._005txt
MyLog_006.txt
MyLog_007.txt
Note that the initial log created will be like "MyLog.txt". Then increment as MyLog_001.txt. As the log files are rolling it will increase the file numbering and remove the older files.
1) Installing Serilog
Get Serilog to your solution using the Nuget package "Serilog.AspNetCore".
2) Removing the default logging
In the appsettingss.json you will get a configuration setting section for the built in logging which gets created for each ASP.NET Core project. Since we are not using it anymore we can remove that section.
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
3) Adding Serilog to the solution
In the program.cs file set the Serilog configurations
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.File("C:\\ProgramData\\MyWebApplication\\MyLog.txt",
rollOnFileSizeLimit: true,
fileSizeLimitBytes: 2000,
retainedFileCountLimit: 5)
.CreateLogger();
try
{
Log.Information("Starting up");
CreateHostBuilder(args).Build().Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application start-up failed");
}
finally
{
Log.CloseAndFlush();
}
}
You may have to use the following using directives:
using Serilog;
using Serilog.Events;
using Serilog.Formatting.Compact;
Now, specify that you will be using serilog when the HostBuilder is created.
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
4) Add logger to your controller class
Example:
[Route("api/[controller]/[action]")]
[ApiController]
public class MySampleController : ControllerBase
{
private readonly ILogger<MySampleController> _logger;
//constructor
public MySampleController (
ILogger<MySampleController> logger)
{
_logger = logger;
}
//sample Action
[HttpPost]
public async Task<ActionResult<Payload>> PostEmployeeInfo([FromBody]JObject notification)
{
try
{
_logger.LogInformation("Post Employee Info Success for :{0} {1}", paramOne, paramTwo);
}
catch(Exception ex)
{
_logger.LogError("Error - Post Employee: Message: {0} StackTrace: {1}", ex.Message, ex.StackTrace);
}
}
}
How is the rolling file implemented ?
In the above code we have already specified it in the Log configuration section. See below code block:
.WriteTo.File("C:\\ProgramData\\MyWebApplication\\MyLog.txt",
rollOnFileSizeLimit: true,
fileSizeLimitBytes: 2000,
retainedFileCountLimit: 5)
This states that we are rolling the files based on a maximum file size limit. In this example I have specified the size to be only 2KB, But in a practical scenario a 5MB file size would be fine. I have set the number of rolling files to 5. So there will be a maximum of 5 files at a given time. The file containing the oldest logs will be removed when a new file is created.
How is the Noise removed ?
Serilog has many log levels:
Level
|
Usage
|
Verbose
|
Verbose
is the noisiest level, rarely (if ever) enabled for a production app.
|
Debug
|
Debug is used for internal system events that are not necessarily
observable from the outside, but useful when determining how something
happened.
|
Information
|
Information
events describe things happening in the system that correspond to its
responsibilities and functions. Generally these are the observable actions
the system can perform.
|
Warning
|
When service is degraded, endangered, or may be behaving outside of
its expected parameters, Warning level events are used.
|
Error
|
When
functionality is unavailable or expectations broken, an Error event is used.
|
Fatal
|
The most critical level, Fatal events demand immediate attention.
|
Normally you would set the logs minimum level to Information.
Example:
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
There is a catch here. Serilog starts to log all Information level logs. It logs information generated related to AspNetCore. I also have the Entity Framework Core in the solution. So now I also get Information level logs generated regarding EntityFrameworkCore. A sample log would look like:
But we don't need all this noise in he log all the time. So we have to specify it when we configure the logging. The following lines overrides the default settings.
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
It sets the logs generated regarding AspNetCore and EntityFrameworkCore to a higher level which is "Warning". So you would get only the warning and Fatal information from these two components. Now the log will be clearer and you can easily spot the information logs which you place in the Controller using the _logger.LogInformation() method.
Resulting file structure:
MyLog_003.txt
MyLog_004.txt
MyLog._005txt
MyLog_006.txt
MyLog_007.txt
Note that the initial log created will be like "MyLog.txt". Then increment as MyLog_001.txt. As the log files are rolling it will increase the file numbering and remove the older files.