Skip to content

How do I use Multiple Substitutions in Lookups for Log4J 2 configurations? Is it possible?

I have a situation in which I want Log4J 2 to determine which directory to use for logging. The pseudocode is as follows:

property LOG_DIR = "./logs" // default
if (isDIR(${env:LOG_DIR}) {
  LOG_DIR = "${env:LOG_DIR}"
} else if (isDir(${sys:catalina.base}) {
  LOG_DIR = "${sys:catalina.base}/logs"
}

The configuration I have for properties (in log4j2.xml) is as follows:

<Configuration status="DEBUG">
  <Properties>
    <Property name="LOG_DIR">${sys:catalina.base}/logs:-logs</Property>
    <Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %t/%c:%L | %m%n</Property>
    <Property name="JAVA_HEADER">${java:version} - ${java:os}</Property>
  </Properties>
  <!-- Other configuration here -->
</configuration>

What I think it should look like:

<!-- Is this permitted? What happens if there's no Catalina Base AND no LOG_DIR env var? -->
<Property name="LOG_DIR">${env:LOG_DIR}:${sys:catalina.base}/logs:-logs</Property>

What I’m not sure on is how to get both ${env:LOG_DIR} and ${sys:catalina.base} options in the LOG_DIR property in configuration (before the default of logs). Is this even possible without a programmatic solution? (I’d like to avoid a programmatic solution as this config will be a template for multiple projects, some of which are libraries in SE applications. I’d like to avoid including a library that is only for configuring Log4J.) As far as I know, there can be only one lookup before the default. I don’t know if nesting or chaining is permitted.

Answer

Today, I encountered the same problem and i stumbled upon this question. I tried at my own end and i was successfully able to solve the issue and accomplish the desired result.

<Property name="LOG_DIR">${env:LOG_DIR:-${sys:catalina.base:-/logs}}/somexyz.log</Property>

sys: It stands for System environment variable, this is for whole PC or your current user.

env: It is the run time environment variable which you configure in runner in Intellij or similar.

According to log4J2 lookup official site: The general format of Lookup is ${sys:SOME_SYS_PATH:-default_path} or ${env:SOME_ENV_PATH:-default_path}.

Now as per your requirement, You want to see if a file path is configured in runtime environment or not, if yes then save all logs event data at that place. If no file is configured in runtime environment then look for system environment, if path is configured there then save all logging information there else save all logging information to a default path i.e /logs.

Use below code and it will work for you.

<Property name="LOG_DIR">${env:LOG_DIR:-${sys:catalina.base:-/logs}}/somexyz.log</Property>

If file path is configured in runtime environment then save it there, else check if path is configured in system environment(PC) and save there , else save it in default path /logs.