Skip to content

Logging Troubleshooting

ilusha edited this page Oct 24, 2023 · 31 revisions

Possible causes

When you get no log output from NLog, then you should check these normal pitfalls:

  1. NLog cannot find the configuration file. Ensure NLog.config is has Build Action = Content and Copy to Output Directory = Copy if newer in Visual Studio.
  2. Is your configuration file valid XML?
  3. Logging rules are incorrect or no rules are defined
  4. Forgetting to call NLog.LogManager.Shutdown() before application exits, so targets are not flushed correctly.
  5. Application tracing code is incorrect (Ex. LogLevel too low)
  6. There is a runtime problem with the target (such as missing permissions)
  7. Logs are written to a different location.

Troubleshooting steps

When the checkpoints listed above doesn't resolve the issue, then one can try these troubleshooting steps:

  1. The first step is to make sure that NLog finds your config file. It is recommended to use NLog.config located in the same directory as your application, but NLog does scan multiple file locations (See also NLog Configuration). Once you've made sure that the configuration file is there, proceed to the next step.
    • If nlog.config file is configured with Build Action = None or Copy to Output Directory = Do not copy in Visual Studio. Then fix it and set Build Action = Content and Copy to Output Directory = Copy if newer.
    • If running on Linux, then make sure to use nlog.config in all lowercase, because of case-sensitive filenames.
    • There are nuget-packages that automatically update Web.config/App.config/etc. which can overwrite the custom NLog-configuration.
    • Do NOT use the NLog.Config-nuget-package, as it can reset nlog.config on application-deployment.
  2. If not having issues with finding NLog.config, then include the xml-attribute throwConfigExceptions="true" for the NLog.config. This will ensure NLog will "explode" when something is wrong with loading the NLog.config (Also invalid XML):
<nlog throwConfigExceptions="true">
    <targets>
       ...
    </targets>
    <rules>
       ...
    </rules>
</nlog>
  1. If the problem is not loading an invalid NLog.config, then activate the NLog InternalLogger and check for issues when loading the NLog.config and writing to the targets. This will output all events happening while loading the NLog.config:
    • NLog InternalLogger can tell you if you have permissions issues so it cannot write to the wanted location.
<nlog internalLogLevel="Debug"
      internalLogFile="c:\temp\nlog-internal.txt"
      internalLogToConsole="true"
      throwConfigExceptions="true">
    <targets>
       ...
    </targets>
    <rules>
       ...
    </rules>
</nlog>
  1. If the NLog InternalLogger is not producing any output, then you are most likely having issues with loading the NLog.config. Instead you can activate the NLog InternalLogger within the application to see any errors when loading NLog.config. The Configuration is read when you create your first Logger, so make sure to enable the InternalLogger before having initialized any static Logger objects:
class Program
{
    // Make sure to comment out static Logger-objects, or else InternalLogger will not work
    // readonly static Logger = LogManager.GetCurrentClassLogger();

    static void Main()
    {
        NLog.Common.InternalLogger.LogLevel = NLog.LogLevel.Debug;
        NLog.Common.InternalLogger.LogToConsole = true;
        NLog.Common.InternalLogger.LogFile = @"c:\temp\nlog-internal.txt"; // On Linux one can use "/home/nlog-internal.txt"
        Logger logger = LogManager.GetLogger("foo");
        logger.Info("Program started");
        LogManager.Shutdown();  // Remember to flush
    }
}
  1. To eliminate the possibility that your logging rules are incorrect, add the rule which matches all loggers and all levels at the beginning of your <rules> section.
    • Also ensure that an explicit flush is made before application shutdown, in case NLog target is having delays in network communication. Ex. by calling NLog.LogManager.Shutdown().
<nlog throwExceptions="true">
  <targets>
    <target name="file" type="File" fileName="${basedir}/log.txt" />
  </targets>
  <rules>
    <logger name="*" minLevel="Trace" writeTo="{all target names separated by comma}" />
  </rules>
</nlog>
  1. Last resort when all other steps fail then you can try to enable LogManager.ThrowExceptions. It is only intended for unit-testing, and it can have unwanted side-effects like unwanted application crashes. So make sure to turn it off again when done with troubleshooting:

    ⚠️ If having throwExceptions="true" enabled already, then it can be the cause of NLog is not working. The throwExceptions="true" is intended for unit-testing of NLog itself, and will prevent NLog from doing self-recovery after failure, and should never be used in production environment.

class Program
{
    // Make sure to comment out static Logger-objects, or else InternalLogger will not work
    // readonly static Logger = LogManager.GetCurrentClassLogger();

    static void Main()
    {
        NLog.LogManager.ThrowExceptions = true; // TODO Remove this when done trouble-shooting
        NLog.Common.InternalLogger.LogLevel = LogLevel.Debug;
        NLog.Common.InternalLogger.LogToConsole = true;
        NLog.Common.InternalLogger.LogFile = "c:\temp\nlog-internal.txt"; // On Linux one can use "/home/nlog-internal.txt"
        Logger logger = LogManager.GetLogger("foo");
        logger.Info("Program started");
        LogManager.Shutdown();  // Remember to flush
    }
}
  1. If after following steps 1..6 you still don't see your log messages - there is another possibility: your log files may be written to a different location. If you don't use a fully qualified name of the file (such as c:\logs\log.txt, or ${basedir}\log.txt your logs may be written to the working directory, which is not necessarily the same directory as where the application resides.

Internal Logging

NLog has its own internal logging system which can be used to troubleshoot problems with log routing and configuration. The simplest way to enable is to add the following attributes to your configuration file:

  • internalLogFile="c:\path\to\nlog-internal.txt" - specifies the location of the internal log file
  • internalLogLevel="Trace" specifies the level of detail of information written to the internal log file
  • internalLogToConsole="true" writes internal log to the console output

More ways to enable internal logging are explained here.

Other troubleshooting tools and techniques

You may use a tracing application such as Process Monitor from SysInternals to monitor file activity in your system. This should give you an idea of what files are being read and written and their exact locations.

Process Explorer is another indispensable utility which can help with investigation of various system-level issues, such as permissions, threading, deadlocks, performance, etc.

Clone this wiki locally