Best way to initialize log4j2 (TWO) programmatically

This is what I am doing to load the log4j2.xml file by specifying the location of the log file from another properties file to make the configuration easier to maintain:

MyProperties props = MyProperties.getInstance();
System.setProperty(MyConstants.AUDIT_LOG_ENV_VAR,
        props.getAuditLogFileName());
ConfigurationSource source =
        new ConfigurationSource(new FileInputStream(new File(
                System.getProperty(MyConstants.PROPERTIES_FILE_ENV_VAR)
                    + "/log4j2.xml")));
Configurator.initialize(null, source);

      

and log4j2 will take and use my filename because I specified it in Appender using the envvar replacement:

<File name="AuditLogger" fileName="${sys:AUDIT_LOG}">
  <PatternLayout pattern="DATETIME  %d{yyyy-MM-dd HH:mm:ss:SSS zzz}%n%msg%n" />
</File>

      

However, I don't like this because there is a smell in squeezing the value of the filename into the system environment before reading it again on the next line of code.

I like to programmatically program log4j2 using the ConfigurationFactory , but it looks like a similar way cannot be built on top of the log4j2.xml file - or is there

+3


source to share


1 answer


Usually the log4j2 team does not recommend programming configuration: the separation between the api and core jars should give developers a clear separation between API and implementation. The software configuration depends on implementation details, so it may be broken in a future version.

If there is anything that cannot be done with the customization, please let us know so we can improve it.

For your specific use case: it looks like you want to set a system property to a specific value before log4j2 initializes itself based on that value. If it's a standalone application, one way to avoid getting stuck in the details of a log4j2 implementation is to set all the required system properties before referencing any log4j2 classes:

public class MainWrapper {
    public static void main(String[] args) {
        System.setProperty("key", "value");
        // ... 
        ActualMain.main(args); // delegate to the actual start of the application
    }
}

      



An alternative that I would like to draw your attention to is to create your own custom search. This can be done in a few lines of code with the log4j2 plugin . It also depends on some implementation details, but the result is more powerful and reusable.

package com.mycompany;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.lookup.AbstractLookup;
import org.apache.logging.log4j.core.lookup.StrLookup;

/** Looks up keys in MyProperties singleton. */
@Plugin(name = "MyProperties", category = StrLookup.CATEGORY)
public class MyPropertiesLookup extends AbstractLookup {
    @Override public String lookup(final LogEvent event, final String key) {
        return MyProperties.getInstance().getValue(key);
    }
}

      

Then in your configuration, you can use your own search instead of system properties:

<File name="AuditLogger" fileName="${MyProperties:AUDIT_LOG}">
  <PatternLayout pattern="DATETIME  %d{yyyy-MM-dd HH:mm:ss:SSS zzz}%n%msg%n" />
</File>

      

+2


source







All Articles