简体   繁体   English

在ASP.NET Core中处理ILoggerFactory

[英]Disposing of ILoggerFactory in ASP.NET Core

In my ASP.NET Core project I have written an extention on ILoggerFactory that adds a custom ILoggerProvider . 在我的ASP.NET核心项目中,我在ILoggerFactory上编写了一个扩展,它添加了一个自定义的ILoggerProvider (Similar to NLog.Extensions.Logging ) (与NLog.Extensions.Logging类似)

I'm adding this in Startup.cs : 我在Startup.cs添加了这个:

loggerFactory.AddRabbitLogger(Configuration.GetSection(nameof(WebLoggerOptions)));

The logging is working perfectly, however, it sends messages to RabbitMQ and that means it opens a connection and a channel. 日志记录工作正常,但它会向RabbitMQ发送消息,这意味着它会打开一个连接和一个通道。 These cannot stay open so I close the channel and connection in Dispose ( ILoggerProvider already inherits from IDisposable ) 这些不能保持打开所以我关闭Dispose的通道和连接( ILoggerProvider已经从IDisposable继承)

My test are successful but the problem is that my test output always shows this error 我的测试成功但问题是我的测试输出总是显示此错误

Error while unloading appdomain. (Exception from HRESULT: 0x80131015)

Another problem is that it takes several seconds after the tests are already finished to show that error so I can't start any new tests. 另一个问题是,测试完成后需要几秒钟来显示错误,因此我无法启动任何新测试。

Is there a way to trigger the dispose of the logger provider in my tests? 有没有办法在我的测试中触发记录器提供程序的处理?

Here is the code of my integration test. 这是我的集成测试的代码。 As you can see, I am doing a dispose in the TearDown 如你所见,我正在TearDown处理

Integration Test 集成测试

public abstract class TestBase
{
    private TestServer _server;
    protected HttpClient TestHttpClient { get; private set; }

    [SetUp]
    protected void BaseSetup()
    {
        _server = new TestServer(new WebHostBuilder()
            .UseStartup<Startup>());
        TestHttpClient = _server.CreateClient();
    }       

    [TearDown]
    public void TearDown()
    {
        TestHttpClient.Dispose();
        _server.Dispose();
    }
}

public class MyTestClass : TestBase
{
    [Test]
    public async Task SendTest()
    {
        requestUrl = "api/ControllerName/Mehthod";
        var response = await TestHttpClient.PostAsync(requestUrl, pardotFormCommand, GetMediaTypeFormatter());
        response.StatusCode.Should().Be(HttpStatusCode.OK);            
    }        
}

I was able to fix this by changing my ILoggerFactory extensions library. 我能够通过更改我的ILoggerFactory扩展库来解决这个问题。 I also had issues with console applications using this extensions but only when I used more than one service with an ILogger implementation. 我也遇到过使用这种扩展的控制台应用程序的问题,但只有在我使用ILogger实现的多个服务时才会出现问题。

In the provider (derived from ILoggerProvider ) there is a CreateLogger method. 在提供程序(从ILoggerProvider派生)中有一个CreateLogger方法。 I found out that within one provider you can have multiple loggers (eg one for each of your asp.net controllers or for each service in your console app). 我发现在一个提供程序中你可以有多个记录器(例如,每个asp.net控制器一个或者你的控制台应用程序中的每个服务)。 I mistakenly thought each logger had it's own provider and I only disposed one ILogger (the last one). 我错误地认为每个记录器都有它自己的提供者,我只处理了一个ILogger (最后一个)。

When I changed my ILoggerProvider code to this, I no longer had hangs or errors in my unit tests 当我将ILoggerProvider代码更改为此时,我的单元测试中不再出现挂起或错误

public ILogger CreateLogger(string categoryName)
{
    var companyLogger = new CompanyLogger(categoryName, _loggerOptions);
    _companyLoggers.Add(companyLogger);

    return companyLogger;
}

public void Dispose()
{
    foreach (var logger in _companyLoggers)
    {
        logger.Dispose();
    }           
}

In short, if you want to write a custom ILoggerFactory with an ILogger class that needs to be disposed, you will have to keep the ILogger objects in a private list in your ILoggerProvider and dispose them all when the Dispose is called. 简而言之,如果要编写一个带有需要处理的ILogger类的自定义ILoggerFactory ,则必须将ILogger对象保存在ILoggerProvider的私有列表中,并在调用Dispose时将它们全部Dispose If your ILogger does not need to be disposed like NLog you don't have to worry about this. 如果您的ILogger不需要像NLog那样处理,您不必担心这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM