7

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?

5
  • You need to use a dependency injection framework. ASP.NET Core just happens to have a built-in system Commented Feb 21, 2021 at 16:41
  • @Xerillio, but there isn't in .NET Console App. Commented Feb 21, 2021 at 16:46
  • 1
    Exactly. So you need add a DI framework to your project (CastleWindsor, Ninject, Spring.NET, Autofac...) Commented Feb 21, 2021 at 16:48
  • @Xerillio, Autofac seems to be the most used, but I gotta learn how to do it rn Commented Feb 21, 2021 at 17:13
  • This isn't really a Serilog question. There are lots of Q&As about how to add DI to a console app. Commented Feb 21, 2021 at 17:21

3 Answers 3

11

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>
Sign up to request clarification or add additional context in comments.

Comments

5

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();

6 Comments

To use AddSerilog method you also need Serilog.Extensions.Logging nuget package.
Thanks for your answer! Can you give a complete example with an example class where you DI it
To be fair, this DI framework isn't any more built-in than the other DI frameworks, but it's probably more lightweight (just a guess though).
Use Serilog.Extensions.Hosting for a similar UseSerilog method on the host builder. No need to call AddLogging and it sets up all the loggers and providers correctly for a Host
@Xerillio Actually you are right. As .net core functionality is separated into packages, the DI isn't a built in feature anymore.
|
2

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!");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.