1
votes

I would like to know how to manage and best way to bring Serilog instance from a console app to a StartUp class that configures a webhost.

Scenario:

I ve got a Main class from a console app where I configure a logger (serilog). Namespace 1

 static void Main(string[] args)
    {
        DateTime Date = new DateTime.Now;
           Log.Logger = = new LoggerConfiguration()
         .MinimumLevel.Debug()
         .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
         .Enrich.FromLogContext()
         .WriteTo.Console()
         .WriteTo.File($"Log-Startup-{Date}.txt", rollingInterval: 
RollingInterval.Day, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff 
zzz}")
         .CreateLogger();

[...]

`StaticLauncherClass.Launch(args, config, Log.Logger)`;

Notice after this I'm just doing a call to static class method and I pass the Logger.

Static class is supposed to configure a Webhost as typical webhost app in net core 2. Launch Method does something like. Namespace2

      public static IConfiguration Config { get; private set; }


public static void Launch(string[] args, IConfigurationSection config, 
ILogger logger)
        {
            Log.Logger = logger;
            Config = config;
            CreateWebHostBuilder(args).Build().Run();
        }


      public static IWebHostBuilder CreateWebHostBuilder(string[] args)
        {
            Log.Information("Starting web host");
  Serilog.ILogger _logger = Log.Logger;
            try
            {
                return CreateWebhostBuilder(args)
                        // Use Serilog
                        // Evitar inicio de hospedaje
                        .UseSerilog()
                        .UseSetting(WebHostDefaults.PreventHostingStartupKey, 
"true")
                    .ConfigureServices(svc =>
{
    svc.AddSingleton(_logger);
})
                        .UseStartup<Startup>();
            }
[...]
}

In same class, finally CreateWebhostBuilder(args) configure webhost

 var builder = new WebHostBuilder()
           .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                var env = hostingContext.HostingEnvironment;

                if (env.IsDevelopment())
                {
                    var appAssembly = Assembly.Load(new 
AssemblyName(env.ApplicationName));
                    if (appAssembly != null)
                    {
                        config.AddUserSecrets(appAssembly, optional: true);
                    }
                }

                if (args != null)
                {
                    config.AddCommandLine(args);
                }
                config.SetBasePath(Directory.GetCurrentDirectory());
                // Add settings to bootstrap EF config.
            })

            .UseIISIntegration()
            .UseDefaultServiceProvider((context, options) =>
            {
                options.ValidateScopes = 
context.HostingEnvironment.IsDevelopment();
            });


    return builder;

And then my question si how with this scenario I can use my Logger in Startup used class. My intention is to globalize logger the best and easier way posible. What solutions you purpose?

 internal class Startup {
???
???
 public Startup(IConfiguration config, IHostingEnvironment environment)
    {       
        ???
    }

   public void ConfigureServices(IServiceCollection services)
    {
        Console.WriteLine("Startup");
        Log.Information("Startup: Configure services");
    }
}

Startup class is writing Console.WriteLine content but does not write Log.Information content. Edit: Actual status, bring service to Startup but does not apply configuration provided to log in file. I think it acts just by default.

1
It seems to me that, in your scenario, is totally advisable to just use the static Serilog.Log.Logger property. I do not see any advantage in using a scoped instance inside your Program class.Federico Dipuma
@FedericoDipuma that is true. I ve changed code. But how could I pass (and Log) from startup class?Sam
Now that you have the static instance you can just use Log.Info() (and the other methods) from your startup classFederico Dipuma
The point is that I am doing Log.Information("Startup: Configure services"); from ConfigureServices method and it does not write anything in the console or file and I dont know what I am missing.Sam
In your post you didn't add all the information needed to find your issue, but from the github repository you posted earlier is clear that you are executing Log.CloseAndFlush(); right after creating the WebHostBuilder (which, of course, will close the current logger immediatly). That's the reason you do not see any log after. Please add the complete code to your question.Federico Dipuma

1 Answers

2
votes

You can register your logger in ConfigureServices method:

var builder = new WebHostBuilder()
            .UseKestrel()

            ...

            .UseIISIntegration()
            .ConfigureServices(servicesCollection =>
            {
                servicesCollection.AddSingleton<Serilog.ILogger>(logger);              
            })
            .UseDefaultServiceProvider((context, options) =>
            {
                options.ValidateScopes = 
context.HostingEnvironment.IsDevelopment();
            });