Disposing of ILoggerFactory in ASP.NET Core

1

In my ASP.NET Core project I have written an extention on ILoggerFactory that adds a custom ILoggerProvider. (Similar to NLog.Extensions.Logging)

I'm adding this in 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. These cannot stay open so I close the channel and connection in Dispose (ILoggerProvider already inherits from 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

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);            
    }        
}
c#
asp.net-core
rabbitmq
asked on Stack Overflow Apr 4, 2017 by Rubanov • edited Apr 5, 2017 by Rubanov

1 Answer

0

I was able to fix this by changing my ILoggerFactory extensions library. I also had issues with console applications using this extensions but only when I used more than one service with an ILogger implementation.

In the provider (derived from ILoggerProvider) there is a CreateLogger method. I found out that within one provider you can have multiple loggers (e.g. one for each of your asp.net controllers or for each service in your console app). I mistakenly thought each logger had it's own provider and I only disposed one ILogger (the last one).

When I changed my ILoggerProvider code to this, I no longer had hangs or errors in my unit tests

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. If your ILogger does not need to be disposed like NLog you don't have to worry about this.

answered on Stack Overflow Nov 29, 2017 by Rubanov

User contributions licensed under CC BY-SA 3.0