NLog – Split trace logging into its own file

This article explains how to configure NLog so that trace-level log messages go to their own file. This is useful because trace logging involves logging every method call for short-term troubleshooting, leading to very large log files. This approach only requires modifying the nlog.config file, and doesn’t require any code changes.

In the end, all levels above Trace – Debug, Error, Warn, Info – will go into one log file and all trace-level messages will go into a separate file.

1 – Install and initialize NLog

If you already have NLog installed and have the nlog.config file, you can skip this step.

  • Install the NLog package. Note: This is using Package Console Manager (View > Other Windows > Package Console Manager).
Install-Package NLog
Code language: PowerShell (powershell)
  • Add a new empty file called nlog.config.
  • Set nlog.config’s property Copy To Output Directory = Copy If Newer.

After these steps, your .csproj should look like this:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="NLog" Version="4.7.5" />
  </ItemGroup>

  <ItemGroup>
    <None Update="nlog.config">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>

</Project>

Code language: HTML, XML (xml)

2 – Configure NLog.config to split trace-level messages to a different file

You may have other requirements for your logging, so make sure to get NLog configured with all your other requirements first (such archiving log files by size). If you are starting from scratch, you might want to just start by copy and pasting the nlog.config shown below.

In the nlog.config file, there are two important sections that enable splitting out trace-level messages:

  • Targets – add a new target for your trace log file.
  • Rules – Add two rules, both with the name “*”. The first rule has minlevel=Debug and writeTo=mainLog. The other has level=Trace and writeTo=traceLog.

This means all log messages with level Debug and above will go to the mainLog target, and all trace-level log messages will go to the traceLog target.

Note: Put enabled=true in the trace rule. This makes it easy to turn trace logging on and off.

<?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 NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">

  
<variable name ="logFile" value="C:/logs/helloworld-${shortdate}" />    

  <targets>
    <target xsi:type="File" 
            name="mainLog" 
            fileName="${logFile}.log"
            layout="${longdate} level=${level} message=${message}" 
            keepFileOpen ="false"
            concurrentWrites ="true"/>

    <target xsi:type="File"
            name="traceLog"
            fileName="${logFile}.tracelog"
            layout="${longdate} level=${level} threadid=${threadid} message=${message}"
            keepFileOpen ="false"
            concurrentWrites ="true"/>
  </targets>

  <rules>
    <logger name="*" minlevel="Debug" writeTo="mainLog" />
    <logger name="*" level="Trace" writeTo="traceLog" enabled="true" />
  </rules>

</nlog>
Code language: HTML, XML (xml)

3 – Use NLog in the code and verify that it logs trace-level messages to separate file

Because the nlog.config rules have name=”*”, these rules apply to all loggers fetched from LogManager. So the following code simply fetches a logger and uses it to log the five different levels of messages.

using NLog;
class Program
{
	static void Main(string[] args)
	{
		var logger = LogManager.GetCurrentClassLogger();
		logger.Info("Hello Info");
		logger.Warn("Hello Warning");
		logger.Error("Hello Error");
		logger.Debug("Hello Debug");
		logger.Trace("Hello Trace");
	   
	}
}
Code language: C# (cs)

When I run this code, it creates the following two log files:

  • C:\logs\helloworld-2020-10-29.log
2020-10-29 07:45:27.1770 level=Info message=Hello Info
2020-10-29 07:45:27.2116 level=Warn message=Hello Warning
2020-10-29 07:45:27.2116 level=Error message=Hello Error
2020-10-29 07:45:27.2116 level=Debug message=Hello Debug
Code language: plaintext (plaintext)
  • C:\logs\helloworld-2020-10-29.tracelog
2020-10-29 07:45:27.2116 level=Trace threadid=1 message=Hello Trace
Code language: plaintext (plaintext)

Leave a Comment