Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0-rc1
    • Fix Version/s: 2.0
    • Component/s: API
    • Labels:
      None

      Description

      Please try out the attached Generate.java tool that provides the functionality described below and give feedback if you notice any issues.


      Extending the Logger interface
      LOG4J2-41 added support for custom log Levels. Users can now log messages at the new custom level by passing the custom level to the Logger.log() method:

      final Logger logger = LogManager.getLogger();
      final Level VERBOSE = Level.forName("VERBOSE", 550);
      
      logger.log(VERBOSE, "a verbose message");
      logger.log(VERBOSE, "another message");
      

      However, custom levels are not as easy to use as the built-in levels: one needs to call the generic log() method and pass a Level parameter. Built-in levels on the other hand have a set of convenience methods on the Logger interface. For example, the Logger interface has 14 debug methods that support the DEBUG level:

      debug(Marker, Message)
      debug(Marker, Message, Throwable)
      debug(Marker, Object)
      debug(Marker, Object, Throwable)
      debug(Marker, String)
      debug(Marker, String, Object...)
      debug(Marker, String, Throwable)
      debug(Message)
      debug(Message, Throwable)
      debug(Object)
      debug(Object, Throwable)
      debug(String)
      debug(String, Object...)
      debug(String, Throwable)
      

      Similar method sets exist for the other built-in levels.

      Several people have expressed the desire to have the same ease of use with custom levels, so after declaring a custom VERBOSE level, we would like to be able to use code like this:

      logger.verbose("a verbose message"); // no need to pass the VERBOSE level as a parameter
      logger.verbose("another message");
      


      Customizing the Logger interface
      In the above use case, convenience methods were added to the Logger interface, in addition to the existing trace(), debug(), info(), ... methods for the built-in log levels.

      There is another use case, Domain Specific Language loggers, where we want to replace the existing trace(), debug(), info(), ... methods with all-custom methods.

      For example, for medical devices we could have only critical(), warning(), and advisory() methods. Another example could be a game that has only defcon1(), defcon2(), and defcon3() levels.

      Finally, if it were possible to hide existing log levels, users could customize the Logger interface to match their requirements. Some people may not want to have a FATAL or a TRACE level, for example. They would like to be able to create a custom Logger that only has debug(), info(), warn() and error() methods.


      Proposal: Generate source code for a Logger wrapper
      Common log4j usage is to get an instance of the Logger interface from the LogManager and call the methods on this interface. This makes it hard to achieve the above customization; especially taking away existing methods is not possible.

      An alternative is for the user to create a wrapper class that exposes only the convenience methods for the desired log levels. When extending the Logger API (adding methods), this wrapper class could subclass org.apache.logging.log4j.spi.AbstractLoggerWrapper. When customizing the Logger API (removing built-in methods), the wrapper class would simply not extend AbstractLoggerWrapper, so the only public methods would be the methods for the custom log levels.

      As the custom log Levels are not known in advance, Log4J cannot provide pre-built wrapper classes for these custom log Levels. However, we don't want to ask the users to hand-code such a wrapper class: this is cumbersome and error-prone: there are 14 methods for each built-in level. To provide comparable functionality for custom log Levels one would need to provide 14 methods for each custom log Level.

      The proposal is to solve this by providing a tool that generates the source code for a wrapper class. The user can specify:

      • the fully qualified name of the class to generate
      • the list of custom levels to support and their intLevel relative strength
      • whether to extend Logger (and keep the existing built-in methods) or have only methods for the custom log levels

      and the tool generates the source code for the wrapper class that has exactly the required methods. Users would include this source code in the project where they want to use custom log levels.

      Note that no Log4J API changes are required to support this functionality.

      Users would create instances of the wrapper by calling a factory method on the wrapper class, instead of calling the LogManager.getLogger() methods.

      For example, instead of writing:

      import org.apache.logging.log4j.Level;
      import org.apache.logging.log4j.LogManager;
      import org.apache.logging.log4j.Logger;
      
      final Logger logger = LogManager.getLogger(MyClass.class); // standard log4j logger
      final Level VERBOSE = Level.forName("VERBOSE", 550);
      logger.log(VERBOSE, "a verbose message");
      

      users would instead write:

      // MyLogger is a generated customized logger wrapper
      import com.mycompany.myproject.MyLogger;
      
      final MyLogger logger = MyLogger.create(MyClass.class);
      logger.verbose("a verbose message");
      

      Creating an extended or customized Logger is as easy as creating a standard Logger (one line of code). Extended Loggers are drop-in replacements for standard Loggers - they only add more convenience methods.

      1. Generate.java
        26 kB
        Remko Popma
      2. GenerateCustomLoggerTest.java
        5 kB
        Remko Popma
      3. GenerateExtendedLoggerTest.java
        7 kB
        Remko Popma

        Issue Links

          Activity

          Hide
          Remko Popma added a comment - - edited

          Attached a first attempt at a source code generator (Generate.java).

          Usage:
          Command to generate a wrapper that extends AbstractLoggerWrapper:
          java org.apache.logging.log4j.util.Generate$ExtendedLogger com.mycomp.ExtLogger DIAG=350 NOTICE=450 VERBOSE=550

          Command to generate a wrapper that only provides convenience methods for the specified custom levels (and hides the convenience methods for the built-in levels):
          java org.apache.logging.log4j.util.Generate$CustomLogger com.mycomp.MyLogger DEFCON1=350 DEFCON2=450 DEFCON3=550

          Example generated source:

          package com.mycomp;
          
          import org.apache.logging.log4j.Level;
          import org.apache.logging.log4j.LogManager;
          import org.apache.logging.log4j.Logger;
          import org.apache.logging.log4j.Marker;
          import org.apache.logging.log4j.message.Message;
          import org.apache.logging.log4j.message.MessageFactory;
          import org.apache.logging.log4j.spi.AbstractLogger;
          import org.apache.logging.log4j.spi.AbstractLoggerWrapper;
          
          /**
           * Extended Logger interface with convenience methods for
           * the DIAG, NOTICE and VERBOSE custom log levels.
           */
          public final class ExtLogger extends AbstractLoggerWrapper {
              private static final long serialVersionUID = 216489351472874L;
          
              private static final Level DIAG = Level.forName("DIAG", 350);
              private static final Level NOTICE = Level.forName("NOTICE", 450);
              private static final Level VERBOSE = Level.forName("VERBOSE", 550);
          
              private ExtLogger(final Logger logger) {
                  super((AbstractLogger) logger, logger.getName(), logger.getMessageFactory());
              }
          
              /**
               * Returns a custom Logger with the name of the calling class.
               * 
               * @return The custom Logger for the calling class.
               */
              public static ExtLogger create() {
                  final Logger wrapped = LogManager.getLogger();
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Returns a custom Logger using the fully qualified name of the Class as
               * the Logger name.
               * 
               * @param loggerName The Class whose name should be used as the Logger name.
               *            If null it will default to the calling class.
               * @return The custom Logger.
               */
              public static ExtLogger create(final Class<?> loggerName) {
                  final Logger wrapped = LogManager.getLogger(loggerName);
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Returns a custom Logger using the fully qualified name of the Class as
               * the Logger name.
               * 
               * @param loggerName The Class whose name should be used as the Logger name.
               *            If null it will default to the calling class.
               * @param messageFactory The message factory is used only when creating a
               *            logger, subsequent use does not change the logger but will log
               *            a warning if mismatched.
               * @return The custom Logger.
               */
              public static ExtLogger create(final Class<?> loggerName, final MessageFactory factory) {
                  final Logger wrapped = LogManager.getLogger(loggerName, factory);
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Returns a custom Logger using the fully qualified class name of the value
               * as the Logger name.
               * 
               * @param value The value whose class name should be used as the Logger
               *            name. If null the name of the calling class will be used as
               *            the logger name.
               * @return The custom Logger.
               */
              public static ExtLogger create(final Object value) {
                  final Logger wrapped = LogManager.getLogger(value);
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Returns a custom Logger using the fully qualified class name of the value
               * as the Logger name.
               * 
               * @param value The value whose class name should be used as the Logger
               *            name. If null the name of the calling class will be used as
               *            the logger name.
               * @param messageFactory The message factory is used only when creating a
               *            logger, subsequent use does not change the logger but will log
               *            a warning if mismatched.
               * @return The custom Logger.
               */
              public static ExtLogger create(final Object value, final MessageFactory factory) {
                  final Logger wrapped = LogManager.getLogger(value, factory);
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Returns a custom Logger with the specified name.
               * 
               * @param name The logger name. If null the name of the calling class will
               *            be used.
               * @return The custom Logger.
               */
              public static ExtLogger create(final String name) {
                  final Logger wrapped = LogManager.getLogger(name);
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Returns a custom Logger with the specified name.
               * 
               * @param name The logger name. If null the name of the calling class will
               *            be used.
               * @param messageFactory The message factory is used only when creating a
               *            logger, subsequent use does not change the logger but will log
               *            a warning if mismatched.
               * @return The custom Logger.
               */
              public static ExtLogger create(final String name, final MessageFactory factory) {
                  final Logger wrapped = LogManager.getLogger(name, factory);
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               */
              public void diag(final Marker marker, final Message msg) {
                  logger.log(DIAG, marker, msg);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void diag(final Marker marker, final Message msg, final Throwable t) {
                  logger.log(DIAG, marker, msg, t);
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void diag(final Marker marker, final Object message) {
                  logger.log(DIAG, marker, message);
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final Marker marker, final Object message, final Throwable t) {
                  logger.log(DIAG, marker, message, t);
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void diag(final Marker marker, final String message) {
                  logger.log(DIAG, marker, message);
              }
          
              /**
               * Logs a message with parameters at the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void diag(final Marker marker, final String message, final Object... params) {
                  logger.log(DIAG, marker, message, params);
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final Marker marker, final String message, final Throwable t) {
                  logger.log(DIAG, marker, message, t);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code DIAG} level.
               * 
               * @param msg the message string to be logged
               */
              public void diag(final Message msg) {
                  logger.log(DIAG, msg);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code DIAG} level.
               * 
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void diag(final Message msg, final Throwable t) {
                  logger.log(DIAG, msg, t);
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param message the message object to log.
               */
              public void diag(final Object message) {
                  logger.log(DIAG, message);
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final Object message, final Throwable t) {
                  logger.log(DIAG, message, t);
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param message the message object to log.
               */
              public void diag(final String message) {
                  logger.log(DIAG, message);
              }
          
              /**
               * Logs a message with parameters at the {@code DIAG} level.
               * 
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void diag(final String message, final Object... params) {
                  logger.log(DIAG, message, params);
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final String message, final Throwable t) {
                  logger.log(DIAG, message, t);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               */
              public void notice(final Marker marker, final Message msg) {
                  logger.log(NOTICE, marker, msg);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void notice(final Marker marker, final Message msg, final Throwable t) {
                  logger.log(NOTICE, marker, msg, t);
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void notice(final Marker marker, final Object message) {
                  logger.log(NOTICE, marker, message);
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final Marker marker, final Object message, final Throwable t) {
                  logger.log(NOTICE, marker, message, t);
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void notice(final Marker marker, final String message) {
                  logger.log(NOTICE, marker, message);
              }
          
              /**
               * Logs a message with parameters at the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void notice(final Marker marker, final String message, final Object... params) {
                  logger.log(NOTICE, marker, message, params);
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final Marker marker, final String message, final Throwable t) {
                  logger.log(NOTICE, marker, message, t);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code NOTICE} level.
               * 
               * @param msg the message string to be logged
               */
              public void notice(final Message msg) {
                  logger.log(NOTICE, msg);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code NOTICE} level.
               * 
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void notice(final Message msg, final Throwable t) {
                  logger.log(NOTICE, msg, t);
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param message the message object to log.
               */
              public void notice(final Object message) {
                  logger.log(NOTICE, message);
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final Object message, final Throwable t) {
                  logger.log(NOTICE, message, t);
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param message the message object to log.
               */
              public void notice(final String message) {
                  logger.log(NOTICE, message);
              }
          
              /**
               * Logs a message with parameters at the {@code NOTICE} level.
               * 
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void notice(final String message, final Object... params) {
                  logger.log(NOTICE, message, params);
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final String message, final Throwable t) {
                  logger.log(NOTICE, message, t);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               */
              public void verbose(final Marker marker, final Message msg) {
                  logger.log(VERBOSE, marker, msg);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void verbose(final Marker marker, final Message msg, final Throwable t) {
                  logger.log(VERBOSE, marker, msg, t);
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void verbose(final Marker marker, final Object message) {
                  logger.log(VERBOSE, marker, message);
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final Marker marker, final Object message, final Throwable t) {
                  logger.log(VERBOSE, marker, message, t);
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void verbose(final Marker marker, final String message) {
                  logger.log(VERBOSE, marker, message);
              }
          
              /**
               * Logs a message with parameters at the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void verbose(final Marker marker, final String message, final Object... params) {
                  logger.log(VERBOSE, marker, message, params);
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final Marker marker, final String message, final Throwable t) {
                  logger.log(VERBOSE, marker, message, t);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code VERBOSE} level.
               * 
               * @param msg the message string to be logged
               */
              public void verbose(final Message msg) {
                  logger.log(VERBOSE, msg);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code VERBOSE} level.
               * 
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void verbose(final Message msg, final Throwable t) {
                  logger.log(VERBOSE, msg, t);
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param message the message object to log.
               */
              public void verbose(final Object message) {
                  logger.log(VERBOSE, message);
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final Object message, final Throwable t) {
                  logger.log(VERBOSE, message, t);
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param message the message object to log.
               */
              public void verbose(final String message) {
                  logger.log(VERBOSE, message);
              }
          
              /**
               * Logs a message with parameters at the {@code VERBOSE} level.
               * 
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void verbose(final String message, final Object... params) {
                  logger.log(VERBOSE, message, params);
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final String message, final Throwable t) {
                  logger.log(VERBOSE, message, t);
              }
          }
          
          Show
          Remko Popma added a comment - - edited Attached a first attempt at a source code generator (Generate.java). Usage: Command to generate a wrapper that extends AbstractLoggerWrapper: java org.apache.logging.log4j.util.Generate$ExtendedLogger com.mycomp.ExtLogger DIAG=350 NOTICE=450 VERBOSE=550 Command to generate a wrapper that only provides convenience methods for the specified custom levels (and hides the convenience methods for the built-in levels): java org.apache.logging.log4j.util.Generate$CustomLogger com.mycomp.MyLogger DEFCON1=350 DEFCON2=450 DEFCON3=550 Example generated source: package com.mycomp; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.MessageFactory; import org.apache.logging.log4j.spi.AbstractLogger; import org.apache.logging.log4j.spi.AbstractLoggerWrapper; /** * Extended Logger interface with convenience methods for * the DIAG, NOTICE and VERBOSE custom log levels. */ public final class ExtLogger extends AbstractLoggerWrapper { private static final long serialVersionUID = 216489351472874L; private static final Level DIAG = Level.forName( "DIAG" , 350); private static final Level NOTICE = Level.forName( "NOTICE" , 450); private static final Level VERBOSE = Level.forName( "VERBOSE" , 550); private ExtLogger( final Logger logger) { super ((AbstractLogger) logger, logger.getName(), logger.getMessageFactory()); } /** * Returns a custom Logger with the name of the calling class. * * @ return The custom Logger for the calling class. */ public static ExtLogger create() { final Logger wrapped = LogManager.getLogger(); return new ExtLogger(wrapped); } /** * Returns a custom Logger using the fully qualified name of the Class as * the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. * If null it will default to the calling class. * @ return The custom Logger. */ public static ExtLogger create( final Class <?> loggerName) { final Logger wrapped = LogManager.getLogger(loggerName); return new ExtLogger(wrapped); } /** * Returns a custom Logger using the fully qualified name of the Class as * the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. * If null it will default to the calling class. * @param messageFactory The message factory is used only when creating a * logger, subsequent use does not change the logger but will log * a warning if mismatched. * @ return The custom Logger. */ public static ExtLogger create( final Class <?> loggerName, final MessageFactory factory) { final Logger wrapped = LogManager.getLogger(loggerName, factory); return new ExtLogger(wrapped); } /** * Returns a custom Logger using the fully qualified class name of the value * as the Logger name. * * @param value The value whose class name should be used as the Logger * name. If null the name of the calling class will be used as * the logger name. * @ return The custom Logger. */ public static ExtLogger create( final Object value) { final Logger wrapped = LogManager.getLogger(value); return new ExtLogger(wrapped); } /** * Returns a custom Logger using the fully qualified class name of the value * as the Logger name. * * @param value The value whose class name should be used as the Logger * name. If null the name of the calling class will be used as * the logger name. * @param messageFactory The message factory is used only when creating a * logger, subsequent use does not change the logger but will log * a warning if mismatched. * @ return The custom Logger. */ public static ExtLogger create( final Object value, final MessageFactory factory) { final Logger wrapped = LogManager.getLogger(value, factory); return new ExtLogger(wrapped); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will * be used. * @ return The custom Logger. */ public static ExtLogger create( final String name) { final Logger wrapped = LogManager.getLogger(name); return new ExtLogger(wrapped); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will * be used. * @param messageFactory The message factory is used only when creating a * logger, subsequent use does not change the logger but will log * a warning if mismatched. * @ return The custom Logger. */ public static ExtLogger create( final String name, final MessageFactory factory) { final Logger wrapped = LogManager.getLogger(name, factory); return new ExtLogger(wrapped); } /** * Logs a message with the specific Marker at the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged */ public void diag( final Marker marker, final Message msg) { logger.log(DIAG, marker, msg); } /** * Logs a message with the specific Marker at the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged * @param t A Throwable or null . */ public void diag( final Marker marker, final Message msg, final Throwable t) { logger.log(DIAG, marker, msg, t); } /** * Logs a message object with the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void diag( final Marker marker, final Object message) { logger.log(DIAG, marker, message); } /** * Logs a message at the {@code DIAG} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final Marker marker, final Object message, final Throwable t) { logger.log(DIAG, marker, message, t); } /** * Logs a message object with the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void diag( final Marker marker, final String message) { logger.log(DIAG, marker, message); } /** * Logs a message with parameters at the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void diag( final Marker marker, final String message, final Object ... params) { logger.log(DIAG, marker, message, params); } /** * Logs a message at the {@code DIAG} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final Marker marker, final String message, final Throwable t) { logger.log(DIAG, marker, message, t); } /** * Logs a message with the specific Marker at the {@code DIAG} level. * * @param msg the message string to be logged */ public void diag( final Message msg) { logger.log(DIAG, msg); } /** * Logs a message with the specific Marker at the {@code DIAG} level. * * @param msg the message string to be logged * @param t A Throwable or null . */ public void diag( final Message msg, final Throwable t) { logger.log(DIAG, msg, t); } /** * Logs a message object with the {@code DIAG} level. * * @param message the message object to log. */ public void diag( final Object message) { logger.log(DIAG, message); } /** * Logs a message at the {@code DIAG} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final Object message, final Throwable t) { logger.log(DIAG, message, t); } /** * Logs a message object with the {@code DIAG} level. * * @param message the message object to log. */ public void diag( final String message) { logger.log(DIAG, message); } /** * Logs a message with parameters at the {@code DIAG} level. * * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void diag( final String message, final Object ... params) { logger.log(DIAG, message, params); } /** * Logs a message at the {@code DIAG} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final String message, final Throwable t) { logger.log(DIAG, message, t); } /** * Logs a message with the specific Marker at the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged */ public void notice( final Marker marker, final Message msg) { logger.log(NOTICE, marker, msg); } /** * Logs a message with the specific Marker at the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged * @param t A Throwable or null . */ public void notice( final Marker marker, final Message msg, final Throwable t) { logger.log(NOTICE, marker, msg, t); } /** * Logs a message object with the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void notice( final Marker marker, final Object message) { logger.log(NOTICE, marker, message); } /** * Logs a message at the {@code NOTICE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final Marker marker, final Object message, final Throwable t) { logger.log(NOTICE, marker, message, t); } /** * Logs a message object with the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void notice( final Marker marker, final String message) { logger.log(NOTICE, marker, message); } /** * Logs a message with parameters at the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void notice( final Marker marker, final String message, final Object ... params) { logger.log(NOTICE, marker, message, params); } /** * Logs a message at the {@code NOTICE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final Marker marker, final String message, final Throwable t) { logger.log(NOTICE, marker, message, t); } /** * Logs a message with the specific Marker at the {@code NOTICE} level. * * @param msg the message string to be logged */ public void notice( final Message msg) { logger.log(NOTICE, msg); } /** * Logs a message with the specific Marker at the {@code NOTICE} level. * * @param msg the message string to be logged * @param t A Throwable or null . */ public void notice( final Message msg, final Throwable t) { logger.log(NOTICE, msg, t); } /** * Logs a message object with the {@code NOTICE} level. * * @param message the message object to log. */ public void notice( final Object message) { logger.log(NOTICE, message); } /** * Logs a message at the {@code NOTICE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final Object message, final Throwable t) { logger.log(NOTICE, message, t); } /** * Logs a message object with the {@code NOTICE} level. * * @param message the message object to log. */ public void notice( final String message) { logger.log(NOTICE, message); } /** * Logs a message with parameters at the {@code NOTICE} level. * * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void notice( final String message, final Object ... params) { logger.log(NOTICE, message, params); } /** * Logs a message at the {@code NOTICE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final String message, final Throwable t) { logger.log(NOTICE, message, t); } /** * Logs a message with the specific Marker at the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged */ public void verbose( final Marker marker, final Message msg) { logger.log(VERBOSE, marker, msg); } /** * Logs a message with the specific Marker at the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged * @param t A Throwable or null . */ public void verbose( final Marker marker, final Message msg, final Throwable t) { logger.log(VERBOSE, marker, msg, t); } /** * Logs a message object with the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void verbose( final Marker marker, final Object message) { logger.log(VERBOSE, marker, message); } /** * Logs a message at the {@code VERBOSE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final Marker marker, final Object message, final Throwable t) { logger.log(VERBOSE, marker, message, t); } /** * Logs a message object with the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void verbose( final Marker marker, final String message) { logger.log(VERBOSE, marker, message); } /** * Logs a message with parameters at the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void verbose( final Marker marker, final String message, final Object ... params) { logger.log(VERBOSE, marker, message, params); } /** * Logs a message at the {@code VERBOSE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final Marker marker, final String message, final Throwable t) { logger.log(VERBOSE, marker, message, t); } /** * Logs a message with the specific Marker at the {@code VERBOSE} level. * * @param msg the message string to be logged */ public void verbose( final Message msg) { logger.log(VERBOSE, msg); } /** * Logs a message with the specific Marker at the {@code VERBOSE} level. * * @param msg the message string to be logged * @param t A Throwable or null . */ public void verbose( final Message msg, final Throwable t) { logger.log(VERBOSE, msg, t); } /** * Logs a message object with the {@code VERBOSE} level. * * @param message the message object to log. */ public void verbose( final Object message) { logger.log(VERBOSE, message); } /** * Logs a message at the {@code VERBOSE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final Object message, final Throwable t) { logger.log(VERBOSE, message, t); } /** * Logs a message object with the {@code VERBOSE} level. * * @param message the message object to log. */ public void verbose( final String message) { logger.log(VERBOSE, message); } /** * Logs a message with parameters at the {@code VERBOSE} level. * * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void verbose( final String message, final Object ... params) { logger.log(VERBOSE, message, params); } /** * Logs a message at the {@code VERBOSE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final String message, final Throwable t) { logger.log(VERBOSE, message, t); } }
          Hide
          Remko Popma added a comment -

          Updated attached file "Generate.java" with code change for the renamed method Level.getOrCreateLevel() to Level.forName().

          Show
          Remko Popma added a comment - Updated attached file "Generate.java" with code change for the renamed method Level.getOrCreateLevel() to Level.forName() .
          Hide
          Remko Popma added a comment - - edited

          Modified code snippet in description for method change Level.getOrCreateLevel() to Level.forName(), added anchor links.

          Show
          Remko Popma added a comment - - edited Modified code snippet in description for method change Level.getOrCreateLevel() to Level.forName() , added anchor links.
          Hide
          Bruce Brouwer added a comment -

          So how would this actually get used? Would you use this with APT, or maybe a Maven plugin?

          Show
          Bruce Brouwer added a comment - So how would this actually get used? Would you use this with APT, or maybe a Maven plugin?
          Hide
          Remko Popma added a comment -

          How to use the Generate tool
          Please follow the steps below. You only need to do this once.

          1. Suppose you decide you want to use custom log levels, e.g. WARN > DIAG > INFO > NOTICE > DEBUG > VERBOSE > TRACE, and you want a convenient API
          2. Download the attached file Generate.java and compile with javac -d org/apache/logging/log4j/util Generate.java
          3. Generate an extended logger with java org.apache.logging.log4j.util.Generate$ExtendedLogger com.mycomp.myproject.util.ExtendedLogger DIAG=350 NOTICE=450 VERBOSE=550 > ExtendedLogger.java
          4. Copy the generated ExtendedLogger.java to the com.mycomp.myproject.util package of your project.

          That's it. You're done. Now in your project you can write:

          import com.mycomp.myproject.util.ExtendedLogger;
          
          final ExtendedLogger logger = ExtendedLogger.create(MyClass.class);
          logger.warn("This is a warning");
          logger.diag("This is a diagnostic message");
          logger.info("This is an info message");
          logger.notice("This is a notice message");
          logger.debug("This is a debug message");
          

          There is no need for Maven or APT to take some additional action at compile time or runtime. Once you've generated the ExtendedLogger class you just use it in your project like any other class.

          Show
          Remko Popma added a comment - How to use the Generate tool Please follow the steps below. You only need to do this once. Suppose you decide you want to use custom log levels, e.g. WARN > DIAG > INFO > NOTICE > DEBUG > VERBOSE > TRACE, and you want a convenient API Download the attached file Generate.java and compile with javac -d org/apache/logging/log4j/util Generate.java Generate an extended logger with java org.apache.logging.log4j.util.Generate$ExtendedLogger com.mycomp.myproject.util.ExtendedLogger DIAG=350 NOTICE=450 VERBOSE=550 > ExtendedLogger.java Copy the generated ExtendedLogger.java to the com.mycomp.myproject.util package of your project. That's it. You're done. Now in your project you can write: import com.mycomp.myproject.util.ExtendedLogger; final ExtendedLogger logger = ExtendedLogger.create(MyClass.class); logger.warn( "This is a warning" ); logger.diag( "This is a diagnostic message" ); logger.info( "This is an info message" ); logger.notice( "This is a notice message" ); logger.debug( "This is a debug message" ); There is no need for Maven or APT to take some additional action at compile time or runtime. Once you've generated the ExtendedLogger class you just use it in your project like any other class.
          Hide
          Bruce Brouwer added a comment -

          Thanks for that explanation. What I was trying to get at, though, is that there are good tools available that can tie code generation such as this into your build tool, so wouldn't that be a better place for this?

          And speaking of a place, where exactly would you recommend this Generate code be placed? log4j-core seem kind of arbitrary to me. And if it went into a new artifact, then why not make it a maven plugin? (You can probably tell that I'm a fan of Maven).

          And if this code generation was tied into the Maven build lifecycle, upgrading the Maven plugin would get me enhancements and bug fixes automatically without requiring me to remember that now I need to update this generated wrapper.

          If you like the idea of this Maven approach, I could contribute a patch.

          Show
          Bruce Brouwer added a comment - Thanks for that explanation. What I was trying to get at, though, is that there are good tools available that can tie code generation such as this into your build tool, so wouldn't that be a better place for this? And speaking of a place, where exactly would you recommend this Generate code be placed? log4j-core seem kind of arbitrary to me. And if it went into a new artifact, then why not make it a maven plugin? (You can probably tell that I'm a fan of Maven). And if this code generation was tied into the Maven build lifecycle, upgrading the Maven plugin would get me enhancements and bug fixes automatically without requiring me to remember that now I need to update this generated wrapper. If you like the idea of this Maven approach, I could contribute a patch.
          Hide
          Gary Gregory added a comment -
          final ExtendedLogger logger = ExtendedLogger.create(MyClass.class);
          

          Why is the factory method not called getLogger(Class)?
          That would make it like LogManager.getLogger(Class)

          Show
          Gary Gregory added a comment - final ExtendedLogger logger = ExtendedLogger.create(MyClass.class); Why is the factory method not called getLogger(Class) ? That would make it like LogManager.getLogger(Class)
          Hide
          Gary Gregory added a comment -

          Can this tool generate a logger class that does not extend the stock logger?

          If you have not read about my DEFCON example on the ML, the idea is to have a logger that only implements defcon1(), defcon2(), ..., defcon5(). No warn, info and so on.

          Show
          Gary Gregory added a comment - Can this tool generate a logger class that does not extend the stock logger? If you have not read about my DEFCON example on the ML, the idea is to have a logger that only implements defcon1(), defcon2(), ..., defcon5(). No warn, info and so on.
          Hide
          Remko Popma added a comment -

          Bruce, there is still discussion going on on the mailing list (currently pending as we are all focusing on the upcoming 2.0 GA release), about which approach to take. Your argument to automatically benefit from bugfixes/enhancements was mentioned on the ML as an argument to have a generated or hand-coded interface instead of an implementation class.
          The log4j library would then generate an implementation at runtime. Personally, I like the simplicity of the concrete class approach, but there are many trade-offs here and I am sure that the discussion is not finished yet.

          Show
          Remko Popma added a comment - Bruce, there is still discussion going on on the mailing list (currently pending as we are all focusing on the upcoming 2.0 GA release), about which approach to take. Your argument to automatically benefit from bugfixes/enhancements was mentioned on the ML as an argument to have a generated or hand-coded interface instead of an implementation class. The log4j library would then generate an implementation at runtime. Personally, I like the simplicity of the concrete class approach, but there are many trade-offs here and I am sure that the discussion is not finished yet.
          Hide
          Remko Popma added a comment - - edited

          Gary,
          I agree, naming the factory method getLogger(Class) is probably better.

          Yes, this tool can generate a logger that does not extend from AbstractLogger. There is a section on this in the description above. (The command is briefly mentioned in my first comment above, but it is easy to overlook.)

          The command to generate a wrapper that only provides convenience methods for the specified custom levels (and hides the convenience methods for the built-in levels) is:
          java org.apache.logging.log4j.util.Generate$CustomLogger com.mycomp.MyLogger DEFCON1=350 DEFCON2=450 DEFCON3=550

          The generated MyLogger class only has defcon1(), defcon2(), ... methods, no info(), debug(), warn(), etc.

          (There are two tools in this class: Generate$ExtendedLogger and Generate$CustomLogger.)

          Show
          Remko Popma added a comment - - edited Gary, I agree, naming the factory method getLogger(Class) is probably better. Yes, this tool can generate a logger that does not extend from AbstractLogger . There is a section on this in the description above. (The command is briefly mentioned in my first comment above, but it is easy to overlook.) The command to generate a wrapper that only provides convenience methods for the specified custom levels (and hides the convenience methods for the built-in levels) is: java org.apache.logging.log4j.util.Generate$CustomLogger com.mycomp.MyLogger DEFCON1=350 DEFCON2=450 DEFCON3=550 The generated MyLogger class only has defcon1() , defcon2() , ... methods, no info() , debug() , warn() , etc. (There are two tools in this class: Generate$ExtendedLogger and Generate$CustomLogger .)
          Hide
          Bruce Brouwer added a comment -

          If we call it .getLogger(...), I as a user might expect to get the exact same instance back from repeated calls. So in this sense, .create(...) would be a better fit. I like the idea of .getLogger(..) best, but would like it to return the same instance each time.

          I didn't yet dig deeper into LogManager.getLogger(...) to determine if I get the exact same instance, but I would assume it is the same instance for each call given the same class name. Perhaps there is some way to use the LoggerContext to retrieve the exact same instance of this custom logger. Or maybe stuff the custom logger into some property on the logger retrieved from LogManager.getLogger(...). I'm just throwing out ideas.

          I honestly just started poking around looking to see how I could help get log4j2 out the door because my company is not terribly interested in using beta software in production. So I actually have very little need for this feature. I personally would rather see this wait until later so we can release 2.0 sooner. I'll check out the mailing lists to see if there is somewhere else that I could better help.

          Show
          Bruce Brouwer added a comment - If we call it .getLogger(...) , I as a user might expect to get the exact same instance back from repeated calls. So in this sense, .create(...) would be a better fit. I like the idea of .getLogger(..) best, but would like it to return the same instance each time. I didn't yet dig deeper into LogManager.getLogger(...) to determine if I get the exact same instance, but I would assume it is the same instance for each call given the same class name. Perhaps there is some way to use the LoggerContext to retrieve the exact same instance of this custom logger. Or maybe stuff the custom logger into some property on the logger retrieved from LogManager.getLogger(...) . I'm just throwing out ideas. I honestly just started poking around looking to see how I could help get log4j2 out the door because my company is not terribly interested in using beta software in production. So I actually have very little need for this feature. I personally would rather see this wait until later so we can release 2.0 sooner. I'll check out the mailing lists to see if there is somewhere else that I could better help.
          Hide
          Remko Popma added a comment -

          Bruce, interesting point, I hadn't thought of that. I think LogManager.getLogger() does return the same instance. Custom/ExtendedLogger.getLogger() would need to do its own caching if we want to provide the same guarantees. Hmm, food for thought...

          Anyway, consensus on the mailing list was to leave this for the time being until after the 2.0 GA release.
          Help with other issues is of course always welcome!

          Show
          Remko Popma added a comment - Bruce, interesting point, I hadn't thought of that. I think LogManager.getLogger() does return the same instance. Custom/ExtendedLogger.getLogger() would need to do its own caching if we want to provide the same guarantees. Hmm, food for thought... Anyway, consensus on the mailing list was to leave this for the time being until after the 2.0 GA release. Help with other issues is of course always welcome!
          Hide
          vibin added a comment - - edited

          Found an issue while testing the custom log level, it does print incorrect Class name, it prints WrapperClass name instead actual class where the logs are originated.
          Find example below:
          The NOTICE level prints incorrect class name in the log file, it prints WrapperClass name instead of "TestApp", any solution to this issue ?

          2014-03-01 08:19:16,551 ERROR c.h.i.d.t.TestApp [main] test message
          2014-03-01 08:19:16,551 WARN c.h.i.d.t.TestApp [main] test message
          2014-03-01 08:19:16,551 INFO c.h.i.d.t.TestApp [main] test message
          2014-03-01 08:19:16,551 DEBUG c.h.i.d.t.TestApp [main] test message
          2014-03-01 08:19:16,551 TRACE c.h.i.d.t.TestApp [main] test message
          2014-03-01 08:19:16,551 NOTICE c.h.i.d.l.w.LoggerWrapper [main] test message

          Thanks.

          Show
          vibin added a comment - - edited Found an issue while testing the custom log level, it does print incorrect Class name, it prints WrapperClass name instead actual class where the logs are originated. Find example below: The NOTICE level prints incorrect class name in the log file, it prints WrapperClass name instead of "TestApp", any solution to this issue ? 2014-03-01 08:19:16,551 ERROR c.h.i.d.t.TestApp [main] test message 2014-03-01 08:19:16,551 WARN c.h.i.d.t.TestApp [main] test message 2014-03-01 08:19:16,551 INFO c.h.i.d.t.TestApp [main] test message 2014-03-01 08:19:16,551 DEBUG c.h.i.d.t.TestApp [main] test message 2014-03-01 08:19:16,551 TRACE c.h.i.d.t.TestApp [main] test message 2014-03-01 08:19:16,551 NOTICE c.h.i.d.l.w.LoggerWrapper [main] test message Thanks.
          Hide
          Ralph Goers added a comment -

          I don't see how the log level would affect the class name. In your custom logger did you set the FQCN properly?

          Show
          Ralph Goers added a comment - I don't see how the log level would affect the class name. In your custom logger did you set the FQCN properly?
          Hide
          Ralph Goers added a comment -

          Can you provide some sample code to demonstrate this?

          Show
          Ralph Goers added a comment - Can you provide some sample code to demonstrate this?
          Hide
          vibin added a comment -

          The example generated code given in this article doesn't contain FQCN properly,I just followed the same. If it is required can you explain how to set FQCN property ?

          Show
          vibin added a comment - The example generated code given in this article doesn't contain FQCN properly,I just followed the same. If it is required can you explain how to set FQCN property ?
          Hide
          vibin added a comment -

          Here is the code :

          Wrapper class:
          *****************
          public final class DPLogger extends AbstractLoggerWrapper
          {
          private static final long serialVersionUID = 216489351472874L;

          private static final Level NOTICE = Level.forName("NOTICE", 450);

          private DPLogger(final Logger logger)

          { super((AbstractLogger) logger, logger.getName(), logger.getMessageFactory()); }

          /**

          • Returns a custom Logger with the name of the calling class.
          • @return The custom Logger for the calling class.
            */
            public static DPLogger create() { final Logger wrapped = LogManager.getLogger(); return new DPLogger(wrapped); }

          /**

          • Returns a custom Logger using the fully qualified name of the Class as
          • the Logger name.
          • @param loggerName The Class whose name should be used as the Logger name.
          • If null it will default to the calling class.
          • @return The custom Logger.
            */
            public static DPLogger create(final Class<?> loggerName) { final Logger wrapped = LogManager.getLogger(loggerName); return new DPLogger(wrapped); }

            ...
            }

          Test App:
          *************
          public class DPTestLogger {

          public static void main(String[] args) {
          // TODO Auto-generated method stub

          final DPLogger logger = DPLogger.create(DPTestLogger.class);

          //DPLog logger = new DPLog(DPTestLogger.class);

          try

          { logger.fatal("test"); logger.error("test"); logger.warn("test"); logger.info("test"); logger.debug("test"); logger.trace("test"); logger.notice("Notice"); }

          catch (Exception e)

          { // TODO Auto-generated catch block e.printStackTrace(); }

          }
          Printed log
          ****************
          2014-03-01 12:45:22,300 FATAL c.h.i.d.t.DPTestLogger [main] test
          2014-03-01 12:45:22,301 ERROR c.h.i.d.t.DPTestLogger [main] test
          2014-03-01 12:45:22,301 WARN c.h.i.d.t.DPTestLogger [main] test
          2014-03-01 12:45:22,301 INFO c.h.i.d.t.DPTestLogger [main] test
          2014-03-01 12:45:22,301 DEBUG c.h.i.d.t.DPTestLogger [main] test
          2014-03-01 12:45:22,301 TRACE c.h.i.d.t.DPTestLogger [main] test
          2014-03-01 12:45:22,302 NOTICE c.h.i.d.l.w.DPLogger [main] Notice

          Show
          vibin added a comment - Here is the code : Wrapper class: ***************** public final class DPLogger extends AbstractLoggerWrapper { private static final long serialVersionUID = 216489351472874L; private static final Level NOTICE = Level.forName("NOTICE", 450); private DPLogger(final Logger logger) { super((AbstractLogger) logger, logger.getName(), logger.getMessageFactory()); } /** Returns a custom Logger with the name of the calling class. @return The custom Logger for the calling class. */ public static DPLogger create() { final Logger wrapped = LogManager.getLogger(); return new DPLogger(wrapped); } /** Returns a custom Logger using the fully qualified name of the Class as the Logger name. @param loggerName The Class whose name should be used as the Logger name. If null it will default to the calling class. @return The custom Logger. */ public static DPLogger create(final Class<?> loggerName) { final Logger wrapped = LogManager.getLogger(loggerName); return new DPLogger(wrapped); } ... } Test App: ************* public class DPTestLogger { public static void main(String[] args) { // TODO Auto-generated method stub final DPLogger logger = DPLogger.create(DPTestLogger.class); //DPLog logger = new DPLog(DPTestLogger.class); try { logger.fatal("test"); logger.error("test"); logger.warn("test"); logger.info("test"); logger.debug("test"); logger.trace("test"); logger.notice("Notice"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } Printed log **************** 2014-03-01 12:45:22,300 FATAL c.h.i.d.t.DPTestLogger [main] test 2014-03-01 12:45:22,301 ERROR c.h.i.d.t.DPTestLogger [main] test 2014-03-01 12:45:22,301 WARN c.h.i.d.t.DPTestLogger [main] test 2014-03-01 12:45:22,301 INFO c.h.i.d.t.DPTestLogger [main] test 2014-03-01 12:45:22,301 DEBUG c.h.i.d.t.DPTestLogger [main] test 2014-03-01 12:45:22,301 TRACE c.h.i.d.t.DPTestLogger [main] test 2014-03-01 12:45:22,302 NOTICE c.h.i.d.l.w.DPLogger [main] Notice
          Hide
          Ralph Goers added a comment - - edited

          in AbstractLoggerWrapper you will notice that the log method contains an fqcn parameter. This value must contain the fully qualified class name of the class that implements your logging. In this case I would guess that to be LoggerWrapper. Log4j uses this to determine the caller information - it traverses the stack until it finds the entry prior to the class named as the fqcn. So if the fqcn is incorrect then the caller information will be incorrect.

          I presume you are referring to the code Remko supplied above. I haven't reviewed it, but if you just copied that then obviously it has a problem with regard to properly setting the fqcn.

          Show
          Ralph Goers added a comment - - edited in AbstractLoggerWrapper you will notice that the log method contains an fqcn parameter. This value must contain the fully qualified class name of the class that implements your logging. In this case I would guess that to be LoggerWrapper. Log4j uses this to determine the caller information - it traverses the stack until it finds the entry prior to the class named as the fqcn. So if the fqcn is incorrect then the caller information will be incorrect. I presume you are referring to the code Remko supplied above. I haven't reviewed it, but if you just copied that then obviously it has a problem with regard to properly setting the fqcn.
          Hide
          Ralph Goers added a comment -

          logger.fatal, logger.error, etc all go straight to AbstractLogger, which is why you get the correct class name - the methods in AbstractLogger all use AbstractLogger as the FQCN. However, the logger.diag and logger.notice methods in Remko's example are all calling a logger.log method that does not contain an FQCN, which is why the caller info is wrong.

          Show
          Ralph Goers added a comment - logger.fatal, logger.error, etc all go straight to AbstractLogger, which is why you get the correct class name - the methods in AbstractLogger all use AbstractLogger as the FQCN. However, the logger.diag and logger.notice methods in Remko's example are all calling a logger.log method that does not contain an FQCN, which is why the caller info is wrong.
          Hide
          vibin added a comment -

          Is there a quick solution to fix this issue ..? i tried setting FQCN in the wrapper calss , did not work..

          Show
          vibin added a comment - Is there a quick solution to fix this issue ..? i tried setting FQCN in the wrapper calss , did not work..
          Hide
          Remko Popma added a comment - - edited

          vibin, thanks a lot for testing this!
          The quick fix may be to use %c (lowercase) in your pattern layout instead of %C (upper case). This will use the logger name instead of its class and as a side-effect will be about ten times faster (depending on how many threads you use) because it doesn't use reflection.

          Ralph, this looks like a bug:
          it basically means that any location-based logic is broken for loggers that subclass AbstractLoggerWrapper. I've raised LOG4J2-555 for this.

          Show
          Remko Popma added a comment - - edited vibin, thanks a lot for testing this! The quick fix may be to use %c (lowercase) in your pattern layout instead of %C (upper case). This will use the logger name instead of its class and as a side-effect will be about ten times faster (depending on how many threads you use) because it doesn't use reflection. Ralph, this looks like a bug: it basically means that any location-based logic is broken for loggers that subclass AbstractLoggerWrapper. I've raised LOG4J2-555 for this.
          Hide
          Remko Popma added a comment -

          I've updated the attached Generate.java tool to keep track of its own FQCN and always call the log(Marker, String, Level, Message, Throwable) method. That should solve the problem even when using %C or other location patterns in the layout.

          Example code below for an Extended logger is generated with the command

          java org.apache.logging.log4j.util.Generate$ExtendedLogger com.mycomp.ExtLogger DIAG=350 NOTICE=450 VERBOSE=550
          

          to generate a wrapper that only provides convenience methods for the specified custom levels (and hides the convenience methods for the built-in levels), use the CustomLogger tool:

          java org.apache.logging.log4j.util.Generate$CustomLogger com.mycomp.MyLogger DEFCON1=350 DEFCON2=450 DEFCON3=550
          

          Sample generated code:

          package com.mycomp;
          
          import org.apache.logging.log4j.Level;
          import org.apache.logging.log4j.LogManager;
          import org.apache.logging.log4j.Logger;
          import org.apache.logging.log4j.Marker;
          import org.apache.logging.log4j.message.Message;
          import org.apache.logging.log4j.message.MessageFactory;
          import org.apache.logging.log4j.spi.AbstractLogger;
          import org.apache.logging.log4j.spi.AbstractLoggerWrapper;
          
          /**
           * Extended Logger interface with convenience methods for
           * the DIAG, NOTICE and VERBOSE custom log levels.
           */
          public final class ExtLogger extends AbstractLoggerWrapper {
              private static final long serialVersionUID = 26876940739430L;
              private final AbstractLoggerWrapper logger;
          
              private static final String FQCN = ExtLogger.class.getName();
              private static final Level DIAG = Level.forName("DIAG", 350);
              private static final Level NOTICE = Level.forName("NOTICE", 450);
              private static final Level VERBOSE = Level.forName("VERBOSE", 550);
          
              private ExtLogger(final Logger logger) {
                  super((AbstractLogger) logger, logger.getName(), logger.getMessageFactory());
                  this.logger = this;
              }
          
              /**
               * Returns a custom Logger with the name of the calling class.
               * 
               * @return The custom Logger for the calling class.
               */
              public static ExtLogger create() {
                  final Logger wrapped = LogManager.getLogger();
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Returns a custom Logger using the fully qualified name of the Class as
               * the Logger name.
               * 
               * @param loggerName The Class whose name should be used as the Logger name.
               *            If null it will default to the calling class.
               * @return The custom Logger.
               */
              public static ExtLogger create(final Class<?> loggerName) {
                  final Logger wrapped = LogManager.getLogger(loggerName);
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Returns a custom Logger using the fully qualified name of the Class as
               * the Logger name.
               * 
               * @param loggerName The Class whose name should be used as the Logger name.
               *            If null it will default to the calling class.
               * @param messageFactory The message factory is used only when creating a
               *            logger, subsequent use does not change the logger but will log
               *            a warning if mismatched.
               * @return The custom Logger.
               */
              public static ExtLogger create(final Class<?> loggerName, final MessageFactory factory) {
                  final Logger wrapped = LogManager.getLogger(loggerName, factory);
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Returns a custom Logger using the fully qualified class name of the value
               * as the Logger name.
               * 
               * @param value The value whose class name should be used as the Logger
               *            name. If null the name of the calling class will be used as
               *            the logger name.
               * @return The custom Logger.
               */
              public static ExtLogger create(final Object value) {
                  final Logger wrapped = LogManager.getLogger(value);
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Returns a custom Logger using the fully qualified class name of the value
               * as the Logger name.
               * 
               * @param value The value whose class name should be used as the Logger
               *            name. If null the name of the calling class will be used as
               *            the logger name.
               * @param messageFactory The message factory is used only when creating a
               *            logger, subsequent use does not change the logger but will log
               *            a warning if mismatched.
               * @return The custom Logger.
               */
              public static ExtLogger create(final Object value, final MessageFactory factory) {
                  final Logger wrapped = LogManager.getLogger(value, factory);
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Returns a custom Logger with the specified name.
               * 
               * @param name The logger name. If null the name of the calling class will
               *            be used.
               * @return The custom Logger.
               */
              public static ExtLogger create(final String name) {
                  final Logger wrapped = LogManager.getLogger(name);
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Returns a custom Logger with the specified name.
               * 
               * @param name The logger name. If null the name of the calling class will
               *            be used.
               * @param messageFactory The message factory is used only when creating a
               *            logger, subsequent use does not change the logger but will log
               *            a warning if mismatched.
               * @return The custom Logger.
               */
              public static ExtLogger create(final String name, final MessageFactory factory) {
                  final Logger wrapped = LogManager.getLogger(name, factory);
                  return new ExtLogger(wrapped);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               */
              public void diag(final Marker marker, final Message msg) {
                  if (logger.isEnabled(DIAG, marker, msg, (Throwable) null)) {
                      logger.log(marker, FQCN, DIAG, msg, null);
                  }
              }
          
              /**
               * Logs a message with the specific Marker at the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void diag(final Marker marker, final Message msg, final Throwable t) {
                  if (logger.isEnabled(DIAG, marker, msg, t)) {
                      logger.log(marker, FQCN, DIAG, msg, t);
                  }
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void diag(final Marker marker, final Object message) {
                  if (logger.isEnabled(DIAG, marker, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(marker, FQCN, DIAG, msg, null);
                  }
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final Marker marker, final Object message, final Throwable t) {
                  if (logger.isEnabled(DIAG, marker, message, t)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(marker, FQCN, DIAG, msg, t);
                  }
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void diag(final Marker marker, final String message) {
                  if (logger.isEnabled(DIAG, marker, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(marker, FQCN, DIAG, msg, null);
                  }
              }
          
              /**
               * Logs a message with parameters at the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void diag(final Marker marker, final String message, final Object... params) {
                  if (logger.isEnabled(DIAG, marker, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message, params);
                      logger.log(marker, FQCN, DIAG, msg, msg.getThrowable());
                  }
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final Marker marker, final String message, final Throwable t) {
                  if (logger.isEnabled(DIAG, marker, message, t)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(marker, FQCN, DIAG, msg, t);
                  }
              }
          
              /**
               * Logs the specified Message at the {@code DIAG} level.
               * 
               * @param msg the message string to be logged
               */
              public void diag(final Message msg) {
                  if (logger.isEnabled(DIAG, null, msg, (Throwable) null)) {
                      logger.log(null, FQCN, DIAG, msg, null);
                  }
              }
          
              /**
               * Logs the specified Message at the {@code DIAG} level.
               * 
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void diag(final Message msg, final Throwable t) {
                  if (logger.isEnabled(DIAG, null, msg, t)) {
                      logger.log(null, FQCN, DIAG, msg, t);
                  }
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param message the message object to log.
               */
              public void diag(final Object message) {
                  if (logger.isEnabled(DIAG, null, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(null, FQCN, DIAG, msg, null);
                  }
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final Object message, final Throwable t) {
                  if (logger.isEnabled(DIAG, null, message, t)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(null, FQCN, DIAG, msg, t);
                  }
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param message the message object to log.
               */
              public void diag(final String message) {
                  if (logger.isEnabled(DIAG, null, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(null, FQCN, DIAG, msg, null);
                  }
              }
          
              /**
               * Logs a message with parameters at the {@code DIAG} level.
               * 
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void diag(final String message, final Object... params) {
                  if (logger.isEnabled(DIAG, null, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message, params);
                      logger.log(null, FQCN, DIAG, msg, msg.getThrowable());
                  }
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final String message, final Throwable t) {
                  if (logger.isEnabled(DIAG, null, message, t)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(null, FQCN, DIAG, msg, t);
                  }
              }
          
              /**
               * Logs a message with the specific Marker at the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               */
              public void notice(final Marker marker, final Message msg) {
                  if (logger.isEnabled(NOTICE, marker, msg, (Throwable) null)) {
                      logger.log(marker, FQCN, NOTICE, msg, null);
                  }
              }
          
              /**
               * Logs a message with the specific Marker at the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void notice(final Marker marker, final Message msg, final Throwable t) {
                  if (logger.isEnabled(NOTICE, marker, msg, t)) {
                      logger.log(marker, FQCN, NOTICE, msg, t);
                  }
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void notice(final Marker marker, final Object message) {
                  if (logger.isEnabled(NOTICE, marker, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(marker, FQCN, NOTICE, msg, null);
                  }
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final Marker marker, final Object message, final Throwable t) {
                  if (logger.isEnabled(NOTICE, marker, message, t)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(marker, FQCN, NOTICE, msg, t);
                  }
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void notice(final Marker marker, final String message) {
                  if (logger.isEnabled(NOTICE, marker, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(marker, FQCN, NOTICE, msg, null);
                  }
              }
          
              /**
               * Logs a message with parameters at the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void notice(final Marker marker, final String message, final Object... params) {
                  if (logger.isEnabled(NOTICE, marker, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message, params);
                      logger.log(marker, FQCN, NOTICE, msg, msg.getThrowable());
                  }
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final Marker marker, final String message, final Throwable t) {
                  if (logger.isEnabled(NOTICE, marker, message, t)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(marker, FQCN, NOTICE, msg, t);
                  }
              }
          
              /**
               * Logs the specified Message at the {@code NOTICE} level.
               * 
               * @param msg the message string to be logged
               */
              public void notice(final Message msg) {
                  if (logger.isEnabled(NOTICE, null, msg, (Throwable) null)) {
                      logger.log(null, FQCN, NOTICE, msg, null);
                  }
              }
          
              /**
               * Logs the specified Message at the {@code NOTICE} level.
               * 
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void notice(final Message msg, final Throwable t) {
                  if (logger.isEnabled(NOTICE, null, msg, t)) {
                      logger.log(null, FQCN, NOTICE, msg, t);
                  }
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param message the message object to log.
               */
              public void notice(final Object message) {
                  if (logger.isEnabled(NOTICE, null, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(null, FQCN, NOTICE, msg, null);
                  }
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final Object message, final Throwable t) {
                  if (logger.isEnabled(NOTICE, null, message, t)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(null, FQCN, NOTICE, msg, t);
                  }
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param message the message object to log.
               */
              public void notice(final String message) {
                  if (logger.isEnabled(NOTICE, null, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(null, FQCN, NOTICE, msg, null);
                  }
              }
          
              /**
               * Logs a message with parameters at the {@code NOTICE} level.
               * 
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void notice(final String message, final Object... params) {
                  if (logger.isEnabled(NOTICE, null, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message, params);
                      logger.log(null, FQCN, NOTICE, msg, msg.getThrowable());
                  }
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final String message, final Throwable t) {
                  if (logger.isEnabled(NOTICE, null, message, t)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(null, FQCN, NOTICE, msg, t);
                  }
              }
          
              /**
               * Logs a message with the specific Marker at the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               */
              public void verbose(final Marker marker, final Message msg) {
                  if (logger.isEnabled(VERBOSE, marker, msg, (Throwable) null)) {
                      logger.log(marker, FQCN, VERBOSE, msg, null);
                  }
              }
          
              /**
               * Logs a message with the specific Marker at the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void verbose(final Marker marker, final Message msg, final Throwable t) {
                  if (logger.isEnabled(VERBOSE, marker, msg, t)) {
                      logger.log(marker, FQCN, VERBOSE, msg, t);
                  }
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void verbose(final Marker marker, final Object message) {
                  if (logger.isEnabled(VERBOSE, marker, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(marker, FQCN, VERBOSE, msg, null);
                  }
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final Marker marker, final Object message, final Throwable t) {
                  if (logger.isEnabled(VERBOSE, marker, message, t)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(marker, FQCN, VERBOSE, msg, t);
                  }
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void verbose(final Marker marker, final String message) {
                  if (logger.isEnabled(VERBOSE, marker, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(marker, FQCN, VERBOSE, msg, null);
                  }
              }
          
              /**
               * Logs a message with parameters at the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void verbose(final Marker marker, final String message, final Object... params) {
                  if (logger.isEnabled(VERBOSE, marker, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message, params);
                      logger.log(marker, FQCN, VERBOSE, msg, msg.getThrowable());
                  }
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final Marker marker, final String message, final Throwable t) {
                  if (logger.isEnabled(VERBOSE, marker, message, t)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(marker, FQCN, VERBOSE, msg, t);
                  }
              }
          
              /**
               * Logs the specified Message at the {@code VERBOSE} level.
               * 
               * @param msg the message string to be logged
               */
              public void verbose(final Message msg) {
                  if (logger.isEnabled(VERBOSE, null, msg, (Throwable) null)) {
                      logger.log(null, FQCN, VERBOSE, msg, null);
                  }
              }
          
              /**
               * Logs the specified Message at the {@code VERBOSE} level.
               * 
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void verbose(final Message msg, final Throwable t) {
                  if (logger.isEnabled(VERBOSE, null, msg, t)) {
                      logger.log(null, FQCN, VERBOSE, msg, t);
                  }
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param message the message object to log.
               */
              public void verbose(final Object message) {
                  if (logger.isEnabled(VERBOSE, null, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(null, FQCN, VERBOSE, msg, null);
                  }
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final Object message, final Throwable t) {
                  if (logger.isEnabled(VERBOSE, null, message, t)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(null, FQCN, VERBOSE, msg, t);
                  }
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param message the message object to log.
               */
              public void verbose(final String message) {
                  if (logger.isEnabled(VERBOSE, null, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(null, FQCN, VERBOSE, msg, null);
                  }
              }
          
              /**
               * Logs a message with parameters at the {@code VERBOSE} level.
               * 
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void verbose(final String message, final Object... params) {
                  if (logger.isEnabled(VERBOSE, null, message, (Throwable) null)) {
                      final Message msg = logger.getMessageFactory().newMessage(message, params);
                      logger.log(null, FQCN, VERBOSE, msg, msg.getThrowable());
                  }
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of
               * the {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final String message, final Throwable t) {
                  if (logger.isEnabled(VERBOSE, null, message, t)) {
                      final Message msg = logger.getMessageFactory().newMessage(message);
                      logger.log(null, FQCN, VERBOSE, msg, t);
                  }
              }
          }
          
          Show
          Remko Popma added a comment - I've updated the attached Generate.java tool to keep track of its own FQCN and always call the log(Marker, String, Level, Message, Throwable) method. That should solve the problem even when using %C or other location patterns in the layout. Example code below for an Extended logger is generated with the command java org.apache.logging.log4j.util.Generate$ExtendedLogger com.mycomp.ExtLogger DIAG=350 NOTICE=450 VERBOSE=550 to generate a wrapper that only provides convenience methods for the specified custom levels (and hides the convenience methods for the built-in levels), use the CustomLogger tool: java org.apache.logging.log4j.util.Generate$CustomLogger com.mycomp.MyLogger DEFCON1=350 DEFCON2=450 DEFCON3=550 Sample generated code: package com.mycomp; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.MessageFactory; import org.apache.logging.log4j.spi.AbstractLogger; import org.apache.logging.log4j.spi.AbstractLoggerWrapper; /** * Extended Logger interface with convenience methods for * the DIAG, NOTICE and VERBOSE custom log levels. */ public final class ExtLogger extends AbstractLoggerWrapper { private static final long serialVersionUID = 26876940739430L; private final AbstractLoggerWrapper logger; private static final String FQCN = ExtLogger.class.getName(); private static final Level DIAG = Level.forName( "DIAG" , 350); private static final Level NOTICE = Level.forName( "NOTICE" , 450); private static final Level VERBOSE = Level.forName( "VERBOSE" , 550); private ExtLogger( final Logger logger) { super ((AbstractLogger) logger, logger.getName(), logger.getMessageFactory()); this .logger = this ; } /** * Returns a custom Logger with the name of the calling class. * * @ return The custom Logger for the calling class. */ public static ExtLogger create() { final Logger wrapped = LogManager.getLogger(); return new ExtLogger(wrapped); } /** * Returns a custom Logger using the fully qualified name of the Class as * the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. * If null it will default to the calling class. * @ return The custom Logger. */ public static ExtLogger create( final Class <?> loggerName) { final Logger wrapped = LogManager.getLogger(loggerName); return new ExtLogger(wrapped); } /** * Returns a custom Logger using the fully qualified name of the Class as * the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. * If null it will default to the calling class. * @param messageFactory The message factory is used only when creating a * logger, subsequent use does not change the logger but will log * a warning if mismatched. * @ return The custom Logger. */ public static ExtLogger create( final Class <?> loggerName, final MessageFactory factory) { final Logger wrapped = LogManager.getLogger(loggerName, factory); return new ExtLogger(wrapped); } /** * Returns a custom Logger using the fully qualified class name of the value * as the Logger name. * * @param value The value whose class name should be used as the Logger * name. If null the name of the calling class will be used as * the logger name. * @ return The custom Logger. */ public static ExtLogger create( final Object value) { final Logger wrapped = LogManager.getLogger(value); return new ExtLogger(wrapped); } /** * Returns a custom Logger using the fully qualified class name of the value * as the Logger name. * * @param value The value whose class name should be used as the Logger * name. If null the name of the calling class will be used as * the logger name. * @param messageFactory The message factory is used only when creating a * logger, subsequent use does not change the logger but will log * a warning if mismatched. * @ return The custom Logger. */ public static ExtLogger create( final Object value, final MessageFactory factory) { final Logger wrapped = LogManager.getLogger(value, factory); return new ExtLogger(wrapped); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will * be used. * @ return The custom Logger. */ public static ExtLogger create( final String name) { final Logger wrapped = LogManager.getLogger(name); return new ExtLogger(wrapped); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will * be used. * @param messageFactory The message factory is used only when creating a * logger, subsequent use does not change the logger but will log * a warning if mismatched. * @ return The custom Logger. */ public static ExtLogger create( final String name, final MessageFactory factory) { final Logger wrapped = LogManager.getLogger(name, factory); return new ExtLogger(wrapped); } /** * Logs a message with the specific Marker at the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged */ public void diag( final Marker marker, final Message msg) { if (logger.isEnabled(DIAG, marker, msg, (Throwable) null )) { logger.log(marker, FQCN, DIAG, msg, null ); } } /** * Logs a message with the specific Marker at the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged * @param t A Throwable or null . */ public void diag( final Marker marker, final Message msg, final Throwable t) { if (logger.isEnabled(DIAG, marker, msg, t)) { logger.log(marker, FQCN, DIAG, msg, t); } } /** * Logs a message object with the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void diag( final Marker marker, final Object message) { if (logger.isEnabled(DIAG, marker, message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log(marker, FQCN, DIAG, msg, null ); } } /** * Logs a message at the {@code DIAG} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final Marker marker, final Object message, final Throwable t) { if (logger.isEnabled(DIAG, marker, message, t)) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log(marker, FQCN, DIAG, msg, t); } } /** * Logs a message object with the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void diag( final Marker marker, final String message) { if (logger.isEnabled(DIAG, marker, message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log(marker, FQCN, DIAG, msg, null ); } } /** * Logs a message with parameters at the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void diag( final Marker marker, final String message, final Object ... params) { if (logger.isEnabled(DIAG, marker, message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message, params); logger.log(marker, FQCN, DIAG, msg, msg.getThrowable()); } } /** * Logs a message at the {@code DIAG} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final Marker marker, final String message, final Throwable t) { if (logger.isEnabled(DIAG, marker, message, t)) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log(marker, FQCN, DIAG, msg, t); } } /** * Logs the specified Message at the {@code DIAG} level. * * @param msg the message string to be logged */ public void diag( final Message msg) { if (logger.isEnabled(DIAG, null , msg, (Throwable) null )) { logger.log( null , FQCN, DIAG, msg, null ); } } /** * Logs the specified Message at the {@code DIAG} level. * * @param msg the message string to be logged * @param t A Throwable or null . */ public void diag( final Message msg, final Throwable t) { if (logger.isEnabled(DIAG, null , msg, t)) { logger.log( null , FQCN, DIAG, msg, t); } } /** * Logs a message object with the {@code DIAG} level. * * @param message the message object to log. */ public void diag( final Object message) { if (logger.isEnabled(DIAG, null , message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log( null , FQCN, DIAG, msg, null ); } } /** * Logs a message at the {@code DIAG} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final Object message, final Throwable t) { if (logger.isEnabled(DIAG, null , message, t)) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log( null , FQCN, DIAG, msg, t); } } /** * Logs a message object with the {@code DIAG} level. * * @param message the message object to log. */ public void diag( final String message) { if (logger.isEnabled(DIAG, null , message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log( null , FQCN, DIAG, msg, null ); } } /** * Logs a message with parameters at the {@code DIAG} level. * * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void diag( final String message, final Object ... params) { if (logger.isEnabled(DIAG, null , message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message, params); logger.log( null , FQCN, DIAG, msg, msg.getThrowable()); } } /** * Logs a message at the {@code DIAG} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final String message, final Throwable t) { if (logger.isEnabled(DIAG, null , message, t)) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log( null , FQCN, DIAG, msg, t); } } /** * Logs a message with the specific Marker at the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged */ public void notice( final Marker marker, final Message msg) { if (logger.isEnabled(NOTICE, marker, msg, (Throwable) null )) { logger.log(marker, FQCN, NOTICE, msg, null ); } } /** * Logs a message with the specific Marker at the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged * @param t A Throwable or null . */ public void notice( final Marker marker, final Message msg, final Throwable t) { if (logger.isEnabled(NOTICE, marker, msg, t)) { logger.log(marker, FQCN, NOTICE, msg, t); } } /** * Logs a message object with the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void notice( final Marker marker, final Object message) { if (logger.isEnabled(NOTICE, marker, message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log(marker, FQCN, NOTICE, msg, null ); } } /** * Logs a message at the {@code NOTICE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final Marker marker, final Object message, final Throwable t) { if (logger.isEnabled(NOTICE, marker, message, t)) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log(marker, FQCN, NOTICE, msg, t); } } /** * Logs a message object with the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void notice( final Marker marker, final String message) { if (logger.isEnabled(NOTICE, marker, message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log(marker, FQCN, NOTICE, msg, null ); } } /** * Logs a message with parameters at the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void notice( final Marker marker, final String message, final Object ... params) { if (logger.isEnabled(NOTICE, marker, message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message, params); logger.log(marker, FQCN, NOTICE, msg, msg.getThrowable()); } } /** * Logs a message at the {@code NOTICE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final Marker marker, final String message, final Throwable t) { if (logger.isEnabled(NOTICE, marker, message, t)) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log(marker, FQCN, NOTICE, msg, t); } } /** * Logs the specified Message at the {@code NOTICE} level. * * @param msg the message string to be logged */ public void notice( final Message msg) { if (logger.isEnabled(NOTICE, null , msg, (Throwable) null )) { logger.log( null , FQCN, NOTICE, msg, null ); } } /** * Logs the specified Message at the {@code NOTICE} level. * * @param msg the message string to be logged * @param t A Throwable or null . */ public void notice( final Message msg, final Throwable t) { if (logger.isEnabled(NOTICE, null , msg, t)) { logger.log( null , FQCN, NOTICE, msg, t); } } /** * Logs a message object with the {@code NOTICE} level. * * @param message the message object to log. */ public void notice( final Object message) { if (logger.isEnabled(NOTICE, null , message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log( null , FQCN, NOTICE, msg, null ); } } /** * Logs a message at the {@code NOTICE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final Object message, final Throwable t) { if (logger.isEnabled(NOTICE, null , message, t)) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log( null , FQCN, NOTICE, msg, t); } } /** * Logs a message object with the {@code NOTICE} level. * * @param message the message object to log. */ public void notice( final String message) { if (logger.isEnabled(NOTICE, null , message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log( null , FQCN, NOTICE, msg, null ); } } /** * Logs a message with parameters at the {@code NOTICE} level. * * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void notice( final String message, final Object ... params) { if (logger.isEnabled(NOTICE, null , message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message, params); logger.log( null , FQCN, NOTICE, msg, msg.getThrowable()); } } /** * Logs a message at the {@code NOTICE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final String message, final Throwable t) { if (logger.isEnabled(NOTICE, null , message, t)) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log( null , FQCN, NOTICE, msg, t); } } /** * Logs a message with the specific Marker at the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged */ public void verbose( final Marker marker, final Message msg) { if (logger.isEnabled(VERBOSE, marker, msg, (Throwable) null )) { logger.log(marker, FQCN, VERBOSE, msg, null ); } } /** * Logs a message with the specific Marker at the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged * @param t A Throwable or null . */ public void verbose( final Marker marker, final Message msg, final Throwable t) { if (logger.isEnabled(VERBOSE, marker, msg, t)) { logger.log(marker, FQCN, VERBOSE, msg, t); } } /** * Logs a message object with the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void verbose( final Marker marker, final Object message) { if (logger.isEnabled(VERBOSE, marker, message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log(marker, FQCN, VERBOSE, msg, null ); } } /** * Logs a message at the {@code VERBOSE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final Marker marker, final Object message, final Throwable t) { if (logger.isEnabled(VERBOSE, marker, message, t)) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log(marker, FQCN, VERBOSE, msg, t); } } /** * Logs a message object with the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void verbose( final Marker marker, final String message) { if (logger.isEnabled(VERBOSE, marker, message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log(marker, FQCN, VERBOSE, msg, null ); } } /** * Logs a message with parameters at the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void verbose( final Marker marker, final String message, final Object ... params) { if (logger.isEnabled(VERBOSE, marker, message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message, params); logger.log(marker, FQCN, VERBOSE, msg, msg.getThrowable()); } } /** * Logs a message at the {@code VERBOSE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final Marker marker, final String message, final Throwable t) { if (logger.isEnabled(VERBOSE, marker, message, t)) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log(marker, FQCN, VERBOSE, msg, t); } } /** * Logs the specified Message at the {@code VERBOSE} level. * * @param msg the message string to be logged */ public void verbose( final Message msg) { if (logger.isEnabled(VERBOSE, null , msg, (Throwable) null )) { logger.log( null , FQCN, VERBOSE, msg, null ); } } /** * Logs the specified Message at the {@code VERBOSE} level. * * @param msg the message string to be logged * @param t A Throwable or null . */ public void verbose( final Message msg, final Throwable t) { if (logger.isEnabled(VERBOSE, null , msg, t)) { logger.log( null , FQCN, VERBOSE, msg, t); } } /** * Logs a message object with the {@code VERBOSE} level. * * @param message the message object to log. */ public void verbose( final Object message) { if (logger.isEnabled(VERBOSE, null , message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log( null , FQCN, VERBOSE, msg, null ); } } /** * Logs a message at the {@code VERBOSE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final Object message, final Throwable t) { if (logger.isEnabled(VERBOSE, null , message, t)) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log( null , FQCN, VERBOSE, msg, t); } } /** * Logs a message object with the {@code VERBOSE} level. * * @param message the message object to log. */ public void verbose( final String message) { if (logger.isEnabled(VERBOSE, null , message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log( null , FQCN, VERBOSE, msg, null ); } } /** * Logs a message with parameters at the {@code VERBOSE} level. * * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void verbose( final String message, final Object ... params) { if (logger.isEnabled(VERBOSE, null , message, (Throwable) null )) { final Message msg = logger.getMessageFactory().newMessage(message, params); logger.log( null , FQCN, VERBOSE, msg, msg.getThrowable()); } } /** * Logs a message at the {@code VERBOSE} level including the stack trace of * the {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final String message, final Throwable t) { if (logger.isEnabled(VERBOSE, null , message, t)) { final Message msg = logger.getMessageFactory().newMessage(message); logger.log( null , FQCN, VERBOSE, msg, t); } } }
          Hide
          vibin added a comment -

          Thanks,I tried test again with latest generated code, it worked.

          Show
          vibin added a comment - Thanks,I tried test again with latest generated code, it worked.
          Hide
          Gary Gregory added a comment -

          Remko Popma Why don't you commit the generator (needs a better name than "Generate") in core's test code base. At least that will give a place to look at it, play with it and make sure it always compiles and is part of any refactorings.

          Show
          Gary Gregory added a comment - Remko Popma Why don't you commit the generator (needs a better name than "Generate") in core's test code base. At least that will give a place to look at it, play with it and make sure it always compiles and is part of any refactorings.
          Hide
          Bruce Brouwer added a comment -

          I've been wondering about the need here to cast to AbstractLogger. This ties us to the implementation of Loggers originally conceived in core. What if we had an interface that has the .log(...) methods defined on AbstractLogger that take the FQCN. Perhaps we could call this interface ExtensibleLogger or something like that. I would feel better about casting to an interface that any logging implementation could implement.

          I'm kind of looking at this for LOG4J2-547 which I am working on.

          Show
          Bruce Brouwer added a comment - I've been wondering about the need here to cast to AbstractLogger. This ties us to the implementation of Loggers originally conceived in core. What if we had an interface that has the .log(...) methods defined on AbstractLogger that take the FQCN. Perhaps we could call this interface ExtensibleLogger or something like that. I would feel better about casting to an interface that any logging implementation could implement. I'm kind of looking at this for LOG4J2-547 which I am working on.
          Hide
          Ralph Goers added a comment - - edited

          Logger is the interface end users can code to. It should only contain methods they should call. If you want to create an interface and add it to the spi directory I guess I don't have a problem with it. But if it just declares all the additional methods in AbstractLogger than I'm not sure I see the point.

          I am not sure where it is but there is at least one other place that is casting to AbstractLogger.

          Show
          Ralph Goers added a comment - - edited Logger is the interface end users can code to. It should only contain methods they should call. If you want to create an interface and add it to the spi directory I guess I don't have a problem with it. But if it just declares all the additional methods in AbstractLogger than I'm not sure I see the point. I am not sure where it is but there is at least one other place that is casting to AbstractLogger.
          Hide
          Bruce Brouwer added a comment -

          Definitely it would go in spi. It would allow flexibility in implementations that might not directly extend AbstractLogger and I think it might help me out with LOG4J2-547 where my logger needs to extend Writer and OutputStream. I could extend Writer and still implement ExtensibleLogger.

          Show
          Bruce Brouwer added a comment - Definitely it would go in spi. It would allow flexibility in implementations that might not directly extend AbstractLogger and I think it might help me out with LOG4J2-547 where my logger needs to extend Writer and OutputStream. I could extend Writer and still implement ExtensibleLogger.
          Hide
          Bruce Brouwer added a comment - - edited

          With my work in LOG4J2-562, this example would turn into something like this:

          package com.bhb.log4j;
          
          import java.util.concurrent.ConcurrentHashMap;
          import java.util.concurrent.ConcurrentMap;
          
          import org.apache.logging.log4j.Level;
          import org.apache.logging.log4j.LogManager;
          import org.apache.logging.log4j.Logger;
          import org.apache.logging.log4j.Marker;
          import org.apache.logging.log4j.message.Message;
          import org.apache.logging.log4j.message.MessageFactory;
          import org.apache.logging.log4j.simple.SimpleLogger;
          import org.apache.logging.log4j.spi.AbstractLogger;
          import org.apache.logging.log4j.spi.LoggerExtension;
          
          public final class ExtLogger extends AbstractLogger {
              private static final long serialVersionUID = 26876940739430L;
              private static final ConcurrentMap<String, ExtLogger> loggers = new ConcurrentHashMap<String, ExtLogger>();
          
              private final LoggerExtension logger;
          
              private static final String FQCN = ExtLogger.class.getName();
              private static final Level DIAG = Level.forName("DIAG", 350);
              private static final Level NOTICE = Level.forName("NOTICE", 450);
              private static final Level VERBOSE = Level.forName("VERBOSE", 550);
          
              private ExtLogger(LoggerExtension logger) {
                  super(logger.getName());
                  this.logger = logger;
              }
          
              /**
               * Returns a custom Logger with the name of the calling class.
               * 
               * @return The custom Logger for the calling class.
               */
              public static ExtLogger getLogger() {
                  return getLogger(getClassName(2));
              }
          
              /**
               * Returns a custom Logger using the fully qualified name of the Class as the Logger name.
               * 
               * @param loggerName The Class whose name should be used as the Logger name. If null it will
               *            default to the calling class.
               * @return The custom Logger.
               */
              public static ExtLogger getLogger(final Class<?> clazz) {
                  return getLogger(clazz != null ? clazz.getName() : getClassName(2));
              }
          
              /**
               * Returns a custom Logger using the fully qualified name of the Class as the Logger name.
               * 
               * @param loggerName The Class whose name should be used as the Logger name. If null it will
               *            default to the calling class.
               * @param messageFactory The message factory is used only when creating a logger, subsequent use
               *            does not change the logger but will log a warning if mismatched.
               * @return The custom Logger.
               */
              public static ExtLogger getLogger(final Class<?> clazz, final MessageFactory factory) {
                  return getLogger(clazz != null ? clazz.getName() : getClassName(2), factory);
              }
          
              /**
               * Returns a custom Logger using the fully qualified class name of the value as the Logger name.
               * 
               * @param value The value whose class name should be used as the Logger name. If null the name
               *            of the calling class will be used as the logger name.
               * @return The custom Logger.
               */
              public static ExtLogger getLogger(final Object value) {
                  return getLogger(value != null ? value.getClass().getName() : getClassName(2));
              }
          
              /**
               * Returns a custom Logger using the fully qualified class name of the value as the Logger name.
               * 
               * @param value The value whose class name should be used as the Logger name. If null the name
               *            of the calling class will be used as the logger name.
               * @param messageFactory The message factory is used only when creating a logger, subsequent use
               *            does not change the logger but will log a warning if mismatched.
               * @return The custom Logger.
               */
              public static ExtLogger getLogger(final Object value, final MessageFactory factory) {
                  return getLogger(value != null ? value.getClass().getName() : getClassName(2), factory);
              }
          
              /**
               * Returns a custom Logger with the specified name.
               * 
               * @param name The logger name. If null the name of the calling class will be used.
               * @return The custom Logger.
               */
              public static ExtLogger getLogger(final String name) {
                  return getLogger(name != null ? name : getClassName(2), null);
              }
          
              /**
               * Returns a custom Logger with the specified name.
               * 
               * @param name The logger name. If null the name of the calling class will be used.
               * @param messageFactory The message factory is used only when creating a logger, subsequent use
               *            does not change the logger but will log a warning if mismatched.
               * @return The custom Logger.
               */
              public static ExtLogger getLogger(final String name, final MessageFactory factory) {
                  final String actualName = name != null ? name : getClassName(2);
                  if (loggers.containsKey(actualName)) {
                      return loggers.get(actualName);
                  }
                  // Since both ExtLogger and AbstractLogger methods will be entry points, both are listed for FQCN to make caller location work
                  final ExtLogger result = new ExtLogger(LogManager.getContext().extendLogger(actualName, factory, ExtLogger.class, AbstractLogger.class));
                  final ExtLogger existing = loggers.putIfAbsent(actualName, result);
                  return existing == null ? result : existing;
              }
          
              /**
               * Gets the class name of the caller in the current stack at the given {@code depth}.
               * 
               * @param depth a 0-based index in the current stack.
               * @return a class name
               */
              private static String getClassName(final int depth) {
                  return new Throwable().getStackTrace()[depth].getClassName();
              }
          
              /**
               * Logs a message with the specific Marker at the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               */
              public void diag(final Marker marker, final Message msg) {
                  logger.log(DIAG, marker, msg, null);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void diag(final Marker marker, final Message msg, final Throwable t) {
                  logger.log(DIAG, marker, msg, t);
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void diag(final Marker marker, final Object message) {
                  logger.log(DIAG, marker, message, null);
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final Marker marker, final Object message, final Throwable t) {
                  logger.log(DIAG, marker, message, t);
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void diag(final Marker marker, final String message) {
                  logger.log(DIAG, marker, message, (Throwable) null);
              }
          
              /**
               * Logs a message with parameters at the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void diag(final Marker marker, final String message, final Object... params) {
                  logger.log(DIAG, marker, message, params);
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final Marker marker, final String message, final Throwable t) {
                  logger.log(DIAG, marker, message, t);
              }
          
              /**
               * Logs the specified Message at the {@code DIAG} level.
               * 
               * @param msg the message string to be logged
               */
              public void diag(final Message msg) {
                  logger.log(DIAG, null, msg, null);
              }
          
              /**
               * Logs the specified Message at the {@code DIAG} level.
               * 
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void diag(final Message msg, final Throwable t) {
                  logger.log(DIAG, null, msg, t);
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param message the message object to log.
               */
              public void diag(final Object message) {
                  logger.log(DIAG, null, message, null);
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final Object message, final Throwable t) {
                  logger.log(DIAG, null, message, t);
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param message the message object to log.
               */
              public void diag(final String message) {
                  logger.log(DIAG, null, message, (Throwable) null);
              }
          
              /**
               * Logs a message with parameters at the {@code DIAG} level.
               * 
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void diag(final String message, final Object... params) {
                  logger.log(DIAG, null, message, params);
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final String message, final Throwable t) {
                  logger.log(DIAG, null, message, t);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               */
              public void notice(final Marker marker, final Message msg) {
                  logger.log(NOTICE, marker, msg, null);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void notice(final Marker marker, final Message msg, final Throwable t) {
                  logger.log(NOTICE, marker, msg, t);
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void notice(final Marker marker, final Object message) {
                  logger.log(NOTICE, marker, message, null);
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final Marker marker, final Object message, final Throwable t) {
                  logger.log(NOTICE, marker, message, t);
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void notice(final Marker marker, final String message) {
                  logger.log(NOTICE, marker, message, (Throwable) null);
              }
          
              /**
               * Logs a message with parameters at the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void notice(final Marker marker, final String message, final Object... params) {
                  logger.log(NOTICE, marker, message, params);
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final Marker marker, final String message, final Throwable t) {
                  logger.log(NOTICE, marker, message, t);
              }
          
              /**
               * Logs the specified Message at the {@code NOTICE} level.
               * 
               * @param msg the message string to be logged
               */
              public void notice(final Message msg) {
                  logger.log(NOTICE, null, msg, null);
              }
          
              /**
               * Logs the specified Message at the {@code NOTICE} level.
               * 
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void notice(final Message msg, final Throwable t) {
                  logger.log(NOTICE, null, msg, t);
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param message the message object to log.
               */
              public void notice(final Object message) {
                  logger.log(NOTICE, null, message, null);
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final Object message, final Throwable t) {
                  logger.log(NOTICE, null, message, t);
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param message the message object to log.
               */
              public void notice(final String message) {
                  logger.log(NOTICE, null, message, (Throwable) null);
              }
          
              /**
               * Logs a message with parameters at the {@code NOTICE} level.
               * 
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void notice(final String message, final Object... params) {
                  logger.log(NOTICE, null, message, params);
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final String message, final Throwable t) {
                  logger.log(NOTICE, null, message, t);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               */
              public void verbose(final Marker marker, final Message msg) {
                  logger.log(VERBOSE, marker, msg, null);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void verbose(final Marker marker, final Message msg, final Throwable t) {
                  logger.log(VERBOSE, marker, msg, t);
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void verbose(final Marker marker, final Object message) {
                  logger.log(VERBOSE, marker, message, null);
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of the
               * {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final Marker marker, final Object message, final Throwable t) {
                  logger.log(VERBOSE, marker, message, t);
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void verbose(final Marker marker, final String message) {
                  logger.log(VERBOSE, marker, message, (Throwable) null);
              }
          
              /**
               * Logs a message with parameters at the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void verbose(final Marker marker, final String message, final Object... params) {
                  logger.log(VERBOSE, marker, message, params);
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of the
               * {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final Marker marker, final String message, final Throwable t) {
                  logger.log(VERBOSE, marker, message, t);
              }
          
              /**
               * Logs the specified Message at the {@code VERBOSE} level.
               * 
               * @param msg the message string to be logged
               */
              public void verbose(final Message msg) {
                  logger.log(VERBOSE, null, msg, null);
              }
          
              /**
               * Logs the specified Message at the {@code VERBOSE} level.
               * 
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void verbose(final Message msg, final Throwable t) {
                  logger.log(VERBOSE, null, msg, t);
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param message the message object to log.
               */
              public void verbose(final Object message) {
                  logger.log(VERBOSE, null, message, null);
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of the
               * {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final Object message, final Throwable t) {
                  logger.log(VERBOSE, null, message, t);
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param message the message object to log.
               */
              public void verbose(final String message) {
                  logger.log(VERBOSE, null, message, (Throwable) null);
              }
          
              /**
               * Logs a message with parameters at the {@code VERBOSE} level.
               * 
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void verbose(final String message, final Object... params) {
                  logger.log(VERBOSE, null, message, params);
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of the
               * {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final String message, final Throwable t) {
                  logger.log(VERBOSE, null, message, t);
              }
          }
          
          Show
          Bruce Brouwer added a comment - - edited With my work in LOG4J2-562 , this example would turn into something like this: package com.bhb.log4j; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.MessageFactory; import org.apache.logging.log4j.simple.SimpleLogger; import org.apache.logging.log4j.spi.AbstractLogger; import org.apache.logging.log4j.spi.LoggerExtension; public final class ExtLogger extends AbstractLogger { private static final long serialVersionUID = 26876940739430L; private static final ConcurrentMap< String , ExtLogger> loggers = new ConcurrentHashMap< String , ExtLogger>(); private final LoggerExtension logger; private static final String FQCN = ExtLogger.class.getName(); private static final Level DIAG = Level.forName( "DIAG" , 350); private static final Level NOTICE = Level.forName( "NOTICE" , 450); private static final Level VERBOSE = Level.forName( "VERBOSE" , 550); private ExtLogger(LoggerExtension logger) { super (logger.getName()); this .logger = logger; } /** * Returns a custom Logger with the name of the calling class. * * @ return The custom Logger for the calling class. */ public static ExtLogger getLogger() { return getLogger(getClassName(2)); } /** * Returns a custom Logger using the fully qualified name of the Class as the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. If null it will * default to the calling class. * @ return The custom Logger. */ public static ExtLogger getLogger( final Class <?> clazz) { return getLogger(clazz != null ? clazz.getName() : getClassName(2)); } /** * Returns a custom Logger using the fully qualified name of the Class as the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. If null it will * default to the calling class. * @param messageFactory The message factory is used only when creating a logger, subsequent use * does not change the logger but will log a warning if mismatched. * @ return The custom Logger. */ public static ExtLogger getLogger( final Class <?> clazz, final MessageFactory factory) { return getLogger(clazz != null ? clazz.getName() : getClassName(2), factory); } /** * Returns a custom Logger using the fully qualified class name of the value as the Logger name. * * @param value The value whose class name should be used as the Logger name. If null the name * of the calling class will be used as the logger name. * @ return The custom Logger. */ public static ExtLogger getLogger( final Object value) { return getLogger(value != null ? value.getClass().getName() : getClassName(2)); } /** * Returns a custom Logger using the fully qualified class name of the value as the Logger name. * * @param value The value whose class name should be used as the Logger name. If null the name * of the calling class will be used as the logger name. * @param messageFactory The message factory is used only when creating a logger, subsequent use * does not change the logger but will log a warning if mismatched. * @ return The custom Logger. */ public static ExtLogger getLogger( final Object value, final MessageFactory factory) { return getLogger(value != null ? value.getClass().getName() : getClassName(2), factory); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will be used. * @ return The custom Logger. */ public static ExtLogger getLogger( final String name) { return getLogger(name != null ? name : getClassName(2), null ); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will be used. * @param messageFactory The message factory is used only when creating a logger, subsequent use * does not change the logger but will log a warning if mismatched. * @ return The custom Logger. */ public static ExtLogger getLogger( final String name, final MessageFactory factory) { final String actualName = name != null ? name : getClassName(2); if (loggers.containsKey(actualName)) { return loggers.get(actualName); } // Since both ExtLogger and AbstractLogger methods will be entry points, both are listed for FQCN to make caller location work final ExtLogger result = new ExtLogger(LogManager.getContext().extendLogger(actualName, factory, ExtLogger.class, AbstractLogger.class)); final ExtLogger existing = loggers.putIfAbsent(actualName, result); return existing == null ? result : existing; } /** * Gets the class name of the caller in the current stack at the given {@code depth}. * * @param depth a 0-based index in the current stack. * @ return a class name */ private static String getClassName( final int depth) { return new Throwable().getStackTrace()[depth].getClassName(); } /** * Logs a message with the specific Marker at the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged */ public void diag( final Marker marker, final Message msg) { logger.log(DIAG, marker, msg, null ); } /** * Logs a message with the specific Marker at the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged * @param t A Throwable or null . */ public void diag( final Marker marker, final Message msg, final Throwable t) { logger.log(DIAG, marker, msg, t); } /** * Logs a message object with the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void diag( final Marker marker, final Object message) { logger.log(DIAG, marker, message, null ); } /** * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final Marker marker, final Object message, final Throwable t) { logger.log(DIAG, marker, message, t); } /** * Logs a message object with the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void diag( final Marker marker, final String message) { logger.log(DIAG, marker, message, (Throwable) null ); } /** * Logs a message with parameters at the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void diag( final Marker marker, final String message, final Object ... params) { logger.log(DIAG, marker, message, params); } /** * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final Marker marker, final String message, final Throwable t) { logger.log(DIAG, marker, message, t); } /** * Logs the specified Message at the {@code DIAG} level. * * @param msg the message string to be logged */ public void diag( final Message msg) { logger.log(DIAG, null , msg, null ); } /** * Logs the specified Message at the {@code DIAG} level. * * @param msg the message string to be logged * @param t A Throwable or null . */ public void diag( final Message msg, final Throwable t) { logger.log(DIAG, null , msg, t); } /** * Logs a message object with the {@code DIAG} level. * * @param message the message object to log. */ public void diag( final Object message) { logger.log(DIAG, null , message, null ); } /** * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final Object message, final Throwable t) { logger.log(DIAG, null , message, t); } /** * Logs a message object with the {@code DIAG} level. * * @param message the message object to log. */ public void diag( final String message) { logger.log(DIAG, null , message, (Throwable) null ); } /** * Logs a message with parameters at the {@code DIAG} level. * * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void diag( final String message, final Object ... params) { logger.log(DIAG, null , message, params); } /** * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final String message, final Throwable t) { logger.log(DIAG, null , message, t); } /** * Logs a message with the specific Marker at the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged */ public void notice( final Marker marker, final Message msg) { logger.log(NOTICE, marker, msg, null ); } /** * Logs a message with the specific Marker at the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged * @param t A Throwable or null . */ public void notice( final Marker marker, final Message msg, final Throwable t) { logger.log(NOTICE, marker, msg, t); } /** * Logs a message object with the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void notice( final Marker marker, final Object message) { logger.log(NOTICE, marker, message, null ); } /** * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final Marker marker, final Object message, final Throwable t) { logger.log(NOTICE, marker, message, t); } /** * Logs a message object with the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void notice( final Marker marker, final String message) { logger.log(NOTICE, marker, message, (Throwable) null ); } /** * Logs a message with parameters at the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void notice( final Marker marker, final String message, final Object ... params) { logger.log(NOTICE, marker, message, params); } /** * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final Marker marker, final String message, final Throwable t) { logger.log(NOTICE, marker, message, t); } /** * Logs the specified Message at the {@code NOTICE} level. * * @param msg the message string to be logged */ public void notice( final Message msg) { logger.log(NOTICE, null , msg, null ); } /** * Logs the specified Message at the {@code NOTICE} level. * * @param msg the message string to be logged * @param t A Throwable or null . */ public void notice( final Message msg, final Throwable t) { logger.log(NOTICE, null , msg, t); } /** * Logs a message object with the {@code NOTICE} level. * * @param message the message object to log. */ public void notice( final Object message) { logger.log(NOTICE, null , message, null ); } /** * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final Object message, final Throwable t) { logger.log(NOTICE, null , message, t); } /** * Logs a message object with the {@code NOTICE} level. * * @param message the message object to log. */ public void notice( final String message) { logger.log(NOTICE, null , message, (Throwable) null ); } /** * Logs a message with parameters at the {@code NOTICE} level. * * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void notice( final String message, final Object ... params) { logger.log(NOTICE, null , message, params); } /** * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final String message, final Throwable t) { logger.log(NOTICE, null , message, t); } /** * Logs a message with the specific Marker at the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged */ public void verbose( final Marker marker, final Message msg) { logger.log(VERBOSE, marker, msg, null ); } /** * Logs a message with the specific Marker at the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged * @param t A Throwable or null . */ public void verbose( final Marker marker, final Message msg, final Throwable t) { logger.log(VERBOSE, marker, msg, t); } /** * Logs a message object with the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void verbose( final Marker marker, final Object message) { logger.log(VERBOSE, marker, message, null ); } /** * Logs a message at the {@code VERBOSE} level including the stack trace of the * {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final Marker marker, final Object message, final Throwable t) { logger.log(VERBOSE, marker, message, t); } /** * Logs a message object with the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void verbose( final Marker marker, final String message) { logger.log(VERBOSE, marker, message, (Throwable) null ); } /** * Logs a message with parameters at the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void verbose( final Marker marker, final String message, final Object ... params) { logger.log(VERBOSE, marker, message, params); } /** * Logs a message at the {@code VERBOSE} level including the stack trace of the * {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final Marker marker, final String message, final Throwable t) { logger.log(VERBOSE, marker, message, t); } /** * Logs the specified Message at the {@code VERBOSE} level. * * @param msg the message string to be logged */ public void verbose( final Message msg) { logger.log(VERBOSE, null , msg, null ); } /** * Logs the specified Message at the {@code VERBOSE} level. * * @param msg the message string to be logged * @param t A Throwable or null . */ public void verbose( final Message msg, final Throwable t) { logger.log(VERBOSE, null , msg, t); } /** * Logs a message object with the {@code VERBOSE} level. * * @param message the message object to log. */ public void verbose( final Object message) { logger.log(VERBOSE, null , message, null ); } /** * Logs a message at the {@code VERBOSE} level including the stack trace of the * {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final Object message, final Throwable t) { logger.log(VERBOSE, null , message, t); } /** * Logs a message object with the {@code VERBOSE} level. * * @param message the message object to log. */ public void verbose( final String message) { logger.log(VERBOSE, null , message, (Throwable) null ); } /** * Logs a message with parameters at the {@code VERBOSE} level. * * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void verbose( final String message, final Object ... params) { logger.log(VERBOSE, null , message, params); } /** * Logs a message at the {@code VERBOSE} level including the stack trace of the * {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final String message, final Throwable t) { logger.log(VERBOSE, null , message, t); } }
          Hide
          Remko Popma added a comment -

          Bruce, it looks like the FQCN is declared, but never used in your example ExtLogger. This means that the FQCN of AbstractLogger will be used and the caller location in the log file will be listed as ExtLogger (because ExtLogger calls a method in AbstractLogger) but we want to list MyApp (the class calling ExtLogger) - this is basically the issue vibin reported above... Note that I've only looked at the code, not tried to run it.

          Show
          Remko Popma added a comment - Bruce, it looks like the FQCN is declared, but never used in your example ExtLogger. This means that the FQCN of AbstractLogger will be used and the caller location in the log file will be listed as ExtLogger (because ExtLogger calls a method in AbstractLogger) but we want to list MyApp (the class calling ExtLogger) - this is basically the issue vibin reported above... Note that I've only looked at the code, not tried to run it.
          Hide
          Bruce Brouwer added a comment -

          Sorry, I wasn't clear in what my code represents. I neglected to remove FQCN from the code I posted as in the last getLogger method, you'll see that my example is passing in the ExtLogger.class and AbstractLogger.class. Basically, what would have been two separate FQCN. I don't particularly need to pass in actual classes. They could be FQCN strings.

          Also, this is is just code that demonstrates where we could take it if we moved forward with what I am suggesting in LOG4J2-562 and influenced by the discussion in LOG4J2-555. The code as I provided does not actually work currently with the trunk on log4j2.

          It is important to note that I'm giving 2 FQCNs. Because some of the implemented methods are on AbstractLogger and others on ExtLogger, we need to tell the extended logger about both classes. I imagine we would want to allow any number of FQCNs if we pursued this approach.

          Show
          Bruce Brouwer added a comment - Sorry, I wasn't clear in what my code represents. I neglected to remove FQCN from the code I posted as in the last getLogger method, you'll see that my example is passing in the ExtLogger.class and AbstractLogger.class. Basically, what would have been two separate FQCN. I don't particularly need to pass in actual classes. They could be FQCN strings. Also, this is is just code that demonstrates where we could take it if we moved forward with what I am suggesting in LOG4J2-562 and influenced by the discussion in LOG4J2-555 . The code as I provided does not actually work currently with the trunk on log4j2. It is important to note that I'm giving 2 FQCNs. Because some of the implemented methods are on AbstractLogger and others on ExtLogger, we need to tell the extended logger about both classes. I imagine we would want to allow any number of FQCNs if we pursued this approach.
          Hide
          Bruce Brouwer added a comment -

          I'm abandoning the idea I had in LOG4J2-562 in favor of what I proposed in LOG4J-555. I think there is one aspect of LOG4J-562 that still has merit and could potentially effect this, but I'm going to leave that discussion for inside LOG4J-562. Here is what I think this code would look like in light of my patch provided in LOG4J2-555

          package com.bhb.log4j;
          
          import java.util.concurrent.ConcurrentHashMap;
          import java.util.concurrent.ConcurrentMap;
          
          import org.apache.logging.log4j.Level;
          import org.apache.logging.log4j.LogManager;
          import org.apache.logging.log4j.Logger;
          import org.apache.logging.log4j.Marker;
          import org.apache.logging.log4j.message.Message;
          import org.apache.logging.log4j.message.MessageFactory;
          import org.apache.logging.log4j.spi.AbstractLoggerWrapper;
          import org.apache.logging.log4j.spi.LoggerProvider;
          
          public final class ExtLogger extends AbstractLoggerWrapper {
              private static final long serialVersionUID = 1L;
              private static final ConcurrentMap<String, ExtLogger> loggers = new ConcurrentHashMap<String, ExtLogger>();
          
              private static final String FQCN = ExtLogger.class.getName();
              public static final Level DIAG = Level.forName("DIAG", 350);
              public static final Level NOTICE = Level.forName("NOTICE", 450);
              public static final Level VERBOSE = Level.forName("VERBOSE", 550);
          
              private ExtLogger(Logger logger) {
                  super((LoggerProvider) logger, logger.getName(), logger.getMessageFactory());
              }
          
              /**
               * Returns a custom Logger with the name of the calling class.
               * 
               * @return The custom Logger for the calling class.
               */
              public static ExtLogger getLogger() {
                  return getLogger(getClassName(2));
              }
          
              /**
               * Returns a custom Logger using the fully qualified name of the Class as the Logger name.
               * 
               * @param loggerName The Class whose name should be used as the Logger name. If null it will
               *            default to the calling class.
               * @return The custom Logger.
               */
              public static ExtLogger getLogger(final Class<?> clazz) {
                  return getLogger(clazz != null ? clazz.getName() : getClassName(2));
              }
          
              /**
               * Returns a custom Logger using the fully qualified name of the Class as the Logger name.
               * 
               * @param loggerName The Class whose name should be used as the Logger name. If null it will
               *            default to the calling class.
               * @param messageFactory The message factory is used only when creating a logger, subsequent use
               *            does not change the logger but will log a warning if mismatched.
               * @return The custom Logger.
               */
              public static ExtLogger getLogger(final Class<?> clazz, final MessageFactory factory) {
                  return getLogger(clazz != null ? clazz.getName() : getClassName(2), factory);
              }
          
              /**
               * Returns a custom Logger using the fully qualified class name of the value as the Logger name.
               * 
               * @param value The value whose class name should be used as the Logger name. If null the name
               *            of the calling class will be used as the logger name.
               * @return The custom Logger.
               */
              public static ExtLogger getLogger(final Object value) {
                  return getLogger(value != null ? value.getClass().getName() : getClassName(2));
              }
          
              /**
               * Returns a custom Logger using the fully qualified class name of the value as the Logger name.
               * 
               * @param value The value whose class name should be used as the Logger name. If null the name
               *            of the calling class will be used as the logger name.
               * @param messageFactory The message factory is used only when creating a logger, subsequent use
               *            does not change the logger but will log a warning if mismatched.
               * @return The custom Logger.
               */
              public static ExtLogger getLogger(final Object value, final MessageFactory factory) {
                  return getLogger(value != null ? value.getClass().getName() : getClassName(2), factory);
              }
          
              /**
               * Returns a custom Logger with the specified name.
               * 
               * @param name The logger name. If null the name of the calling class will be used.
               * @return The custom Logger.
               */
              public static ExtLogger getLogger(final String name) {
                  return getLogger(name != null ? name : getClassName(2), null);
              }
          
              /**
               * Returns a custom Logger with the specified name.
               * 
               * @param name The logger name. If null the name of the calling class will be used.
               * @param messageFactory The message factory is used only when creating a logger, subsequent use
               *            does not change the logger but will log a warning if mismatched.
               * @return The custom Logger.
               */
              public static ExtLogger getLogger(final String name, final MessageFactory factory) {
                  final String actualName = name != null ? name : getClassName(2);
                  if (loggers.containsKey(actualName)) {
                      return loggers.get(actualName);
                  }
                  // Since both ExtLogger and AbstractLogger methods will be entry points, both are listed for FQCN to make caller location work
                  final ExtLogger result = new ExtLogger(LogManager.getContext().getLogger(actualName, factory));
                  final ExtLogger existing = loggers.putIfAbsent(actualName, result);
                  return existing == null ? result : existing;
              }
          
              /**
               * Gets the class name of the caller in the current stack at the given {@code depth}.
               * 
               * @param depth a 0-based index in the current stack.
               * @return a class name
               */
              private static String getClassName(final int depth) {
                  return new Throwable().getStackTrace()[depth].getClassName();
              }
          
              /**
               * Logs a message with the specific Marker at the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               */
              public void diag(final Marker marker, final Message msg) {
                  log(FQCN, DIAG, marker, msg, null);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void diag(final Marker marker, final Message msg, final Throwable t) {
                  log(FQCN, DIAG, marker, msg, t);
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void diag(final Marker marker, final Object message) {
                  log(FQCN, DIAG, marker, message, null);
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final Marker marker, final Object message, final Throwable t) {
                  log(FQCN, DIAG, marker, message, t);
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void diag(final Marker marker, final String message) {
                  log(FQCN, DIAG, marker, message, (Throwable) null);
              }
          
              /**
               * Logs a message with parameters at the {@code DIAG} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void diag(final Marker marker, final String message, final Object... params) {
                  log(FQCN, DIAG, marker, message, params);
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final Marker marker, final String message, final Throwable t) {
                  log(FQCN, DIAG, marker, message, t);
              }
          
              /**
               * Logs the specified Message at the {@code DIAG} level.
               * 
               * @param msg the message string to be logged
               */
              public void diag(final Message msg) {
                  log(FQCN, DIAG, null, msg, null);
              }
          
              /**
               * Logs the specified Message at the {@code DIAG} level.
               * 
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void diag(final Message msg, final Throwable t) {
                  log(FQCN, DIAG, null, msg, t);
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param message the message object to log.
               */
              public void diag(final Object message) {
                  log(FQCN, DIAG, null, message, null);
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final Object message, final Throwable t) {
                  log(FQCN, DIAG, null, message, t);
              }
          
              /**
               * Logs a message object with the {@code DIAG} level.
               * 
               * @param message the message object to log.
               */
              public void diag(final String message) {
                  log(FQCN, DIAG, null, message, (Throwable) null);
              }
          
              /**
               * Logs a message with parameters at the {@code DIAG} level.
               * 
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void diag(final String message, final Object... params) {
                  log(FQCN, DIAG, null, message, params);
              }
          
              /**
               * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void diag(final String message, final Throwable t) {
                  log(FQCN, DIAG, null, message, t);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               */
              public void notice(final Marker marker, final Message msg) {
                  log(FQCN, NOTICE, marker, msg, null);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void notice(final Marker marker, final Message msg, final Throwable t) {
                  log(FQCN, NOTICE, marker, msg, t);
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void notice(final Marker marker, final Object message) {
                  log(FQCN, NOTICE, marker, message, null);
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final Marker marker, final Object message, final Throwable t) {
                  log(FQCN, NOTICE, marker, message, t);
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void notice(final Marker marker, final String message) {
                  log(FQCN, NOTICE, marker, message, (Throwable) null);
              }
          
              /**
               * Logs a message with parameters at the {@code NOTICE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void notice(final Marker marker, final String message, final Object... params) {
                  log(FQCN, NOTICE, marker, message, params);
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final Marker marker, final String message, final Throwable t) {
                  log(FQCN, NOTICE, marker, message, t);
              }
          
              /**
               * Logs the specified Message at the {@code NOTICE} level.
               * 
               * @param msg the message string to be logged
               */
              public void notice(final Message msg) {
                  log(FQCN, NOTICE, null, msg, null);
              }
          
              /**
               * Logs the specified Message at the {@code NOTICE} level.
               * 
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void notice(final Message msg, final Throwable t) {
                  log(FQCN, NOTICE, null, msg, t);
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param message the message object to log.
               */
              public void notice(final Object message) {
                  log(FQCN, NOTICE, null, message, null);
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final Object message, final Throwable t) {
                  log(FQCN, NOTICE, null, message, t);
              }
          
              /**
               * Logs a message object with the {@code NOTICE} level.
               * 
               * @param message the message object to log.
               */
              public void notice(final String message) {
                  log(FQCN, NOTICE, null, message, (Throwable) null);
              }
          
              /**
               * Logs a message with parameters at the {@code NOTICE} level.
               * 
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void notice(final String message, final Object... params) {
                  log(FQCN, NOTICE, null, message, params);
              }
          
              /**
               * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable}
               * {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void notice(final String message, final Throwable t) {
                  log(FQCN, NOTICE, null, message, t);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               */
              public void verbose(final Marker marker, final Message msg) {
                  log(FQCN, VERBOSE, marker, msg, null);
              }
          
              /**
               * Logs a message with the specific Marker at the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void verbose(final Marker marker, final Message msg, final Throwable t) {
                  log(FQCN, VERBOSE, marker, msg, t);
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void verbose(final Marker marker, final Object message) {
                  log(FQCN, VERBOSE, marker, message, null);
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of the
               * {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final Marker marker, final Object message, final Throwable t) {
                  log(FQCN, VERBOSE, marker, message, t);
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message object to log.
               */
              public void verbose(final Marker marker, final String message) {
                  log(FQCN, VERBOSE, marker, message, (Throwable) null);
              }
          
              /**
               * Logs a message with parameters at the {@code VERBOSE} level.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void verbose(final Marker marker, final String message, final Object... params) {
                  log(FQCN, VERBOSE, marker, message, params);
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of the
               * {@link Throwable} {@code t} passed as parameter.
               * 
               * @param marker the marker data specific to this log statement
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final Marker marker, final String message, final Throwable t) {
                  log(FQCN, VERBOSE, marker, message, t);
              }
          
              /**
               * Logs the specified Message at the {@code VERBOSE} level.
               * 
               * @param msg the message string to be logged
               */
              public void verbose(final Message msg) {
                  log(FQCN, VERBOSE, null, msg, null);
              }
          
              /**
               * Logs the specified Message at the {@code VERBOSE} level.
               * 
               * @param msg the message string to be logged
               * @param t A Throwable or null.
               */
              public void verbose(final Message msg, final Throwable t) {
                  log(FQCN, VERBOSE, null, msg, t);
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param message the message object to log.
               */
              public void verbose(final Object message) {
                  log(FQCN, VERBOSE, null, message, null);
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of the
               * {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final Object message, final Throwable t) {
                  log(FQCN, VERBOSE, null, message, t);
              }
          
              /**
               * Logs a message object with the {@code VERBOSE} level.
               * 
               * @param message the message object to log.
               */
              public void verbose(final String message) {
                  log(FQCN, VERBOSE, null, message, (Throwable) null);
              }
          
              /**
               * Logs a message with parameters at the {@code VERBOSE} level.
               * 
               * @param message the message to log; the format depends on the message factory.
               * @param params parameters to the message.
               * @see #getMessageFactory()
               */
              public void verbose(final String message, final Object... params) {
                  log(FQCN, VERBOSE, null, message, params);
              }
          
              /**
               * Logs a message at the {@code VERBOSE} level including the stack trace of the
               * {@link Throwable} {@code t} passed as parameter.
               * 
               * @param message the message to log.
               * @param t the exception to log, including its stack trace.
               */
              public void verbose(final String message, final Throwable t) {
                  log(FQCN, VERBOSE, null, message, t);
              }
          }
          
          Show
          Bruce Brouwer added a comment - I'm abandoning the idea I had in LOG4J2-562 in favor of what I proposed in LOG4J-555. I think there is one aspect of LOG4J-562 that still has merit and could potentially effect this, but I'm going to leave that discussion for inside LOG4J-562. Here is what I think this code would look like in light of my patch provided in LOG4J2-555 package com.bhb.log4j; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.MessageFactory; import org.apache.logging.log4j.spi.AbstractLoggerWrapper; import org.apache.logging.log4j.spi.LoggerProvider; public final class ExtLogger extends AbstractLoggerWrapper { private static final long serialVersionUID = 1L; private static final ConcurrentMap< String , ExtLogger> loggers = new ConcurrentHashMap< String , ExtLogger>(); private static final String FQCN = ExtLogger.class.getName(); public static final Level DIAG = Level.forName( "DIAG" , 350); public static final Level NOTICE = Level.forName( "NOTICE" , 450); public static final Level VERBOSE = Level.forName( "VERBOSE" , 550); private ExtLogger(Logger logger) { super ((LoggerProvider) logger, logger.getName(), logger.getMessageFactory()); } /** * Returns a custom Logger with the name of the calling class. * * @ return The custom Logger for the calling class. */ public static ExtLogger getLogger() { return getLogger(getClassName(2)); } /** * Returns a custom Logger using the fully qualified name of the Class as the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. If null it will * default to the calling class. * @ return The custom Logger. */ public static ExtLogger getLogger( final Class <?> clazz) { return getLogger(clazz != null ? clazz.getName() : getClassName(2)); } /** * Returns a custom Logger using the fully qualified name of the Class as the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. If null it will * default to the calling class. * @param messageFactory The message factory is used only when creating a logger, subsequent use * does not change the logger but will log a warning if mismatched. * @ return The custom Logger. */ public static ExtLogger getLogger( final Class <?> clazz, final MessageFactory factory) { return getLogger(clazz != null ? clazz.getName() : getClassName(2), factory); } /** * Returns a custom Logger using the fully qualified class name of the value as the Logger name. * * @param value The value whose class name should be used as the Logger name. If null the name * of the calling class will be used as the logger name. * @ return The custom Logger. */ public static ExtLogger getLogger( final Object value) { return getLogger(value != null ? value.getClass().getName() : getClassName(2)); } /** * Returns a custom Logger using the fully qualified class name of the value as the Logger name. * * @param value The value whose class name should be used as the Logger name. If null the name * of the calling class will be used as the logger name. * @param messageFactory The message factory is used only when creating a logger, subsequent use * does not change the logger but will log a warning if mismatched. * @ return The custom Logger. */ public static ExtLogger getLogger( final Object value, final MessageFactory factory) { return getLogger(value != null ? value.getClass().getName() : getClassName(2), factory); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will be used. * @ return The custom Logger. */ public static ExtLogger getLogger( final String name) { return getLogger(name != null ? name : getClassName(2), null ); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will be used. * @param messageFactory The message factory is used only when creating a logger, subsequent use * does not change the logger but will log a warning if mismatched. * @ return The custom Logger. */ public static ExtLogger getLogger( final String name, final MessageFactory factory) { final String actualName = name != null ? name : getClassName(2); if (loggers.containsKey(actualName)) { return loggers.get(actualName); } // Since both ExtLogger and AbstractLogger methods will be entry points, both are listed for FQCN to make caller location work final ExtLogger result = new ExtLogger(LogManager.getContext().getLogger(actualName, factory)); final ExtLogger existing = loggers.putIfAbsent(actualName, result); return existing == null ? result : existing; } /** * Gets the class name of the caller in the current stack at the given {@code depth}. * * @param depth a 0-based index in the current stack. * @ return a class name */ private static String getClassName( final int depth) { return new Throwable().getStackTrace()[depth].getClassName(); } /** * Logs a message with the specific Marker at the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged */ public void diag( final Marker marker, final Message msg) { log(FQCN, DIAG, marker, msg, null ); } /** * Logs a message with the specific Marker at the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged * @param t A Throwable or null . */ public void diag( final Marker marker, final Message msg, final Throwable t) { log(FQCN, DIAG, marker, msg, t); } /** * Logs a message object with the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void diag( final Marker marker, final Object message) { log(FQCN, DIAG, marker, message, null ); } /** * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final Marker marker, final Object message, final Throwable t) { log(FQCN, DIAG, marker, message, t); } /** * Logs a message object with the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void diag( final Marker marker, final String message) { log(FQCN, DIAG, marker, message, (Throwable) null ); } /** * Logs a message with parameters at the {@code DIAG} level. * * @param marker the marker data specific to this log statement * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void diag( final Marker marker, final String message, final Object ... params) { log(FQCN, DIAG, marker, message, params); } /** * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final Marker marker, final String message, final Throwable t) { log(FQCN, DIAG, marker, message, t); } /** * Logs the specified Message at the {@code DIAG} level. * * @param msg the message string to be logged */ public void diag( final Message msg) { log(FQCN, DIAG, null , msg, null ); } /** * Logs the specified Message at the {@code DIAG} level. * * @param msg the message string to be logged * @param t A Throwable or null . */ public void diag( final Message msg, final Throwable t) { log(FQCN, DIAG, null , msg, t); } /** * Logs a message object with the {@code DIAG} level. * * @param message the message object to log. */ public void diag( final Object message) { log(FQCN, DIAG, null , message, null ); } /** * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final Object message, final Throwable t) { log(FQCN, DIAG, null , message, t); } /** * Logs a message object with the {@code DIAG} level. * * @param message the message object to log. */ public void diag( final String message) { log(FQCN, DIAG, null , message, (Throwable) null ); } /** * Logs a message with parameters at the {@code DIAG} level. * * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void diag( final String message, final Object ... params) { log(FQCN, DIAG, null , message, params); } /** * Logs a message at the {@code DIAG} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void diag( final String message, final Throwable t) { log(FQCN, DIAG, null , message, t); } /** * Logs a message with the specific Marker at the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged */ public void notice( final Marker marker, final Message msg) { log(FQCN, NOTICE, marker, msg, null ); } /** * Logs a message with the specific Marker at the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged * @param t A Throwable or null . */ public void notice( final Marker marker, final Message msg, final Throwable t) { log(FQCN, NOTICE, marker, msg, t); } /** * Logs a message object with the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void notice( final Marker marker, final Object message) { log(FQCN, NOTICE, marker, message, null ); } /** * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final Marker marker, final Object message, final Throwable t) { log(FQCN, NOTICE, marker, message, t); } /** * Logs a message object with the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void notice( final Marker marker, final String message) { log(FQCN, NOTICE, marker, message, (Throwable) null ); } /** * Logs a message with parameters at the {@code NOTICE} level. * * @param marker the marker data specific to this log statement * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void notice( final Marker marker, final String message, final Object ... params) { log(FQCN, NOTICE, marker, message, params); } /** * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final Marker marker, final String message, final Throwable t) { log(FQCN, NOTICE, marker, message, t); } /** * Logs the specified Message at the {@code NOTICE} level. * * @param msg the message string to be logged */ public void notice( final Message msg) { log(FQCN, NOTICE, null , msg, null ); } /** * Logs the specified Message at the {@code NOTICE} level. * * @param msg the message string to be logged * @param t A Throwable or null . */ public void notice( final Message msg, final Throwable t) { log(FQCN, NOTICE, null , msg, t); } /** * Logs a message object with the {@code NOTICE} level. * * @param message the message object to log. */ public void notice( final Object message) { log(FQCN, NOTICE, null , message, null ); } /** * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final Object message, final Throwable t) { log(FQCN, NOTICE, null , message, t); } /** * Logs a message object with the {@code NOTICE} level. * * @param message the message object to log. */ public void notice( final String message) { log(FQCN, NOTICE, null , message, (Throwable) null ); } /** * Logs a message with parameters at the {@code NOTICE} level. * * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void notice( final String message, final Object ... params) { log(FQCN, NOTICE, null , message, params); } /** * Logs a message at the {@code NOTICE} level including the stack trace of the {@link Throwable} * {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void notice( final String message, final Throwable t) { log(FQCN, NOTICE, null , message, t); } /** * Logs a message with the specific Marker at the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged */ public void verbose( final Marker marker, final Message msg) { log(FQCN, VERBOSE, marker, msg, null ); } /** * Logs a message with the specific Marker at the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param msg the message string to be logged * @param t A Throwable or null . */ public void verbose( final Marker marker, final Message msg, final Throwable t) { log(FQCN, VERBOSE, marker, msg, t); } /** * Logs a message object with the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void verbose( final Marker marker, final Object message) { log(FQCN, VERBOSE, marker, message, null ); } /** * Logs a message at the {@code VERBOSE} level including the stack trace of the * {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final Marker marker, final Object message, final Throwable t) { log(FQCN, VERBOSE, marker, message, t); } /** * Logs a message object with the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param message the message object to log. */ public void verbose( final Marker marker, final String message) { log(FQCN, VERBOSE, marker, message, (Throwable) null ); } /** * Logs a message with parameters at the {@code VERBOSE} level. * * @param marker the marker data specific to this log statement * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void verbose( final Marker marker, final String message, final Object ... params) { log(FQCN, VERBOSE, marker, message, params); } /** * Logs a message at the {@code VERBOSE} level including the stack trace of the * {@link Throwable} {@code t} passed as parameter. * * @param marker the marker data specific to this log statement * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final Marker marker, final String message, final Throwable t) { log(FQCN, VERBOSE, marker, message, t); } /** * Logs the specified Message at the {@code VERBOSE} level. * * @param msg the message string to be logged */ public void verbose( final Message msg) { log(FQCN, VERBOSE, null , msg, null ); } /** * Logs the specified Message at the {@code VERBOSE} level. * * @param msg the message string to be logged * @param t A Throwable or null . */ public void verbose( final Message msg, final Throwable t) { log(FQCN, VERBOSE, null , msg, t); } /** * Logs a message object with the {@code VERBOSE} level. * * @param message the message object to log. */ public void verbose( final Object message) { log(FQCN, VERBOSE, null , message, null ); } /** * Logs a message at the {@code VERBOSE} level including the stack trace of the * {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final Object message, final Throwable t) { log(FQCN, VERBOSE, null , message, t); } /** * Logs a message object with the {@code VERBOSE} level. * * @param message the message object to log. */ public void verbose( final String message) { log(FQCN, VERBOSE, null , message, (Throwable) null ); } /** * Logs a message with parameters at the {@code VERBOSE} level. * * @param message the message to log; the format depends on the message factory. * @param params parameters to the message. * @see #getMessageFactory() */ public void verbose( final String message, final Object ... params) { log(FQCN, VERBOSE, null , message, params); } /** * Logs a message at the {@code VERBOSE} level including the stack trace of the * {@link Throwable} {@code t} passed as parameter. * * @param message the message to log. * @param t the exception to log, including its stack trace. */ public void verbose( final String message, final Throwable t) { log(FQCN, VERBOSE, null , message, t); } }
          Hide
          Remko Popma added a comment -

          This weekend I won't have time (one more push for an exam I have next week), but after that I'll look at the patch for LOG4J2-555 and also update the generator tool.

          Show
          Remko Popma added a comment - This weekend I won't have time (one more push for an exam I have next week), but after that I'll look at the patch for LOG4J2-555 and also update the generator tool.
          Hide
          Remko Popma added a comment -

          Updated attached Generate.java for RC2.

          Show
          Remko Popma added a comment - Updated attached Generate.java for RC2.
          Hide
          Remko Popma added a comment - - edited

          I am working on JUnit tests for both the Generate CustomLogger and Generate ExtendedLogger use cases.

          The JUnit test uses the tool to generate source code, compiles it, asserts that the generated class has the expected methods, and finally executes some simple logging using the generated class and validates the result. This ensures that any future API changes, if they occur, will break the JUnit tests and give us a heads-up that the tool needs to be updated too.

          Once I have this working I would like to commit the tool to the org.apache.logging.log4j.util package in the log4j-api module. Since the tool only has dependencies on log4j-api and not on log4j-core, I think the api module is the best place for it.

          About the class name: usually class names are nouns, and method names are verbs, so that when the class is used it will follow the noun.verb() pattern (e.g. car.move(), bird.fly()). This class is only used from the command line, and there are two use cases:
          java Generate$CustomLogger and java Generate$ExtendedLogger. This follows the verb + noun pattern. If we were to rename the class to Generator or some other noun, we would end up with java Generator$CustomLogger, giving us a noun + noun pattern, like car.wheel(), or bird.beak(). This does not look right to me.

          Because of this command line-only usage I think it is appropriate to not follow Java conventions in this particular case and keep the class name a verb.

          Thoughts?

          Show
          Remko Popma added a comment - - edited I am working on JUnit tests for both the Generate CustomLogger and Generate ExtendedLogger use cases. The JUnit test uses the tool to generate source code, compiles it, asserts that the generated class has the expected methods, and finally executes some simple logging using the generated class and validates the result. This ensures that any future API changes, if they occur, will break the JUnit tests and give us a heads-up that the tool needs to be updated too. Once I have this working I would like to commit the tool to the org.apache.logging.log4j.util package in the log4j-api module. Since the tool only has dependencies on log4j-api and not on log4j-core, I think the api module is the best place for it. About the class name: usually class names are nouns, and method names are verbs, so that when the class is used it will follow the noun.verb() pattern (e.g. car.move(), bird.fly()). This class is only used from the command line, and there are two use cases: java Generate$CustomLogger and java Generate$ExtendedLogger . This follows the verb + noun pattern. If we were to rename the class to Generator or some other noun, we would end up with java Generator$CustomLogger , giving us a noun + noun pattern, like car.wheel(), or bird.beak(). This does not look right to me. Because of this command line-only usage I think it is appropriate to not follow Java conventions in this particular case and keep the class name a verb. Thoughts?
          Hide
          Remko Popma added a comment -

          Attached JUnit test for the Generate CustomLogger use case.

          Show
          Remko Popma added a comment - Attached JUnit test for the Generate CustomLogger use case.
          Hide
          Remko Popma added a comment -

          Attached JUnit test for the 2nd use case: generating extended loggers.

          Has anyone had a chance to think about my previous comment/questions?

          No objections if I commit the tool for generating custom/extended loggers to the org.apache.logging.log4j.util package in the log4j-api module?

          Show
          Remko Popma added a comment - Attached JUnit test for the 2nd use case: generating extended loggers. Has anyone had a chance to think about my previous comment/questions? No objections if I commit the tool for generating custom/extended loggers to the org.apache.logging.log4j.util package in the log4j-api module?
          Hide
          Remko Popma added a comment -

          Tool to be added to the org.apache.logging.log4j.core.tools package in the log4j-core module as discussed on the mailing list.

          Show
          Remko Popma added a comment - Tool to be added to the org.apache.logging.log4j.core.tools package in the log4j-core module as discussed on the mailing list.
          Hide
          Remko Popma added a comment -

          Committed in revision 1609735.

          I'll raise a separate ticket for documenting this feature.

          Show
          Remko Popma added a comment - Committed in revision 1609735. I'll raise a separate ticket for documenting this feature.

            People

            • Assignee:
              Remko Popma
              Reporter:
              Remko Popma
            • Votes:
              1 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development