Search code examples
c#serilog

Why is it creted two log files with serilog in a windows service application?


I have a windows service that hosts a worker service.

But I have a log for the program.cs code and other file for the worker service code.

My code is this:

program.cs:

try
{
    Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);


    var builder = Host.CreateApplicationBuilder(args); 
    builder.Services
        .AddSerilog(lc => lc.ReadFrom.Configuration(builder.Configuration))
        .AddHostedService<Worker>()
        .InstalarServicios(builder.Configuration);

    Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(builder.Configuration)
                .Enrich.FromLogContext()
                //.CreateBootstrapLogger()
                .CreateLogger()
                ;

    Log.Information("Aplicación iniciada.");
    var host = builder.Build();
    await host.RunAsync();
}
catch(Exception ex)
{
    Log.Fatal(ex, "Se ha producido un error en la aplicación y se cerrará.");
}
finally
{
    Log.Information("Aplicación finalizada.");
    Log.CloseAndFlush();
}

This is the worker:

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

    public Worker(ILogger<Worker> logger)
    {
        _logger = logger;
    }
    
    public override Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Servicio iniciado.");
        return base.StartAsync(cancellationToken);
    }
}

And this is the .json file:

"Serilog": {
  "MinimumLevel": {
    "Default": "Information",
    "Override": {
      "Microsoft": "Information",
      "System": "Warning"
    }
  },

  "WriteTo": [
    {
      "Name": "File",
      "Args": {
        "path": "./logs/log-.txt",
        "rollingInterval": "Day"
      }
    },
    {
      "Name": "Seq",
      "Args": { "serverUrl": "http://localhost:5341" }
    }
  ]
}

How could I have all the log in a unique file?

Thanks.


Solution

  • The code sets up Serilog logging twice. Once with :

    builder.Services
        .AddSerilog(lc => lc.ReadFrom.Configuration(builder.Configuration))
    

    and once by creating a new static logger with :

    Log.Logger = new LoggerConfiguration()...
    

    To use the static logger everywhere, use either AddSerilog or UseSerilog without additional parameters. The landing page example of the Serilog.Extensions.Hosting package shows exactly this use case:

    using Serilog;
    
    Log.Logger = new LoggerConfiguration()
        .Enrich.FromLogContext()
        .WriteTo.Console()
        .CreateLogger();
    
    try
    {
        Log.Information("Starting host");
    
        var builder = Host.CreateApplicationBuilder(args);
        builder.Services.AddHostedService<PrintTimeService>();
        builder.Services.AddSerilog();
    
        var app = builder.Build();
        
        await app.RunAsync();
        return 0;
    }
    catch (Exception ex)
    {
        Log.Fatal(ex, "Host terminated unexpectedly");
        return 1;
    }
    finally
    {
        await Log.CloseAndFlushAsync();
    }
    

    This is mentioned in the ILogger parameter help for the AddSerilog(IServiceCollection,ILogger,bool,providers) method :

    • logger: The Serilog logger; if not supplied, the static Serilog.Log will be used.