Search code examples
c#nlog

Redirect NLog logging output to file specified by the logger


I want all messages to go to all.log file and if logSource property is set then message should also go to logSource file. If I uncomment the when filter then the logSource file is not created. I added when filter so it will include only message that had logSource set to non-null value.

Code

internal class Program
{
    private static readonly Logger _log = LogManager.GetCurrentClassLogger();

    static async Task Main(string[] args)
    {
        var logEvent = LogEventInfo.Create(LogLevel.Info, null, "message");
        logEvent.Properties["logSource"] = "Program";
        _log.Log(logEvent);

        _log.Info("This message should not be in the log since logSource is not set.");
    }
}

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"
  autoReload="true">

  <targets>
    <target xsi:type="File" name="fileInfo" fileName="all.log" 
        layout="${longdate}|${level}|${event-properties:logSource}"
      />
    <target xsi:type="File" name="fileInfoSource" fileName="${event-properties:logSource}.log" 
       layout="${longdate}|${level}|${event-properties:logSource}"
    />
  </targets>

  <rules>
    <logger name="*" minlevel="Info" writeTo="fileInfo"/>
    <logger name="*" minlevel="Info" writeTo="fileInfoSource">
      <filters>
        <!--when condition="not isset('${event-properties:logSource}')" action="Ignore" /-->
      </filters>
    </logger>
  </rules>
</nlog>

Solution

  • Alternative approach using WithProperty together with special Logger-Name for file-target redirection:

    internal class Program
    {
        private static readonly Logger _log = LogManager.GetCurrentClassLogger();
        private static readonly Logger _logSource = LogManager.GetLogger("LogSource");
    
        static async Task Main(string[] args)
        {
            GetLogSource("Program").Info("Message redirected to special place");        
            _log.Info("This message goes to the default place"):
        }
    
        static Logger GetLogSource(string logSource)
        {
            // Consider storing in class-variable when logSource is static
            return _logSource.WithProperty("LogSource", logSource);
        }
    }
    

    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"
      autoReload="true">
    
      <targets>
        <target xsi:type="File" name="fileInfo" fileName="all.log" />
        <target xsi:type="File" name="fileInfoSource" fileName="${event-properties:logSource:whenEmpty=MissingSource}.log" />
      </targets>
    
      <rules>
        <logger name="LogSource" minlevel="Info" writeTo="fileInfoSource" />
        <logger name="*" minlevel="Info" writeTo="fileInfo" />
      </rules>
    </nlog>