What is the default MessageFactory for Log4J
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:
- Create your own MessageFactory (extend from
AbstractMessageFactory
or just use theMessageFactory
interface) - Create a new LoggerContext (extend from the
LoggerContext
class or use theLoggerContext
interface- Override
newInstance(LoggerContext, String, MessageFactory)
and return your previously defined MessageFactory if argumentmessageFactory
isnull
- Override
- Create a new ContextSelector (extend from
ClassLoaderContextSelector
or just use theContextSelector
interface).- Override the method createContext(String, URI) and return a new instance of your previously defined LoggerContext
- Create a file
log4j.component.properties
in your classpath and set the propertyLog4jContextSelector
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
- Alternative: Don't create the file, just set the system property
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
- If you don't set a message factory,
ParameterizedMessageFactory
is used by default. - By default, log4j uses a message factory for parameterized messages, so you can do
logger.warn("hello {}", user.getName());
- 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.