<?xml version="1.0"?>
<!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
    this work for additional information regarding copyright ownership.
    The ASF licenses this file to You under the Apache License, Version 2.0
    (the "License"); you may not use this file except in compliance with
    the License.  You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->

<document xmlns="http://maven.apache.org/XDOC/2.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
  <properties>
    <title>Log4j 2 Usage</title>
    <author email="rgoers@apache.org">Ralph Goers</author>
  </properties>

  <body>
    <section name="Usage">
      <a name="StaticVsNonStatic"/>
      <subsection name="Static vs Non-Static Loggers">
        <p>As with any variable in Java, Loggers may be declared as static variables or class member variables. However,
        there are a few factors to consider when choosing to declare a logger as static vs non-static. Generally, it
        is better to declare Loggers as static.
        <ol>
          <li>
            Instantiation of a new Logger is a fairly expensive operation when using the default ContextSelector,
            <a class="javadoc" href="../log4j-core/apidocs/org/apache/logging/log4j/core/selector/ClassLoaderContextSelector.html">ClassLoaderContextSelector</a>.
            When the Logger is created the <code>ClassLoaderContextSelector</code> will locate the ClassLoader for the Class the Logger
            is associated with and add the Logger to the LoggerContext associated with that ClassLoader.
          </li>
          <li>
            Once a Logger is created it will not be deleted until the <code>LoggerContext</code> it is associated with
            is deleted. Typically, this will only happen when the application is shut down or un-deployed. Each call
            to getLogger with the same logger name will return the same Logger instance. Thus, there is very little
            difference between a static or non-static Logger.
          </li>
          <li>
            There is no behavioral difference between a static and non-static Logger. Both will have the Logger name
            assigned when they are created, which usually will be the name of the class they are associated with. See
            the discussion below on logger names vs class names and the example for more information.
          </li>
        </ol>
         </p>
      </subsection>
      <a name="LoggerVsClass"/>
      <subsection name="Logging the Logger name vs the Class name">
        <p>
          The logger name of a Logger is specified when the Logger is created. When a log method is called the
          class name value in the log event will reflect the name of the class the log method was called from, which is
          not necessarily the same as the class that created the Logger. The following example illustrations this.
        </p>

        <p>The base class creates a static Logger and a logger variable that is initialized as that same Logger.
          It has a method that performs logging, but provides access to two Loggers, one that is static and one
          that can be overridden.
        </p>


<pre class="prettyprint">
  package org.apache.logging;

  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  import org.apache.logging.log4j.Marker;

  /**
  *
  */
  public abstract class Parent {

      // The name of this Logger will be "org.apache.logging.Parent"
      protected static final Logger parentLogger = LogManager.getLogger();

      private Logger logger = parentLogger;

      protected Logger getLogger() {
          return logger;
      }

      protected void setLogger(Logger logger) {
          this.logger = logger;
      }


      public void log(Marker marker) {
          logger.debug(marker,"Parent log message");
      }
  }
</pre>

        <p>
          This class extends the base class. It provides its own logger and has three methods, one that uses the
          logger in this class,one that uses the static logger from the base class, and one that where the logger
          may be set to either the parent or the child.
        </p>

<pre class="prettyprint">
  package org.apache.logging;

  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  import org.apache.logging.log4j.Marker;

  /**
  *
  */
  public class Child extends Parent {

      // The name of this Logge will be "org.apache.logging.Child"
      public Logger childLogger = LogManager.getLogger();

      public void childLog(Marker marker) {
          childLogger.debug(marker,"Child logger message");
      }

      public void logFromChild(Marker marker) {
          getLogger().debug(marker,"Log message from Child");
      }

      public void parentLog(Marker marker) {
          parentLogger.debug(marker,"Parent logger, message from Child");
      }
  }
</pre>
      <p>
        The application exercises all the logging methods four times. The first two times the Logger in the base
        class is set to the static Logger. The second two times the Logger in the base class is set to use the
        Logger in the subclass. In the first and third invocation of each method a null Marker is passed. In the
        second and fourth a Marker named "CLASS" is passed.
      </p>

