Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Log4J – Runtime variable substitution

Log4J appears to have an annoying restriction – at runtime, variable substitution does not appear to work.

In this example

File: Log4j.properties

file_pattern=%d{ISO8601} %-5p %m%n

log4j.rootLogger=DEBUG, FileAppender

log4j.appender.FileAppender=org.apache.log4j.FileAppender log4j.appender.FileAppender.layout=org.apache.log4j.PatternLayout log4j.appender.FileAppender.layout.ConversionPattern=${file_pattern} log4j.appender.FileAppender.File=log4jtest1.log

log4j.appender.FileAppender.Threshold=ERROR

The FileAppender configured in the log4j.properties file produces the correct output:

File: log4jtest1.log

ERROR Sample error message FATAL Sample fatal message

If I attempt to create a FileAppender at runtime

import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

public class Main {
    static final Logger logger = Logger.getLogger(Main.class);

    public static void main(String[] args) throws Exception {

        FileAppender appender = new FileAppender();
        appender.setFile("log4test2.log");

        PatternLayout pl = new PatternLayout("${file_pattern}");

        appender.setLayout(pl);
        appender.setName("log4jtest2");
        appender.setThreshold(Level.ERROR);
        appender.activateOptions(); 
        logger.addAppender(appender);

        logger.trace("Sample trace message");
        logger.debug("Sample debug message");
        logger.info("Sample info message");
        logger.warn("Sample warn message");
        logger.error("Sample error message");
        logger.fatal("Sample fatal message");
    }
}

Te output is

File: log4jtest2.log

${file_pattern}${file_pattern}

Can anyone explain what is the problem and how can it be fixed?

Related question: Can an application access the ResourceBundle in order to read variables intended to be substituted?

like image 428
Adrian Avatar asked Jul 28 '26 16:07

Adrian


1 Answers

Variable substitution is a feature of PropertyConfigurator not of PatternLayout. If you look at your code, you never define what file_pattern should be. But why would you need variable substitution in code? Just do this:

 PatternLayout pl = new PatternLayout("%d{ISO8601} %-5p %m%n");

If you want to reference that string somewhere else, just make it a constant.

Edit: You will have to read the properties object, but PropertyConfigurator can take a properties object instead a file, so you could load that, do what you need to do and pass it on to the PropertiesConfigurator, so you only have one configuration path.

like image 82
Yishai Avatar answered Jul 30 '26 05:07

Yishai



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!