Search code examples
.netloggingconfignlogevent-log

NLog Configuration :: Controlling Which Levels Go To Which Outputs


I'm attempting to configure NLog for a .NET console program to log errors and fatal errors to the Windows event log, everything to a file, and only really info, warnings, errors, and fatal errors to the console.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
  </configSections>
  <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
  </startup>
  <nlog autoReload="true" internalLogFile="log/internal.txt" internalLogLevel="Trace">
    <variable name="brief" value="${longdate} ${level} ${logger} ${message}${onexception:inner= ${exception:format=toString,Data}} "/>
    <variable name="verbose" value="${longdate} | ${machinename} | ${processid} | ${processname} | ${level} | ${logger} | ${message}${onexception:inner= ${exception:format=toString,Data}}"/>
    <targets>
      <target name="console" type="Console" layout="${brief}"/>
      <target name="all_in" type="File" layout="${verbose}" fileName="${basedir}/log/log.txt" archiveFileName="${basedir}/log/archive/log.{#}.txt" archiveNumbering="DateAndSequence" archiveAboveSize="1048576" archiveDateFormat="yyyyMMdd" keepFileOpen="false" encoding="iso-8859-2"/>
      <target name="events" type="EventLog" layout="${verbose}" source="nlog-test" onOverflow="Split"/>
    </targets>
    <rules>
      <logger name="*" minlevel="Info" writeTo="console"/>
      <logger name="*" minlevel="Trace" writeTo="all_in"/>
      <logger name="*" minlevel="Fatal" maxlevel="Error" writeTo="events"/>
    </rules>
  </nlog>
</configuration>

I wrote up a simple console program to test this out that just reads commands from the user and writes to the appropriate level. As you can see, I've also tried enabling internal logging so I can understand what NLog is doing and why.

This started out writing errors (good) and info (bad) to the event log. Now it's not writing anything to the event log. I don't understand why it was writing "Info" levels to the event log when the "maxlevel" is defined as Error, and apparently, "Info" is "higher". I also don't understand why it stopped writing ANYTHING to the event log..

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using NLog;

namespace nlog_test
{
    class Program
    {
        static Logger logger = LogManager.GetCurrentClassLogger();

        static void Main(string[] args)
        {
            while(true)
            {
                try
                {
                    Console.Write("nlog-test> ");

                    var operands = Console.ReadLine().Split(
                            new[] {' ', '\t'},
                            StringSplitOptions.RemoveEmptyEntries);

                    if(operands.Length == 0)
                    {
                        continue;
                    }

                    var command = operands[0];
                    var arguments = operands.Skip(1);
                    Action<Action<string>> log =
                            f => f(string.Join(" ", arguments));

                    switch(command)
                    {
                        case "debug":
                            log(logger.Debug);
                            break;
                        case "delete":
                            File.Delete("log/log.txt");
                            break;
                        case "error":
                            log(logger.Error);
                            break;
                        case "fatal":
                            log(logger.Fatal);
                            break;
                        case "help":
                            Console.Write(@"
COMMAND [ARG...]

Commands:

    debug TEXT...
        Delete the log file.

    delete
        Delete the log file.

    error TEXT...
        Write an error message.

    fatal TEXT...
        Write a fatal error message.

    help
        Print this message.

    info TEXT...
        Write an information message.

    print
        Print the contents of the log file.

    quit
        Exit the process.

    trace TEXT...
        Write a trace message.

    warn TEXT...
        Write a warning message.
");
                            break;
                        case "info":
                            log(logger.Info);
                            break;
                        case "print":
                            {
                                var psi = new ProcessStartInfo("less.exe", "log/log.txt");

                                //psi.CreateNoWindow = true;
                                psi.UseShellExecute = false;

                                using(var process = Process.Start(psi))
                                {
                                    process.WaitForExit();
                                }
                            }
                            break;
                        case "quit":
                            return;
                        case "trace":
                            log(logger.Trace);
                            break;
                        case "warn":
                            log(logger.Warn);
                            break;
                        default:
                            Console.Error.WriteLine(
                                    "Unknown command: {0}",
                                    command);
                            break;
                    }
                }
                catch(Exception ex)
                {
                    Console.Error.Write($"Caught unhandled exception: ");
                    Console.Error.WriteLine(ex);
                }
            }
        }
    }
}

Solution

  • For the events-logging-rule, then remove maxlevel="Error" and change minlevel="Fatal" to minlevel="Error".

    From this:

     <logger name="*" minlevel="Fatal" maxlevel="Error" writeTo="events"/>
    

    To this:

     <logger name="*" minlevel="Error" writeTo="events"/>