Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET DependencyInjection and Serilog without using IHost (for console app)

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.

like image 513
EricBDev Avatar asked Oct 22 '25 00:10

EricBDev


2 Answers

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:

  • Microsoft.Extensions.DependencyInjection
  • Serilog.Extensions.Logging
  • Serilog.Sinks.File

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.

like image 50
Tawab Wakil Avatar answered Oct 24 '25 13:10

Tawab Wakil


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!

like image 33
EricBDev Avatar answered Oct 24 '25 13:10

EricBDev