<pre class="prettyprint">
  package org.apache.logging;

  import org.apache.logging.log4j.Marker;
  import org.apache.logging.log4j.MarkerManager;

  public class App {

      public static void main( String[] args ) {
          Marker marker = MarkerManager.getMarker("CLASS");
          Child child = new Child();

          System.out.println("------- Parent Logger ----------");
          child.log(null);
          child.log(marker);
          child.logFromChild(null);
          child.logFromChild(marker);
          child.parentLog(null);
          child.parentLog(marker);

          child.setLogger(child.childLogger);

          System.out.println("------- Parent Logger set to Child Logger ----------");
          child.log(null);
          child.log(marker);
          child.logFromChild(null);
          child.logFromChild(marker);
      }
  }</pre>

      <p>
        The configuration takes advantage of Log4j's ability to select a pattern based upon attributes of the log event.
        In this case %C, the class name pattern, is used when the CLASS Marker is present, and %c, the logger name
        is used when the CLASS marker is not present.
      </p>
<pre class="prettyprint linenums"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout>
        <MarkerPatternSelector defaultPattern="%sn. %msg: Logger=%logger%n">
          <PatternMatch key="CLASS" pattern="%sn. %msg: Class=%class%n"/>
        </MarkerPatternSelector>
      </PatternLayout>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="TRACE">
      <AppenderRef ref="Console" />
    </Root>
  </Loggers>
</Configuration>]]></pre>

        <p>
          The output below illustrates the difference between using the Logger name and the Class name in the pattern. All
          the odd numbered items print the name of the logger (%c) while all the even numbered items print the
          name of the class that called the logging method (%C). The numbers in the description of the outcomes in the
          following list match the corresponding numbers shown in the output.
          <ol>
            <li>Logging is performed in the parent class using the static logger with the Logger name pattern. The
            logger name matches the name of the parent class.</li>
            <li>Logging is performed in the parent class using the static logger with the Class name pattern. Although
              the method was called against the Child instance it is implemented in Parent so that is what
              appears.</li>
            <li>Logging is performed in Child using the logger in the parent, so the name of the
              parent is printed as the logger name.</li>
            <li>Logging is performed in Child using the logger in the parent. Since the method calling the logging
              method is in Child that is the class name that appears.</li>
            <li>Logging is performed in Child using the static logger in the parent, so the name of the
              parent is printed as the logger name.</li>
            <li>Logging is performed in Child using the static logger in the parent. Since the method calling the logging
              method is in Child that is the class name that appears.</li>

            <li>Logging is performed in the parent class using the logger of Child. The
              logger name matches the name of the child and so it is printed.</li>
            <li>Logging is performed in the parent class using the logger of the Child. Although
              the method was called against the Child instance it is implemented in Parent so that is what
              appears as the class name.</li>
            <li>Logging is performed in Child using the logger in the parent which is set to the child logger,
              so the name of the child is printed as the logger name.</li>
            <li>Logging is performed in Child using the logger in the parent, which is set to the child logger. Since
              the method calling the logging method is in Child that is the class name that appears.</li>
          </ol>
        </p>
<pre class="prettyprint">
  ------- Parent Logger ----------
  1. Parent log message: Logger=org.apache.logging.Parent
  2. Parent log message: Class=org.apache.logging.Parent
  3. Log message from Child: Logger=org.apache.logging.Parent
  4. Log message from Child: Class=org.apache.logging.Child
  5. Parent logger, message from Child: Logger=org.apache.logging.Parent
  6. Parent logger, message from Child: Class=org.apache.logging.Child
  ------- Parent Logger set to Child Logger ----------
  7. Parent log message: Logger=org.apache.logging.Child
  8. Parent log message: Class=org.apache.logging.Parent
  9. Log message from Child: Logger=org.apache.logging.Child
  10. Log message from Child: Class=org.apache.logging.Child
</pre>

        <p>
          In the example above there are two Loggers declared. One is static and one is non-static. When looking at
          the results it is clear that the outcomes would be exactly the same regardless of whether how the loggers
          are declared. The name of the logger will always originate from the class in which it is created and the
          Class name in each log event will always reflect the Class from which the logging method was called.
        </p>
        <p>
          It should be noted that there is a substantial performance penalty for printing the location information
          (class name, method name, and line number). If the method name and line number are not important it is
          usually better to make sure that each class has its own Logger so the logger name accurately reflects the
          class performing the logging.
        </p>


      </subsection>

    </section>
  </body>
</document>
