I'm using the .NET Core 2.1 HostBuilder class to set up and run a GRPC server and am having trouble getting SeriLog properly configured so that it is used by the .NET Core logging pipeline as well as available (via dependency injection) elsewhere in my app.
class Program
{
private static async Task Main(string[] args)
{
var hostBuilder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<ILogger>(BuildLogger);
// other services here
})
.ConfigureLogging((hostContext, loggingBuilder) =>
loggingBuilder.AddSerilog(dispose: true));
await hostBuilder.RunConsoleAsync();
}
private static ILogger BuildLogger(IServiceProvider provider)
{
// create a (global) logger
Log.Logger = new LoggerConfiguration()
...
.CreateLogger();
return Log.Logger;
}
}
The problem is that I need the call to loggingBuilder.AddSerilog()
to use the singleton ILogger
that was registered with the DI services configuration a few lines above.
I realize I could directly call BuildLogger()
to get the ILogger
instance and register that instance with the DI service configuration, but it seems like I shouldn't have to. What I'm looking for is a way, from within the .ConfigureLogging()
method to access a ServiceProvider
instance so I can get the registered ILogger
maybe like
serviceProvider.GetRequiredService<ILogger>();
and pass that to the AddSerilog()
call. Any ideas?
Serilog is a third-party, open-source library that integrates nicely with ASP.NET Core and allows developers to easily log-structured event data to the console, to files, and various kinds of log targets.
Serilog is a . NET library that provides diagnostic logging to files, the console, and almost everywhere you would like. Serilog can be used in classic . NET Framework applications and for applications running on the latest and greatest .
Try the new package now available in Serilog - https://github.com/serilog/serilog-extensions-hosting.
public static IHost BuildHost(string[] args) =>
new HostBuilder()
.ConfigureServices(services => services.AddSingleton<IHostedService, PrintTimeService>())
.UseSerilog() // <- Add this line
.Build();
Here is a sample that shows how to do this including using appsettings.json for configuring serilog and how to get the logging using ILogger without having to manually inject it as the marked answer shows and how you can also you IOptions:
public class Settings
{
public string Sample { get; set; }
}
public class Service : IHostedService
{
private readonly ILogger<Service> _logger;
private Settings _settings;
public Service(ILogger<Service> logger,
Settings settings)
{
_logger = logger;
_settings = settings;
}
public Task StartAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
class Program
{
static async Task Main(string[] args)
{
var host = new HostBuilder()
.ConfigureHostConfiguration(builder =>
{
builder.AddJsonFile("hostsettings.json", optional: true);
})
.ConfigureAppConfiguration((hostContext, builder) =>
{
builder.AddJsonFile("appsettings.json");
builder.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true);
})
.ConfigureLogging((hostContext, builder) =>
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(hostContext.Configuration).CreateLogger();
builder.AddConfiguration(hostContext.Configuration.GetSection("Logging"));
builder.AddSerilog(dispose: true);
})
.ConfigureServices((hostContext, services) =>
{
var settings = hostContext.Configuration.GetSection("Configuration").Get<Settings>();
services.AddSingleton(settings);
services.AddHostedService<Service>();
services.AddLogging();
services.AddOptions();
})
.Build();
using (host)
{
await host.StartAsync();
await host.WaitForShutdownAsync();
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With