Scripter9700
Scripter9700

Reputation: 81

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?

Upvotes: 2

Views: 2298

Answers (2)

Rolf Kristensen
Rolf Kristensen

Reputation: 19867

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

Upvotes: 3

Fildor
Fildor

Reputation: 16104

Building upon Combine nlog.config and config from code

Please note that combining the config file (nlog.config) and changing it in code, the reload of nlog.config could undo your changes. If you combine both, then reapply the changes on the reload event. E.g.

// On start of your program
UpdateConfig();

LogManager.ConfigurationReloaded += (sender, e) =>
{
    //Re apply if config reloaded
    UpdateConfig();
};

Where UpdateConfig is

public void UpdateConfig()
{
    var configuration = LogManager.Configuration;
    var fileTarget = configuration.FindTargetByName<FileTarget>("myTargetName");
    fileTarget.FileName = "${basedir}/file.log";
    LogManager.Configuration = configuration; //apply
}

and then, I'd tweak this to

public void UpdateConfig()
{
    var configuration = LogManager.Configuration;

    // Get User-Defined LogLevel and FileSize from App Settings
    // Set NLog LogLevel and FileSize

    LogManager.Configuration = configuration; //apply
}

while in the handler for the Log-Config-Dialog, I'd write Level and FileSize to App Settings, then call UpdateConfig.

Make sure to either ship with defaults set for those app settings or handle the settings not been set, yet.

Upvotes: 3

Related Questions