Search code examples
log4jlog4j2

How to set the logging directory dynamically in Log4J2 by using service loader services?


I know that in Log4j2 you can set the logging directory dynamically by using something like:

System.setProperty('logDirectory', getLogDirectoryDynamically());

and use this value in Log4j2's configuration:

<File name="File" fileName="${sys:logDirectory:-.}/my.log" append="false">
...
</File>

Okay, but now assume, for whatever reasons you do NOT have a central location (for example no main method of a main class) where you can invoke System.setProperty('logDirectory', ...).

Is there a way that you can register some (java.util.ServiceLoader) services where you can add this logDirectory as property, maybe by implementing the org.apache.logging.log4j.util.PropertySource interface or something similar?

The aim is that at the first LogManager.getLogger(...) invocation your additional property source will be loaded by java.util.ServiceLoader which contains the value for logDirectory.


Solution

  • The PropertySource service is not used in a configuration file.

    What you can implement is StrLookup. Lookups are not detected through the normal ServiceLoader mechanism, but through Log4j's plugin mechanism, so you need to annotate the class with:

    @Plugin(name = "mylookup", category = StrLookup.CATEGORY)
    

    and compile it with the annotation processor contained in log4j-core (most of the time it is automatically detected).

    Once you have done that you can use:

    <File name="File" fileName="${mylookup:logDirectory:-.}/my.log" append="false">
    ...
    </File>
    

    in your config file.

    Remark: the name of the lookup must be all lowercase.