Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change the NLog layout at run time?

Tags:

c#

logging

nlog

I created the 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"
      throwExceptions="false"
      throwConfigExceptions="true"> <!--make NLog complain, when something is wrong with the configuration-->


  <targets>
    <target name="logfile" xsi:type="File" 
            fileName="${basedir}/Logs/Log_${shortdate}.txt" 
            layout="[${longdate}] [${uppercase:${level}}] ${message} ${exception:format=tostring}"
            />
    <target name="logconsole" xsi:type="ColoredConsole" 
            layout="[${longdate}] ${uppercase:${level}}: ${message} ${exception:format=tostring}"
            />    
  </targets>

  <rules>
    <logger name="*" minlevel="Info" writeTo="logconsole" />
    <logger name="*" minlevel="Debug" writeTo="logfile" />

  </rules>
</nlog>

When I call logger.Info("Hello World"); I get an output both in the console and the file:

[2018-03-17 15:34:24.2843] INFO: Hello World

Which is fine. Now in some cases I do not want to display the date-time part, and I want to display it only in the console.

How would I do that with NLog?

A pseudo solution I would want is:

logger.Info("Hello World", writeTo: "logconsole", layout: "[${uppercase:${level}}] ${message}");

I tried adding a new taget

<target name="logconsole_simple" xsi:type="ColoredConsole"
            layout="${uppercase:${level}}: ${message} ${exception:format=tostring}"/>

and new rule:

<logger name="logconsole_simple"  level="Info" writeTo="logconsole_simple" />

And call it like:

logger.Log(LogEventInfo.Create(LogLevel.Info, "logconsole_simple", "simple message!"));

But it still displays the date-time part and logs it to the file also (which I don't want). How to fix this?

like image 772
zig Avatar asked Jan 02 '26 00:01

zig


1 Answers

Add a target and rule for your special case and reference your loggers by name.

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"
      throwExceptions="false"
      throwConfigExceptions="true"><!--make NLog complain, when something is wrong with the configuration-->

  <targets>
    <target name="logfile" xsi:type="File"
            fileName="${basedir}/Logs/Log_${shortdate}.txt"
            layout="[${longdate}] [${uppercase:${level}}] ${message} ${exception:format=tostring}"
    />
    <target name="logconsole_default" xsi:type="Console"
            layout="[${longdate}] ${uppercase:${level}}: ${message} ${exception:format=tostring}"
    />
    <target name="logconsole_other" xsi:type="Console"
            layout="${uppercase:${level}}: ${message} ${exception:format=tostring}"
    />
  </targets>

  <rules>
    <logger name="default" minlevel="Debug" writeTo="logfile" />
    <logger name="default" minlevel="Info" writeTo="logconsole_default" />
    <logger name="other" minlevel="Info" writeTo="logconsole_other" />
  </rules>
</nlog>

Usage:

internal class Program
{
    private static readonly Logger DefaultLogger = LogManager.GetLogger("default");

    private static readonly Logger OtherLogger = LogManager.GetLogger("other");

    private static void Main(string[] args)
    {
        for (var i = 0; i < 2; i++)
        {
            if (i % 2 == 0)
            {
                DefaultLogger.Info("normal log message");
            }
            else
            {
                OtherLogger.Info("special case");
            }
        }
    }
}

EDIT: If you really want to do it in code by modifying your existing target and rule, you can (this will work with the config from your original post):

using System.Linq;
using NLog;
using NLog.Layouts;
using NLog.Targets;

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

    private static void Main(string[] args)
    {
        for (var i = 0; i < 2; i++)
        {                
            if (i % 2 == 0)
            {
                Logger.Info("normal log message");
            }
            else
            {
                // reconfigure
                var consoleTarget = LogManager.Configuration.FindTargetByName<ColoredConsoleTarget>("logconsole");
                var oldLayout = consoleTarget.Layout;
                consoleTarget.Layout = new SimpleLayout { Text = "${uppercase:${level}}: ${message} ${exception:format=tostring}" };
                var fileRule = LogManager.Configuration.LoggingRules.Single(r => r.Targets.Any(t => t.Name == "logfile"));
                LogManager.Configuration.LoggingRules.Remove(fileRule);
                LogManager.Configuration.Reload();

                Logger.Info("special case");

                // replace originals
                consoleTarget.Layout = oldLayout;
                LogManager.Configuration.LoggingRules.Add(fileRule);
                LogManager.Configuration.Reload();
            }
        }
    }
}
like image 85
ejohnson Avatar answered Jan 03 '26 15:01

ejohnson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!