简体   繁体   中英

What is the default MessageFactory for Log4J

The documentation for org.apache.logging.log4j.Logger says

   /**
     * Logs a message with parameters at the given level.
     *
     * @param level the logging level
     * @param message the message to log; the format depends on the message factory.
     * @param params parameters to the message.
     * @see #getMessageFactory()
     */
    void log(Level level, String message, Object... params);

But:

  1. Which MessageFactory is used when I didn't set any?
  2. Which message format uses the default factory?
  3. How can I set my own factory in case the default factory can't do what I need?

Update:

Please add class names and XML element names to the answer. It is very difficult to find anything about Log4J 2.x on Google without the proper search terms.

  1. If you don't set a message factory, ParameterizedMessageFactory is used by default.
  2. By default, log4j uses a message factory for parameterized messages, so you can do logger.warn("hello {}", user.getName());
  3. You set your own factory by calling LogManager.getLogger(name, messageFactory) when you obtain a logger.

If you want the String.format kind of params (the System.out.printf format) you would use LogManager.getLogger(MyClass.class, new StringFormatterMessageFactory()) to obtain a logger.

If your most common usage is parameterized messages (the {} format), but if you occasionally want more control over the output format as afforded by the string formatter, you can declare your logger normally (so it uses {} parameterized messages), and use the Logger.printf methods.

Example:

class MyClass {
    private static Logger logger = LogManager.getLogger(MyClass.class);

    public void someMethod() {
        // use printf here to precisely control the number of digits displayed
        logger.printf(Level.INFO, "pi: %.5f", Math.PI);
    }
}

This is all in code. Configuration (XML or otherwise) is not involved.

This thread is already about one year old, but maybe I can still help some guys, because I just had the same problem and found out a way how to set your own default MessageFactory. It's a bit tricky, maybe someone else knows a better way without creating so much classes. But for me it works:

  1. Create your own MessageFactory (extend from AbstractMessageFactory or just use the MessageFactory interface)
  2. Create a new LoggerContext (extend from the LoggerContext class or use the LoggerContext interface
    • Override newInstance(LoggerContext, String, MessageFactory) and return your previously defined MessageFactory if argument messageFactory is null
  3. Create a new ContextSelector (extend from ClassLoaderContextSelector or just use the ContextSelector interface).
    • Override the method createContext(String, URI) and return a new instance of your previously defined LoggerContext
  4. Create a file log4j.component.properties in your classpath and set the property Log4jContextSelector to the fully-qualified-name of your in step 3 created contextSelector
    • Alternative: Don't create the file, just set the system property Log4jContextSelector to the fqn

Some code examples (without any comments):

MessageFactory:

public final class OwnMessageFactory extends AbstractMessageFactory
{
  public static final OwnMessageFactory INSTANCE = new OwnMessageFactory();

  @Override
  public Message newMessage(final String message, final Object... params)
  {
    return new OwnDataMessage(message, params);
  }
}

LoggerContext:

public class OwnLoggerContext extends LoggerContext
{
  // constructors

  protected Logger newInstance(final LoggerContext ctx, final String name, MessageFactory messageFactory)
  {
    if (null == messageFactory)
      messageFactory = OwnMessageFactory.INSTANCE;

    return super.newInstance(ctx, name, messageFactory);
  }

}

ContextSelector :

public class OwnContextSelector extends ClassLoaderContextSelector
{

  @Override
  protected LoggerContext createContext(String name, URI configLocation)
  {
    return new OwnLoggerContext(name, null, configLocation);
  }

}

log4j2.component.properties :

Log4jContextSelector=com.example.OwnContextSelector

1) Which MessageFactory is used when I did set any?

Using @Remko Popma hint I fount out that the default message factory is org.apache.logging.log4j.message.ParameterizedMessageFactory .

2) Which message format uses the default factory?

The {} syntax which java.util.logger uses as well.

3) How can I set my own factory in case the default factory can't do what I need?

Don't know yet.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM