asp.net 如何使用LoggerFactory在.net core中添加两个日志文件

j9per5c4  于 5个月前  发布在  .NET
关注(0)|答案(2)|浏览(73)
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类中,我创建了两个记录器。既然它有两个记录器,我如何在控制器中设置Ilogger数据?它可以使用正常的方式吗?或者当在控制器中记录时,是否有任何不同的方式来传递记录器文件名?

gstyhher

gstyhher1#

好吧,所以你想在一个控制器中有两个不同的日志记录器,你想让这两个日志记录器记录到不同的文件。.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");
    }
}

字符串
记录器的类别为Logger1Logger2
默认情况下,每个记录器将记录到所有配置的提供程序。您希望具有一个类别的记录器记录到一个提供程序,而具有另一个类别的记录器记录到另一个提供程序。
虽然您可以创建基于类别、提供程序和日志级别的筛选器,但问题是您希望对这两个类别使用相同的提供程序。提供程序由其类型标识,因此您不能创建针对提供程序的特定示例的规则。如果您为文件提供程序创建规则,则会影响所有已配置的文件提供程序。
所以这就是黑客开始的地方:你必须创建自己的提供程序类型,这些类型链接到文件,以便能够过滤每个文件。
.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();


您可以通过调用扩展方法.ConfigureLogging来配置Main中的日志记录:

.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-实际上实现了确保两个不同类别的日志消息正确路由到两个不同提供者的预期结果。第三个提供者被添加,它将不受这些过滤器的影响,并且来自两个类别的消息将由第三个提供者记录。

8fsztsew

8fsztsew2#

我为此创建了一个聚合日志记录器。

public class AggregateLogger : ILogger
{
    ILogger[] Loggers { get; set; }

    public AggregateLogger(params ILogger[] loggers) 
    {
        Loggers = loggers;
    }

    public IDisposable BeginScope<TState>(TState state)
    {
        List<IDisposable> disposables = new List<IDisposable>();
        
        foreach(var log in Loggers) 
            disposables.Add(log.BeginScope(state));

        Disposer disposer = new Disposer(disposables);
        return disposer;
    }

    public bool IsEnabled(LogLevel logLevel)
    {
        return Loggers.Any(o => o.IsEnabled(logLevel));
    }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        foreach(var log in Loggers)
            log.Log(logLevel, eventId, state, exception, formatter);
    }
}

public class Disposer : IDisposable
{
    List<IDisposable> _disposables;

    public Disposer(List<IDisposable> disposables) 
    {
        _disposables = disposables;
    }

    public void Dispose()
    {
        foreach (var obj in _disposables)
            obj.Dispose();
    }
}

字符串

相关问题