mtpultz
mtpultz

Reputation: 18328

.Net Core 3.1 Using Serilog with Microsoft.Extensions.Logger

In this application I've pulled in and setup Serilog, which works for exceptions, and I wanted to use the Microsoft's Logger with Serilog, but I can't seem to figure out how to DI it into services without this error during dotnet build.

I'm not sure what I'm missing to have ILogger be using an instance of Serilog?

Error on dotnet build:

[13:56:21 FTL] Host terminated unexpectedly
System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Unable to resolve service for type 'Microsoft.Extensions.Logging.ILogger' while attempting to activate 'App.Services.MyService'.) 

Dependency Injection into Service:

using Microsoft.Extensions.Logging;

public class MyService : BaseService
{
    private readonly ILogger _logger;

    public MyService(
        ILogger logger)
        : base(context, httpContext)
    {
        _logger = logger;
    }
    
    // ... Removed for brevity
}

Implementation

public static int Main(string[] args)
{
    CreateLogger();

    try
    {
        Log.Information("Starting web host");
        CreateHostBuilder(args)
            .Build()
            .Run();
        return 0;
    }
    catch (Exception ex)
    {
        Log.Fatal(ex, "Host terminated unexpectedly");
        return 1;
    }
    finally
    {
        // Ensure buffered logs are written to their target sink
        Log.CloseAndFlush();
    }
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>())
        .UseSerilog();

private static void CreateLogger()
{
    string path = PrimeConstants.LOG_FILE_PATH;

    try
    {
        if (isDevelopment())
        {
            Directory.CreateDirectory(path);
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("Creating the logging directory failed: {0}", e.ToString());
    }

    var name = Assembly.GetExecutingAssembly().GetName();
    var outputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}";

    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Information()
        .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
        .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
        .MinimumLevel.Override("System", LogEventLevel.Warning)
        .Enrich.FromLogContext()
        .Enrich.WithMachineName()
        .Enrich.WithProperty("Assembly", $"{name.Name}")
        .Enrich.WithProperty("Version", $"{name.Version}")
        .WriteTo.Console(
            outputTemplate: outputTemplate,
            theme: AnsiConsoleTheme.Code)
        .WriteTo.Async(a => a.File(
            $@"{path}/prime.log",
            outputTemplate: outputTemplate,
            rollingInterval: RollingInterval.Day,
            shared: true))
        .WriteTo.Async(a => a.File(
            new JsonFormatter(),
            $@"{path}/prime.json",
            rollingInterval: RollingInterval.Day))
        .CreateLogger();
}

Upvotes: 3

Views: 4492

Answers (1)

Kirk Larkin
Kirk Larkin

Reputation: 93283

ILogger isn't available to DI. You can use one of the following approaches:

  1. Inject ILogger<TCategoryName>:

     public class MyService : BaseService
     {
         private readonly ILogger _logger;
    
         public MyService(ILogger<MyService> logger)
             : base(context, httpContext)
         {
             _logger = logger;
         }
    
         // ...
     }
    
  2. Inject ILoggerFactory and use its CreateLogger method:

     public class MyService : BaseService
     {
         private readonly ILogger _logger;
    
         public MyService(ILoggerFactory loggerFactory)
             : base(context, httpContext)
         {
             _logger = loggerFactory.CreateLogger("<YOUR_CATEGORY_NAME>");
         }
    
         // ...
     }
    

I'd recommend option #1, unless you want full control over the log category. See the docs to learn more about what that means:

That category is included with each log message created by that instance of ILogger.

Upvotes: 7

Related Questions