Serilog 和 .NET Core 2.1 HostBuilder 配置
Serilog and .NET Core 2.1 HostBuilder Configuration
我正在使用 .NET Core 2.1 HostBuilder class 设置和 运行 GRPC 服务器,但无法正确配置 SeriLog 以便 .NET Core 使用它日志记录管道以及我应用程序其他地方的可用(通过依赖注入)。
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;
}
}
问题是我需要调用 loggingBuilder.AddSerilog()
才能使用在上面几行的 DI 服务配置中注册的单例 ILogger
。
我意识到我可以直接调用 BuildLogger()
来获取 ILogger
实例并使用 DI 服务配置注册该实例,但似乎我不应该这样做。我正在寻找一种方法,从 .ConfigureLogging()
方法中访问 ServiceProvider
实例,这样我就可以获得注册的 ILogger
可能像
serviceProvider.GetRequiredService<ILogger>();
并将其传递给 AddSerilog()
调用。有什么想法吗?
根据 .NET Core 2.0+ 的 repo 文档,在提供的 loggingBuilder
上调用 AddSerilog()
并确保首先配置 Serilog:
//...
private static async Task Main(string[] args) {
Log.Logger = new LoggerConfiguration()
//...
.CreateLogger();
var hostBuilder = new HostBuilder()
.ConfigureServices((hostContext, services) => {
services.AddLogging(loggingBuilder =>
loggingBuilder.AddSerilog(dispose: true));
// other services here
});
await hostBuilder.RunConsoleAsync();
}
//...
试试 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();
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
您可以通过 ILoggingBuilder.Services.BuildServiceProvider()
从 ConfigureLogging()
方法中访问 ServiceProvider
。像这样:
//...
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(
loggingBuilder
.Services.BuildServiceProvider().GetRequiredService<ILogger>(),
dispose: true));
await hostBuilder.RunConsoleAsync();
}
...//
这里有一个示例,展示了如何执行此操作,包括使用 appsettings.json 配置 serilog 以及如何使用 ILogger 获取日志记录而无需手动注入它,如标记的答案所示,以及您如何也可以IO选项:
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();
}
}
}
.Net6 中的一些变化
这是我的 program.cs
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
builder.Host.UseSerilog( Log.Logger);
var app = builder.Build();
我正在使用 .NET Core 2.1 HostBuilder class 设置和 运行 GRPC 服务器,但无法正确配置 SeriLog 以便 .NET Core 使用它日志记录管道以及我应用程序其他地方的可用(通过依赖注入)。
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;
}
}
问题是我需要调用 loggingBuilder.AddSerilog()
才能使用在上面几行的 DI 服务配置中注册的单例 ILogger
。
我意识到我可以直接调用 BuildLogger()
来获取 ILogger
实例并使用 DI 服务配置注册该实例,但似乎我不应该这样做。我正在寻找一种方法,从 .ConfigureLogging()
方法中访问 ServiceProvider
实例,这样我就可以获得注册的 ILogger
可能像
serviceProvider.GetRequiredService<ILogger>();
并将其传递给 AddSerilog()
调用。有什么想法吗?
根据 .NET Core 2.0+ 的 repo 文档,在提供的 loggingBuilder
上调用 AddSerilog()
并确保首先配置 Serilog:
//...
private static async Task Main(string[] args) {
Log.Logger = new LoggerConfiguration()
//...
.CreateLogger();
var hostBuilder = new HostBuilder()
.ConfigureServices((hostContext, services) => {
services.AddLogging(loggingBuilder =>
loggingBuilder.AddSerilog(dispose: true));
// other services here
});
await hostBuilder.RunConsoleAsync();
}
//...
试试 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();
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
您可以通过 ILoggingBuilder.Services.BuildServiceProvider()
从 ConfigureLogging()
方法中访问 ServiceProvider
。像这样:
//...
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(
loggingBuilder
.Services.BuildServiceProvider().GetRequiredService<ILogger>(),
dispose: true));
await hostBuilder.RunConsoleAsync();
}
...//
这里有一个示例,展示了如何执行此操作,包括使用 appsettings.json 配置 serilog 以及如何使用 ILogger 获取日志记录而无需手动注入它,如标记的答案所示,以及您如何也可以IO选项:
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();
}
}
}
.Net6 中的一些变化
这是我的 program.cs
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
builder.Host.UseSerilog( Log.Logger);
var app = builder.Build();