Logging
Logs are facts emitted by your application especially when it is running in production.
Structured logging is a way to give facts a shape so that you can query logs better.
Serilog is a structured logging library for .NET and it is one of the most popular logging libraries in .NET.
But how to use Serilog with the new .NET 8 Worker template?
Use Serilog with .NET 8 Worker or Hosted Service
You can create a new .NET 8 Worker or Hosted Service using the following command.
dotnet new worker -n MyWorker
Then install the following NuGet packages.
dotnet add package Serilog
dotnet add package Serilog.Extensions.Hosting
dotnet add package Serilog.Sinks.File
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Settings.Configuration
Then change the Program.cs
file to look like this.
I would appreciate if you can subscribe to my YouTube Channel.
I know it's a big ask, but it will help me to keep writing and producing awesome content for you.
Ok, lets do it YouTube Channel.
var builder = Host.CreateApplicationBuilder(args);
//Clear Providers
builder.Logging.ClearProviders();
//Read appsettings.json
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.CreateLogger();
// add the provider
builder.Logging.AddSerilog();
builder.Services.AddHostedService<Worker>();
var host = builder.Build();
host.Run();
And your appsettings.json
file should look like this.
{
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "logs/log.txt",
"rollingInterval": "Day",
"retainedFileCountLimit": 7
}
}
],
"Properties": {
"Application": "YourWorkerName"
}
}
}
Before .NET 8, you were using Host.CreateDefaultBuilder(args)
to create the host builder, but now you are using Host.CreateApplicationBuilder(args)
.
With the Host.CreateDefaultBuilder(args)
you were able to use the UseSerilog()
extension method,
but with the Host.CreateApplicationBuilder(args)
you have to use the AddSerilog()
extension method.
The only thing different Host.CreateApplicationBuilder(args)
is doing that it is already adding the
Logger Factory and Configuration to the builder, so you don't have to do it manually.
It does in when you call the CreateApplicationBuilder(args)
method, under the hood it calls the AddLogging()
method
which then calls the extension method to add the required services Source Code
Thus when you call the AddSerilog()
extension method, it is only adding the logging provider which is then used by the factory to create the logger.
public static IServiceCollection AddLogging(this IServiceCollection services, Action<ILoggingBuilder> configure)
{
ThrowHelper.ThrowIfNull(services);
services.AddOptions();
services.TryAdd(ServiceDescriptor.Singleton<ILoggerFactory, LoggerFactory>());
services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(Logger<>)));
services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<LoggerFilterOptions>>(
new DefaultLoggerLevelConfigureOptions(LogLevel.Information)));
configure(new LoggingBuilder(services));
return services;
}
Feedback
I would love to hear your feedback, feel free to share it on Twitter.