Question

I would like to know how to get my custom logger through log4j's LogManger.getLogger() method.

I'm almost sure my project doesn't need custom logger and go with default log4j's logger.

But, in case of necessary, I want to change all loggers in source code with my custom logger.

Can I do it with just changing setting file or LoggerFactory source code?

If this post is duplicate, please put the link to lead me there.

Thanks.

Was it helpful?

Solution

The recommended method is to modify the configuration file and have the watch flag set to true. If you want to push forwards doing the source-code approach though, see below.

It is a pretty involved process which includes casting to the log4j.core.logger type to expose protected methods that are hidden by the Logger interface. I should also give the disclaimer that this involves the protected methods in core.logger, which are subject to change at any time.

Lucky for you I just tackled this problem and have example code.

/**
 * Dynamically creates an instance of a Logger.
 * 
 * @param appenderName
 *            most often will be the name of the class this logger will
 *            belong to.
 * @param logFileName
 *            the file name to save the logs to
 * @return
 */
public static org.apache.logging.log4j.Logger createInstanceLogger(String appenderName,
        String logFileName) {
    //call getLogger() which will create and load a logger with a default configuration
    org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager
            .getLogger(String.format("DynamicLogger%s",
                    String.valueOf(DynamicLogManager.loggerCount++)));
    org.apache.logging.log4j.core.Logger coreLogger = (org.apache.logging.log4j.core.Logger) logger; // cast logger to core logger to access protected methods
    org.apache.logging.log4j.core.LoggerContext context = coreLogger.getContext();
    org.apache.logging.log4j.core.config.BaseConfiguration configuration = (org.apache.logging.log4j.core.config.BaseConfiguration) context
            .getConfiguration();

    TriggeringPolicy compositePolicy = CompositeTriggeringPolicy.createPolicy(
            SizeBasedTriggeringPolicy.createPolicy("5mb"),
            TimeBasedTriggeringPolicy.createPolicy("1", "true"));

    String fileName = String.format("%1$s/%2$s", appenderName, logFileName);
    String filePattern = String.format("%1$s/%2$s.%%d{yyyy-MM-dd}",
            appenderName, logFileName);

    Layout<String> layout = PatternLayout.createLayout(DynamicLogManager._conversionPattern,
            configuration, RegexReplacement.createRegexReplacement("a^", "."), //empty regex replacement
            "utf-8", "false");

    Filter f = ThresholdFilter.createFilter("trace", "accept", "accept");

    Appender a = RollingFileAppender.createAppender(fileName, //fileName
            filePattern, //filePattern
            "true", //append
            appenderName, //appender name
            "true", //bufferred io
            "true", //immediate flush
            compositePolicy, //policy
            null, //strategy default
            layout, //layout
            f, //filter none
            "true", //ignore exceptions
            "false", //advertise
            "null", //advertise uri
            configuration //configuration
            );

    a.start();

    coreLogger.addAppender(a);

    //this is where we would figure out how to configure the logger to listen on a configuration file
    coreLogger.setLevel(Level.ALL); //set the log level of the logger that we are returning to Level.ALL

    return coreLogger; //cast logger back to Logger interface

Edit following your comment:

It seems like you just want to add your logger to your xml configuration and grab it from java code, this is very easy to do...

  <Loggers>
    <Logger name="com.foo.Bar" level="trace" additivity="false">
      <AppenderRef ref="whateverAppenderName"/>
    </Logger>
    <Root level="error">
      <AppenderRef ref="whateverOtherAppenderName"/>
    </Root>
  </Loggers>

then in java code:

package com.foo;
class Bar{
private static final Logger log = LogManager.getLogger(); //qualified class name is com.foo.Bar
}

Logging in log4j is also hierarchal. This means if you define a logger with name "com.foo", it will be grabbed by all children of that package, if it is the most reachable logger(meaning, you don't have a more specific logger name for that particular class)

Read this... http://logging.apache.org/log4j/2.x/manual/configuration.html#XML

OTHER TIPS

Please take a look at https://issues.apache.org/jira/browse/LOG4J2-519

Note that the code generator attached to that ticket is experimental and custom/extended loggers generated with this tool may break in future releases of log4j-2.0.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top