Steven Volckaert
Steven Volckaert

Reputation: 357

No log output after upgrading to NLog v5.0.x

In our ASP.NET, ASP.NET Core, and command-line programs we have been using NLog for many years.

In an ASP.NET Core app targeting net6.0, the following configuration works when using NLog version 4.7.15 and NLog.Extensions.Hosting version 1.7.5. When upgrading both packages to version 5.0.x (e.g. the latest available version, 5.0.4), logging stops working. Nothing is logged: The log file remains empty.

The application is supposed to use the Microsoft.Extensions.Logging filters as defined in appsettings.json - see below.

I've read NLog 5.0 - List of major changes many times and tried to workaround the breaking changes. Unfortunately I haven't been able to get it to work.

Our setup is below, hopefully someone is able to help. Thank you!


ASP.NET Core app targeting net6.0, using NLog version 4.7.15 and NLog.Extensions.Hosting version 1.7.5

As soon as I upgrade to NLog version 5.0.4 and NLog.Extensions.Hosting version 5.0.4, the logging breaks. Nothing is logged any more.

NLog.config

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd http://nlog-project.org/schemas/NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogLevel="Off"
      internalLogFile="D:\Logs\StevenVolckaert.WebService\nlog-internal.log">

  <!-- Docs @ https://github.com/nlog/nlog/wiki/Configuration-file -->
  <!-- ASP.NET Core examples @ https://github.com/akovac35/Logging.Samples -->

  <extensions>
    <add assembly="NLog.Extensions.Hosting" />
  </extensions>

  <!-- ConfigSetting Layout Renderer @ https://github.com/NLog/NLog/wiki/ConfigSetting-Layout-Renderer -->

  <variable name="ApplicationName" value="${configsetting:item=ApplicationName:default=application}" />
  <variable name="BuildNumber" value="${configsetting:item=BuildNumber:default=undefined}" />
  <variable name="EnvironmentName" value="${configsetting:item=EnvironmentName:default=undefined}" />
  <variable name="LogDirectory" value="${whenEmpty:whenEmpty=${basedir}logs:inner=${configsetting:item=NLog.LogDirectory}}" />

  <!-- https://github.com/nlog/nlog/wiki/Configuration-file#targets -->

  <targets>
    <target
       xsi:type="Console"
       name="Console"
       layout="${longdate} ${threadid:padding=2} ${uppercase:${level:padding=5}} ${logger} ${message} ${exception:format=toString}">
    </target>
    <target
      xsi:type="File"
      name="LogFile"
      fileName="${var:LogDirectory}\${var:ApplicationName}.log"
      layout="${longdate} ${threadid:padding=2} ${uppercase:${level:padding=5}} ${logger} ${message} ${exception:format=toString}"
      archiveEvery="Day"
      archiveFileName="${var:LogDirectory}\Archive\{#}.${var:ApplicationName}.log"
      archiveNumbering="Date"
      archiveDateFormat="yyyy-MM-dd"
      maxArchiveDays="90">
    </target>
  </targets>

  <!-- https://github.com/nlog/nlog/wiki/Configuration-file#rules -->

  <rules>
    <logger name="*" minlevel="Trace" writeTo="Console,LogFile" />
  </rules>

</nlog>

appsettings.json

{
  "ApplicationName": "StevenVolckaert.WebService",
  "BuildNumber": null,
  "ConnectionStrings": {
    "DefaultDatabaseConnection": ""
  },
  "EnvironmentName": "Local",
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "NLog": {
    "LogDirectory": "D:\\Logs\\StevenVolckaert.WebService\\"
  }
}

Program.cs

using NLog.Extensions.Logging;

public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        builder.Services
            .AddLogging(loggingBuilder =>
            {
                loggingBuilder
                    .ClearProviders()
                    .SetMinimumLevel(LogLevel.Trace)
                    .AddConfiguration(builder.Configuration.GetSection("Logging"))
                    .AddNLog(builder.Configuration, new NLogProviderOptions { RemoveLoggerFactoryFilter = false });
            });

        // code removed for brevity

        var app = builder.Build();

        // code removed for brevity

        app.Run();
    }

I've tried adding the filters element to the logger rule, specifying defaultAction="Log", but this doesn't make a difference: Still no output in the logging.

   <rules>
    <logger name="*" minlevel="Trace" writeTo="Console,LogFile">
      <filters defaultAction="Log" />
    </logger>
  </rules>

Upvotes: 3

Views: 1332

Answers (1)

Rolf Kristensen
Rolf Kristensen

Reputation: 19847

Think the issue is caused by this new default-value:

NLogProviderOptions.LoggingConfigurationSectionName = "NLog"

The change in default-value causes the "NLog"-section to become reserved, and intended for having NLog.config in appsettings.json. This works together with SchemaStore that provides basic-intellisense when editing the now reserved "NLog"-section.

This probably causes NLog.Extensions.Logging to lookup the "NLog"-section in the appsettings.json where it finds this:

{
  "NLog": {
    "LogDirectory": "D:\\Logs\\StevenVolckaert.WebService\\"
  }
}

After having "loaded" this empty NLog-configuration, then it skips further attempts and doesn't load your NLog.config-file.

I suggest that you remove the "NLog"-section and change it into this (And updates NLog.config to ${configsetting:NLogDirectory}):

{
   "NLogDirectory": "D:\\Logs\\StevenVolckaert.WebService\\"
}

Sorry about the bad experience, but it was done to make NLog.config in appsettings.json work out of the box (Making it closer to a first class citizen).

P.S Consider updating your program.cs like this (But I encourage that you remove RemoveLoggerFactoryFilter = false and instead make use of NLog finalMinLevel):

var builder = WebApplication.CreateBuilder(args);
// NLog: Setup NLog for Dependency injection
builder.Logging.ClearProviders();
builder.Host.UseNLog(new NLogProviderOptions { RemoveLoggerFactoryFilter = false });
var app = builder.Build();

Upvotes: 2

Related Questions