nop
nop

Reputation: 6331

How to dependency inject Serilog into the rest of my classes in .NET Console App

I'm getting started with Serilog but I don't know how to dependency inject the ILogger into my classes. It's easy if I was using ASP.NET Core 5, but I'm using a .NET Core Console App. How can I do similarly?

Before with log4net:

public class TestStrategy
{
    private static readonly ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.Name);

    ...
}

My Serilog logger creation:

var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

var logger = new LoggerConfiguration()
    .ReadFrom.Configuration(configuration)
    .CreateLogger();

Do I have to DI logger into all classes?

Upvotes: 7

Views: 14124

Answers (3)

Tawab Wakil
Tawab Wakil

Reputation: 2313

Do I have to DI logger into all classes?

No, you don't. Although some may not prefer it, you can choose not to use DI at all for this and just configure the global logger:

Log.Logger = new LoggerConfiguration()
    .ReadFrom.Configuration(configuration)
    .CreateLogger();

The global logger is automatically accessible to any class that references the Serilog namespace, and can be called like this to log an entry:

Log.Logger.Information("Hello, world!");

Upvotes: 2

Hossein Salmanian
Hossein Salmanian

Reputation: 763

The built-in DI Mechanism in a .Net Core Console Application is available using Microsoft.Extensions.DependencyInjection package after DI package installation, configuring services is possible via instantiating a ServiceCollection instance. Serilog logging functionality can be added as follows.

var serviceProvider = new ServiceCollection()
                      .AddSingleton<IFoo, Foo>()
                      .AddSingleton<IBar, Bar>()
                      .AddLogging(builder =>
                      {
                          var logger = new LoggerConfiguration()
                          .MinimumLevel.Debug()
                          .WriteTo.Console()
                          .CreateLogger();

                          builder.AddSerilog(logger);
                      })
                      .BuildServiceProvider();

to have DI configurations encapsulated, configuration can be implemented in a class.

public class Startup
        {
            private ServiceProvider _serviceProvider;
            public Startup()
            {
                ConfigureServices();
            }

            private void ConfigureServices()
            {
                _serviceProvider = new ServiceCollection()
                      .AddSingleton<IFoo, Foo>()
                      .AddSingleton<IBar, Bar>()
                      .AddLogging(builder =>
                      {
                          var logger = new LoggerConfiguration()
                          .MinimumLevel.Debug()
                          .WriteTo.Console()
                          .CreateLogger();

                          builder.AddSerilog(logger);
                      })
                      .BuildServiceProvider();
            }

            public ServiceProvider Provider { get { return _serviceProvider; } }
        }

Then in the program main method, a new instance of Startup class should be created and starting point implementation can call using the provider property of the startup instance.

var startup = new Startup();
        startup.Provider.GetService<IFoo>().DoSomthing();

Upvotes: 5

Melchia
Melchia

Reputation: 24234

Here's an example using .net 5 using Microsoft.Extensions.DependencyInjection;:

Program.cs:

namespace dotnet.console.app
{
    using System.Threading.Tasks;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using Serilog;
    class Program
    {
        static Task Main(string[] args) =>
            CreateHostBuilder(args).Build().RunAsync();

        static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((_, services) =>
                    services.AddHostedService<Worker>()
                            .AddLogging(builder =>
                            {
                                var logger = new LoggerConfiguration()
                                            .MinimumLevel.Debug()
                                            .WriteTo.Console()
                                            .CreateLogger();

                                builder.AddSerilog(logger);
                            }));
    }
}

Worker.cs

namespace dotnet.console.app
{
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;

    public class Worker : BackgroundService
    {
        private ILogger<Worker> _logger;

        public Worker(ILogger<Worker> logger)
        {
            this._logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                this._logger.LogInformation("Hello, Serilog!");
                await Task.Delay(1000, stoppingToken);
            }
        }
    }
}

csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
    <PackageReference Include="Serilog" Version="2.10.0" />
    <PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
    <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
    <PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
  </ItemGroup>

</Project>

Upvotes: 11

Related Questions