Search code examples
c#upgradenlogdeprecated

Update to Nlog 5.0: Configuration not applied


While upgrading from NLog 4.7.15 to 5.0.1 I found this test in our code base:

        [Test]
        public void CustomLogFactoryShouldBehaveCompletelyIndependent()
        {
            var memoryTarget4 = new MemoryTarget();
            memoryTarget4.Layout = "${level}|${logger}|${message}${exception}";
            var memoryTarget5 = new MemoryTarget();
            var customConfig = new LoggingConfiguration();
            customConfig.AddTarget("UnitTestLogger4", memoryTarget4);
            customConfig.LoggingRules.Add(new LoggingRule("UnitTestLogger4", LogLevel.Trace, memoryTarget4));
            customConfig.AddTarget("UnitTestLogger2", memoryTarget5);
            customConfig.LoggingRules.Add(new LoggingRule("UnitTestLogger2", LogLevel.Info, memoryTarget5));

            using (var customFactory = new LogFactory(customConfig)) // <<-- This ctor is marked obsolete
            {
                // Log logger defined only in custom config
                var logger4 = customFactory.GetLogger("UnitTestLogger4");
                logger4.Trace("Test4");
                Assert.That(memoryTarget4.Logs.Count, Is.EqualTo(1));
                Assert.That(memoryTarget5.Logs, Is.Empty);
                memoryTarget4.Logs.Clear();

               //... More cases tested here
           }
      }

The test works fine both in the old and the new version, but only after I disable the deprecation warning CS0618 for the constructor LogFactory(LoggingConfiguration).

To work around this, I tried to use the suggested alternative LoggingConfiguration(LogFactory), which connects the factory and the configuration basically the other way round.

        [Test]
        public void CustomLogFactoryShouldBehaveCompletelyIndependent()
        {
            var memoryTarget4 = new MemoryTarget();
            memoryTarget4.Layout = "${level}|${logger}|${message}${exception}";
            var memoryTarget5 = new MemoryTarget();

            using (var customFactory = new LogFactory())
            {
                var customConfig = new LoggingConfiguration(customFactory);
                customConfig.AddTarget("UnitTestLogger4", memoryTarget4);
                customConfig.LoggingRules.Add(new LoggingRule("UnitTestLogger4", LogLevel.Trace, memoryTarget4));
                customConfig.AddTarget("UnitTestLogger2", memoryTarget5);
                customConfig.LoggingRules.Add(new LoggingRule("UnitTestLogger2", LogLevel.Info, memoryTarget5));
                // customFactory.ReconfigExistingLoggers(); // <<-- Adding this changes nothing

                // Log logger defined only in custom config
                var logger4 = customFactory.GetLogger("UnitTestLogger4");
                logger4.Trace("Test4");
                Assert.That(memoryTarget4.Logs.Count, Is.EqualTo(1)); // <<-- Fails here, nothing was added to memoryTarget4.
                Assert.That(memoryTarget5.Logs, Is.Empty);
                memoryTarget4.Logs.Clear();
           }
      }

At least that's what I think should be changed. But the test fails now. The configuration is not applied, as the target does not get any logs.

What did I miss? What's the correct way of replacing the deprecated LogFactory(LoggingConfiguration) constructor here?


Solution

  • The constructor new LogFactory(customConfig) became obsolete to ensure that the LoggingConfiguration.Factory-option had the expected value (Using the intended isolated LogFactory instead of the global static LogManager.Factory)

    You can replace:

    customFactory.ReconfigExistingLoggers();
    

    With this so the configuration is activated:

    customFactory.Configuration = customConfig;
    

    Alternative you could do this:

    using var customFactory = new NLog.LogFactory().Setup().LoadConfiguration(builder => {
       var memoryTarget4 = new MemoryTarget();
       memoryTarget4.Layout = "${level}|${logger}|${message}${exception}";
       var memoryTarget5 = new MemoryTarget();
       builder.Configuration.LoggingRules.Add(new LoggingRule("UnitTestLogger4", LogLevel.Trace, memoryTarget4));
       builder.Configuration.LoggingRules.Add(new LoggingRule("UnitTestLogger2", LogLevel.Info, memoryTarget5)));
    }).LogFactory;
    
    var logger4 = customFactory.GetLogger("UnitTestLogger4");
    logger4.Trace("Test4");
    Assert.That(memoryTarget4.Logs.Count, Is.EqualTo(1));
    Assert.That(memoryTarget5.Logs, Is.Empty);
    memoryTarget4.Logs.Clear();