Search code examples
c#logging.net-5.net-6.0

MS Logger factory and Serilog issue getting log messages to file


I've been building a tool to resolve some data related issues. Bottom line this is in .Net 5.0 with future to port to .net 6.0.

I've used Serilog in the past without issues. But as part of my "tool" I need to use a TCP Server. I've selected to use WastonTCP as it simply works.

The problem is that it uses the MS Logger factory and defaults output to Console. Not a production desired result.

When I run the app now I get the start and stop messages in the log but none of these show below enter image description here

These messages I want in the serilog. Here is the program.cs code:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Enrichers;
using Serilog.Events;
using System;

namespace PostDataService
{
  public class Program
  {

    public static void Main(string[] args)
    {
      const string _logTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff}\t{EnvironmentUserName}\t[{Level:u4}]\t<{ThreadId}>\t{Message:lj}{NewLine}{Exception}";
      var loggerConfig = new LoggerConfiguration()
        .MinimumLevel.Override("Microsoft", LogEventLevel.Verbose)
        .Enrich.WithThreadId()
        .Enrich.WithEnvironmentUserName()
        .WriteTo.File("./App_Data/logs/USPS.Log",
        fileSizeLimitBytes: 524288000,
        outputTemplate: _logTemplate);

      Log.Logger = loggerConfig.CreateLogger();
      try
      {
        Log.Write(LogEventLevel.Information, "Start USPS Data Server");
        CreateHostBuilder(args).Build().Run();
      }
      catch (Exception ex)
      {
        Log.Fatal(ex, "Host terminated unexpectedly");
      }
      finally
      {
        Log.Information("USPS Server stopped");
        Log.CloseAndFlush();
      }
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =>
            {
              services.AddHostedService<Worker>();
            });

  }
}

I'm very new to MS logger tooling so not sure if that is the issue and/or the fact that I'm running the TCP server as a background worker that is at fault.

Here is the ExecuteAsync method from worker.cs it generates the first message in the screen shot.

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
      //_logger.LogInformation("Worker running at: {time} {threadid}", DateTimeOffset.Now, Thread.CurrentThread.ManagedThreadId);
      while (!stoppingToken.IsCancellationRequested)
      {
        if (_msgcnt == 0 || (_msgcnt % 500 == 0) )
        {
          _logger.LogInformation("Worker running at: {time} {threadid}", DateTimeOffset.Now, Thread.CurrentThread.ManagedThreadId);
        }
        //_logger.LogInformation("Worker running at: {time} {threadid}", DateTimeOffset.Now, Thread.CurrentThread.ManagedThreadId);
        _msgcnt++;
        await Task.Delay(500, stoppingToken);
      }
      //_Server.Stop();
    }

Here is the appsettings.Developement.json (same as appsettings.json):

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "FormatterOptions": {
      "SingleLine":  true
    }
  }
}

Solution

  • When you do Log.Logger = loggerConfig.CreateLogger(); you are configuring the global static Serilog.Log object. It will work as long as you call it via Log.Write() etc.

    Your problem starts from the fact that, in your worker, I'm guessing you're using an injected ILogger<>. This will inject an MS ILogger. Unfortunately you have not told the MS ILogger to use serilog.

    Linking the two should be straightforward (as per the instructions); you just tell the host builder you want to use Serilog:

    public static IHostBuilder CreateHostBuilder(string[] args) =>
      Host.CreateDefaultBuilder(args)
        .UseSerilog() // <- this right here
        .ConfigureServices((hostContext, services) => { ... });
    

    Bonus: You may later move your config to appsettings.json using Serilog.Settings.Configuration, once you get the code-first config above to work. Would save you from rebuilding every time you want to log/filter out certain things.