public class Startup
{
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
loggerFactory.AddFile(logFilePath1);
services.AddSingleton<ILoggerFactory>(loggerFactory);
loggerFactory.AddFile(logFilePath2);
services.AddSingleton<ILoggerFactory>(loggerFactory);
}
}
在startup.cs
类中,我创建了两个loggers。由于它有两个记录器,如何在控制器中设置Ilogger数据?可以用正常方式吗?还是在控制器内登录时传递记录器文件名有其他方法吗?
答案 0 :(得分:1)
好,因此您希望在一个控制器中有两个不同的记录器,并且希望这两个记录器记录到不同的文件。 .NET Core日志记录对此情况没有很好的支持,因此需要一点技巧来实现此目的。每当我发现自己在使用的框架中遇到很多阻力时,都会重新考虑是否要尝试做的事是个好主意,以及是否应该使用另一个框架,以便您可能想做相同。考虑到这一点,这里是实现您想要的方法。
记录器可以按类别标识。在您的情况下,您希望一个控制器具有两个不同的记录器,因此您必须使用ILoggerFactory
来创建记录器(您可以使用通用的ILogger<T>
界面,但由于您需要两个不同的界面而变得有点奇怪T
的类型:
public class MyController : Controller
{
private readonly ILogger logger1;
private readonly ILogger logger2;
public Controller1(ILoggerFactor loggerFactory)
{
logger1 = loggerFactory.Create("Logger1");
logger2 = loggerFactory.Create("Logger2");
}
}
记录器的类别为Logger1
和Logger2
。
默认情况下,每个记录器都将记录到所有已配置的提供程序。您希望一个类别的记录器登录到一个提供程序,而另一个类别的记录器登录到另一个提供程序。
虽然您可以基于类别,提供者和日志级别创建过滤器,但问题是您想对两个类别使用相同的提供者。提供者通过其类型进行标识,因此您不能创建以提供者的特定实例为目标的规则。如果为文件提供者创建规则,它将影响所有配置的文件提供者。
这就是黑客活动开始的地方:您必须创建自己的提供程序类型,这些提供程序类型链接到文件,以便能够在每个文件上进行过滤。
.NET Core不支持记录文件,因此您需要第三方提供程序。您尚未指定要使用的提供程序,因此在此示例中,我将使用Serilog文件接收器和Serilog提供程序,以允许您将Serilog记录器插入.NET Core记录框架。
要能够过滤提供程序,您必须创建自己的提供程序。幸运的是,从SerilogLoggerProvider
派生出来很容易做到:
class SerilogLoggerProvider1 : SerilogLoggerProvider
{
public SerilogLoggerProvider1(Serilog.ILogger logger) : base(logger) { }
}
class SerilogLoggerProvider2 : SerilogLoggerProvider
{
public SerilogLoggerProvider2(Serilog.ILogger logger) : base(logger) { }
}
这两个提供程序没有添加任何功能,但是允许您创建针对特定提供程序的过滤器。
下一步是创建两个不同的Serilog记录器,以记录到不同的文件中:
var loggerConfiguration1 = new LoggerConfiguration()
.WriteTo.File("...\1.log");
var loggerConfiguration2 = new LoggerConfiguration()
.WriteTo.File("...\2.log");
var logger1 = loggerConfiguration1.CreateLogger();
var logger2 = loggerConfiguration2.CreateLogger();
您可以通过调用扩展方法Main
配置.ConfigureLogging
的登录记录:
.ConfigureLogging((hostingContext, loggingBuilder) =>
{
loggingBuilder
.AddProvider(new SerilogLoggerProvider1(logger1))
.AddFilter("Logger1", LogLevel.None)
.AddFilter<SerilogLoggerProvider1>("Logger1", LogLevel.Information)
.AddProvider(new SerilogLoggerProvider2(logger2))
.AddFilter("Logger2", LogLevel.None)
.AddFilter<SerilogLoggerProvider2>("Logger2", LogLevel.Information);
})
添加每个提供程序(与特定文件关联),然后为每个提供程序配置两个过滤器。我发现过滤器评估规则很难解释,但是添加的两个过滤器-一个带有LogLevel.None
和另一个带有LogLevel.Information
的过滤器实际上达到了确保正确路由两个不同类别的日志消息的预期结果给两个不同的提供商。如果添加了第三个提供程序,它将不受这些过滤器的影响,并且来自这两个类别的消息将由第三个提供程序记录。