Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't ConsoleAppender configured in app.config causing logs to write to the console?

Tags:

c#

.net

log4net

In App.Config I declare a config section for my console application:

  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>

And configure a ConsoleAppender:

<log4net>
  <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
    <layout type="log4net.Layout.PatternLayout">
    </layout>
  </appender>
  <root>
    <level value="ALL" />
    <appender-ref ref="ConsoleAppender" />
  </root>
</log4net>

We also declare a RollingFile appender in a logging util class that's part of our standard codebase at app-startup (which is not easily modified):

        _hierarchy = (Hierarchy)LogManager.GetRepository();
        _rollingFileAppender = new RollingFileAppender();            
        ... //_rollingFileppender options

        _rollingFileAppender.ActivateOptions();
        _hierarchy.Root.AddAppender(_rollingFileAppender);
        _hierarchy.Configured = true;

When I run the application, I see log-entries are written to files as expected but nothing is written to the console.

When I inspect my ILog instance in the debugger, I see no appenders at all in Logger.Appenders but I do see the RollingFileAppender instance as the only element in Root.Appenders.

log4net is something I am used to "it just works" - is there some incompatibility having config and code add appenders, or some line I need to get LogManager to look in app.config?

like image 441
Mr. Boy Avatar asked Jun 04 '20 11:06

Mr. Boy


People also ask

What is the default target of ConsoleAppender?

The default target is System.err. Console appender uses the log message pattern specified by the user in configuration using PatternLayout property. 1. Log4j2 ConsoleAppender Configuration

What is ConsoleAppender in log4j2?

Log4j2 ConsoleAppender appends the log events generated by application into the System.out or System.err. The default target is System.err. Console appender uses the log message pattern specified by the user in configuration using PatternLayout property. 1.

Why is my rootlogger not showing up on console Appender?

Your second log4j.rootLogger line is overwriting the first, which explains why you aren't seeing anything on the console appender. You need to merge your two rootLogger definitions into one. It looks like you're trying to have DEBUG messages go to the console and INFO messages to the file.

How to disable console logging when not in use?

If not using configuration files, we can use the property logging.pattern.console with empty value to disable console logging. It is not the recommended approach and do it only for POCs.


1 Answers

You just got me curious and i decided to play around a bit.
First observations is: You are right.

After some google i found this this

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
  <log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date %level [%thread] %logger{1} %username - %message%newline" />
      </layout>
      <mapping>
        <level value="WARN" />
        <foreColor value="Yellow, HighIntensity" />
      </mapping>
      <mapping>
        <level value="ERROR" />
        <foreColor value="Red, HighIntensity" />
      </mapping>
    </appender>
    <root>
      <level value="ALL" />
      <appender-ref ref="ConsoleAppender" />
    </root>
  </log4net>
  <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
</configuration>

Setup

using log4net;
using log4net.Appender;
using log4net.Layout;
using log4net.Repository.Hierarchy;

namespace LoggerDemo
{
    public static class Program
    {
        private static readonly ILog Logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public static void Main(string[] args)
        {
            SetupFileAppender();
            SetupTraceAppender();
            Logger.Error("Error");
        }

        private static void SetupTraceAppender()
        {
            var patternLayout = new PatternLayout();
            patternLayout.ConversionPattern = "%date [%thread] %-5level %logger - %message%newline";
            patternLayout.ActivateOptions();

            var trace = new TraceAppender();
            trace.Layout = patternLayout;
            trace.ActivateOptions();
            var l = (Logger)Logger.Logger;
            l.AddAppender(trace);
        }

        private static void SetupFileAppender()
        {
            var patternLayout = new PatternLayout();
            patternLayout.ConversionPattern = "%date [%thread] %-5level %logger - %message%newline";
            patternLayout.ActivateOptions();

            var roller = new RollingFileAppender();
            roller.AppendToFile = true;
            roller.File = "Log.txt";
            roller.Layout = patternLayout;
            roller.MaxSizeRollBackups = 5;
            roller.RollingStyle = RollingFileAppender.RollingMode.Size;
            roller.StaticLogFileName = true;
            roller.ActivateOptions();
            var l = (Logger)Logger.Logger;
            l.AddAppender(roller);
        }
    }
}

Most Important

In your AssemblyInfo add [assembly: log4net.Config.XmlConfigurator(Watch = true)]

Result

Result

like image 185
lokusking Avatar answered Nov 04 '22 04:11

lokusking