-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Logging Troubleshooting
When no log output is produced, the issue may originate in NLog configuration, the application, or the runtime environment. Common causes include:
- NLog cannot find the configuration file. Ensure
NLog.confighas:- Build Action = Content
- Copy to Output Directory = Copy if newer
- The configuration file contains invalid XML or NLog configuration errors.
- Logging rules do not match the logger name or log level.
- The logging code is never executed.
- The application exits before logs are flushed. Call
NLog.LogManager.Shutdown()during application shutdown to flush pending events. - The logging target fails at runtime (e.g., missing file permissions).
- Log output is written to an unexpected location.
- A different configuration is used at deployment time (overriding the expected
NLog.config). - Environment differences (hosting, container, or filesystem) compared to local development.
These steps help isolate the problem area: configuration loading → initialization → rule matching → target writing → application execution
Ensure NLog.config xml-file is located in the application’s base directory, as the primary location of the multiple file location scanned by NLog at startup.
- Ensure
NLog.confighas:- Build Action = Content
- Copy to Output Directory = Copy if newer
- On Linux, file name must be
nlog.config(all lowercase as case-sensitive) - Some NuGet packages may modify
Web.configorApp.configand override logging configuration - Do NOT use the deprecated NLog.Config NuGet-package, which may overwrite or reset configuration during deployment.
- Verify that the deployed configuration matches the expected version.
NLog will by default suppress any configuration errors, instead of causing the application to fail. But this also means that application will not produce any logging output.
Enabling throwConfigExceptions will make NLog throw exceptions to report any issues detected in the NLog Configuration at startup:
<nlog throwConfigExceptions="true">
<targets>
...
</targets>
<rules>
...
</rules>
</nlog>Enable the NLog InternalLogger and use the output to help diagnose:
- Configuration loading issues
- Logger rules decisions
- Target initialization failures
- Target writing failures (File permission problems, File path issues, Ex.)
- Etc.
<nlog internalLogLevel="Debug"
internalLogFile="c:\temp\nlog-internal.txt"
internalLogToConsole="true"
throwConfigExceptions="true">
<targets>
...
</targets>
<rules>
...
</rules>
</nlog>If no InternalLogger output appears, then it either NLog.config could not be found or failed to load. It can also be that the InternalLogger was enabled after initial attempt to load the NLog logging configuration.
Try to enable NLog InternalLogger from code at application startup. Ensure it happens before any logger usage (like static Logger objects), as configuration is initially loaded when first Logger is created.
class Program
{
// Temporarily disable static logger initialization
// 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";
var logger = LogManager.GetLogger("foo");
logger.Info("Program started");
LogManager.Shutdown();
}
}Reduce logging rule complexity to eliminate matching issues, by adding catch-all rule that matches all loggers and all levels at the beginning of your <rules> section:
<nlog throwConfigExceptions="true">
<targets>
<target name="file" type="File" fileName="C:/Logs/log.txt" />
<target name="console" type="Console" />
</targets>
<rules>
<logger name="*" minLevel="Trace" writeTo="file,console" />
</rules>
</nlog>If still no logs appear:
- Verify that the logging call is actually executed in the application code.
- Ensure explicit flush is made before application shutdown, in case NLog target is having delays in network communication. Ex. by calling
NLog.LogManager.Shutdown(). - If using file-target then make sure to use absolute file-path as more predictable.
Enable runtime exception propagation only for diagnostics:
NLog.LogManager.ThrowExceptions = true;ThrowExceptions = true for troubleshooting and unit-testing. Should never be kept enabled in production, as it can cause application runtime crashes. Different from throwConfigExceptions="true" that only enables configuration verification at startup.
class Program
{
static void Main()
{
NLog.LogManager.ThrowExceptions = true; // TODO Remove after troubleshooting
NLog.Common.InternalLogger.LogLevel = LogLevel.Debug;
NLog.Common.InternalLogger.LogToConsole = true;
NLog.Common.InternalLogger.LogFile = @"c:\temp\nlog-internal.txt";
var logger = LogManager.GetLogger("foo");
logger.Info("Program started");
LogManager.Shutdown();
}
}External tools can help determine whether the issue is inside NLog or the environment:
- Process Monitor — file access, permission, and I/O tracing
- Process Explorer — handles, threads, and runtime diagnostics
These help distinguish between "NLog not writing" vs "Operating System prevented writing".
Focus on observable behavior:
- Is the configuration loaded?
- Is the logger initialized?
- Is the logging call executed?
- Is the log event routed?
- Is the target writing successfully?
Answering these typically identifies the failing component quickly.
- Troubleshooting Guide - See available NLog Targets and Layouts: https://nlog-project.org/config
- Getting started
- How to use structured logging
- Troubleshooting
- FAQ
- Articles about NLog
-
All targets, layouts and layout renderers
Popular: - Using NLog with NLog.config
- Using NLog with appsettings.json