When you look at solutions for Dependency Injection and Serilog on .NET projects, most documentation and blogs refers to the IHost model. It does not matter much if for current .NET 6 or other versions of .NET Core. This is my favorite way for applications providing REST APIs since .NET Core 2.1.
I first defined a BuildLogger() method to configure Serilog with min log level and add all my enrichers/sinks I need.
So my Program.Main method used to look like:
Log.Logger = LoggerBuilder.BuildLogger();
var builder = Host.CreateDefaultBuilder(args).UseSerilog(); // serilog injected in Host.
builder.ConfigureServices(services => services.AddMyServices());
using var source = new CancellationTokenSource();
await builder.Build().RunAsync(source.Token).ConfigureAwait(false);
All fine.
Question is: how to do reuse DI and Serilog without using the IHost model from .NET 6? My today's user case if for a console app which is only running a few tests and then close, and still reusing some parts I wrote for my previous apps.
Here's a minimum working example in a .NET 6 console app that uses top-level statements. It uses Serilog with dependency injection and logs to a text file:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
var serviceCollection = new ServiceCollection()
.AddLogging(builder => builder.AddSerilog(new LoggerConfiguration()
.WriteTo.File("Logs/log.txt")
.CreateLogger()))
.BuildServiceProvider();
var logger = serviceCollection.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Hello, world!");
You'll need these packages from NuGet:
Update: Although dependency injection is in vogue these days, if you just want the simplest possible solution that logs to a file, here it is:
using Serilog;
Log.Logger = new LoggerConfiguration()
.WriteTo.File("Logs/log.txt")
.CreateLogger();
Log.Logger.Information("Hello, world!"); // can call from anywhere in project
You'll still need the Serilog.Sinks.File package above.
So instead of the above, I defined that
Log.Logger = LoggerBuilder.BuildLogger();
await using var serviceProvider = new ServiceCollection()
.AddMyServices()
.AddLogging(logBuilder => logBuilder.AddSerilog()) // attach serilog.
.BuildServiceProvider()
RunTests(serviceProvider);
This seems to work as expected.
The trick with AddLogging/AddSerilog() instead of UseSerilog() might be helpful for others!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With