Search code examples
c#wpfnlog

Selecting a custom log level in NLog


I am writing a NLog file for an application. One of the requirements needed is that the user should be able to select the file size and the log level. The log level can be selected from a drop down menu. I was thinking that I can have a place holder for file size and log level. How can I go about doing this? Currently, I've done this:

<target name="logfile" xsi:type="File" FileName=".\logs\${shortdate}.log" 
        archiveFileName=".\logs\archive\${shortdate}.log"
        maxArchiveFiles="60" archiveEvery="Day" archiveAboveSize="###MaxSize###"
        layout="${longdate}|${level:uppercase=true}|${callsite}|${message}|${exception:format=toString}"/>
    <rules>
<logger name="*" minlevel="Trace" writeTo="logfile" />

I have two questions regarding this:

  1. How can I make it so that the log level can be selected on a choice?
  2. Do I need to make different target for each log level?

Solution

  • Semi Dynamic Routing Rules

    NLog 4.6.7 makes it easy to change the LogLevel on-the-fly:

    <nlog>
       <variable name="myLevel" value="Trace" />
        <rules>
          <logger name="*" minlevel="${var:myLevel}" writeTo="logfile" />
        </rules>
    </nlog>
    

    And then change it from runtime like this:

    LogManager.Configuration.Variables["myLevel"] = "Debug";
    LogManager.ReconfigExistingLoggers();
    

    https://github.com/NLog/NLog/wiki/Filtering-log-messages#semi-dynamic-routing-rules

    Rewrite and reload NLog.config

    But it sounds like you should just perform a search and replace in the NLog.config-file, and then perform an explicit reload:

    <nlog>
        <variable name="myLevel" value="Trace" />
        <variable name="mySize" value="42" />
        <targets>
            <target name="logfile" xsi:type="File"
                  fileName=".\logs\${shortdate}.log" 
                  archiveAboveSize="${mySize}" />
        </targets>
        <rules>
          <logger name="*" minlevel="${var:myLevel}" writeTo="logfile" />
        </rules>
    </nlog>
    

    After the file-rewrite/update (that changes the two variables) then explicit reload is done like this:

    NLog.LogManager.Configuration = NLog.LogManager.Configuration?.Reload();
    

    Alternative to explicit reload would be to use <nlog autoReload="true"> (Then NLog will detect changes to NLog.config-file and reload automatically).

    Rewrite and reload NLog.user.config

    If you feel excited and like advanced stuff, then you could also make use of include-files, and have a default NLog.config that includes NLog.user.config:

    <nlog autoreload="true">
        <variable name="myLevel" value="Trace" />
        <variable name="mySize" value="42" />
        <include file="NLog.user.config" ignoreErrors="true" />  <!-- Can override variables -->
        <targets>
            <target name="logfile" xsi:type="File"
                  fileName=".\logs\${shortdate}.log" 
                  archiveAboveSize="${mySize}" />
        </targets>
        <rules>
          <logger name="*" minlevel="${var:myLevel}" writeTo="logfile" />
        </rules>
    </nlog>
    

    See also: https://github.com/NLog/NLog/wiki/XML-config-include-Example