ppkarwasz commented on issue #2852:
URL: 
https://github.com/apache/logging-log4j2/issues/2852#issuecomment-2304373882

   Hi @mattrpav,
   
   Your proposal certainly addresses several limitations in the way Log4j Core 
determines the appropriate configuration file, although I am not certain how 
these limitations should be addressed. From a maintainer perspective I would 
prefer not to have too many configuration knobs that I need to care about. If 
some feature applies to a very small number of environments, I would prefer to 
externalize it.
   
   Let's analyze the current situation and how we can improve it.
   
   ## Current status
   
   Currently Log4j Core has already a mechanism that looks for files named 
`log4j2<contextName>.xml` and falls back to `log4j2.xml` if nothing is found 
(see [configuration file 
location](https://logging.staged.apache.org/log4j/2.x/manual/configuration.html#automatic-configuration)).
 This mechanism is useless for Java SE applications (the `<contextName>` is 
random), but can be used with some success in "use case 2", if you integrate 
the runtime environment with Log4j Core. An example of such an integration is 
provided by the 
[`log4j-jakarta-web`](https://logging.staged.apache.org/log4j/2.x/components.html#log4j-jakarta-web)
 module (see the documentation of the 
[`log4jContextName`](https://logging.staged.apache.org/log4j/2.x/jakarta.html#log4jContextName)
 and 
[`log4jConfiguration`](https://logging.staged.apache.org/log4j/2.x/jakarta.html#log4jConfiguration)
 Servlet context parameters).
   
   Admittedly this mechanism is limited:
   
   1. As I stated before `<contextName>` is initialized to a random value in a 
Java SE application. Even in the favorable case of a Servlet Environment 
`<contextName>` does not necessarily give a valid file name, e.g. it can be the 
unescaped Servlet context path `/my-app`. However, you can always change it at 
runtime with a call like:
      ```java
      Configurator.initialize("-dev", null).reconfigure();
      ```
   2. The search path for the `log4j2<contextName>.xml` file is limited to the 
**classpath**. You could work around this limitation by setting the 
[`log4j2.configurationFile`](https://logging.staged.apache.org/log4j/2.x/manual/systemproperties.html#log4j2.configurationFile)
 property to something like `log4j2-${spring:profiles.active[0]}.xml`. This 
would enlarge the search path to the classpath **or** current working directory.
   
   ## Possible solutions
   
   ### Resolution of relative filenames
   
   As explained above, the search path for Log4j Core configuration files 
differs, depending on the value of `log4j2.configurationFile`:
   
   - If `log4j2.configurationFile` has a value that is not an absolute URI or 
file path, Log4j Core tries to find it in the **current working directory** or 
the classpath. This might resemble the way [Spring Boot does 
it](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files),
 but in my experience the cwd is a value the should not be relied upon, 
especially in a production environment, where applications are not started from 
the CLI.
   - if `log4j2.configurationFile` is not set, Log4j Core looks exclusively in 
the classpath.
   
   We should probably:
   
   1. Introduce a `log4j2.configurationArea` or `log4j2.configurationDirectory` 
configuration property as you propose, to provide a **list** of directories to 
be searched for configuration files. Runtime environments could set it to the 
value that makes most sense. For example Eclipse Equinox could use 
[`${osgi.configuration.area}`](https://help.eclipse.org/latest/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fmisc%2Fruntime-options.html&anchor=osgiinstallarea),
 while Tomcat could use `${catalina.base}/conf/:${catalina.home}/conf/`.
   2. Fix the automatic configuration mechanism to also look for files in 
`log4j2.configurationDirectory`.
   
   **Note**: We don't necessarily need a **new** configuration property. We 
could extend the definition of `log4j2.configurationFile` and use the same 
convention as Spring Boot (cf. [External Application 
Properties](https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.files):
 if a value in `log4j2.configurationFile` ends in `/`, it is treated as a 
directory and Log4j appends `log4j2-<contextName>.<extension>` to it.
   
   The default value of `log4j2.configurationFile` will change from `null` to 
`file:./,classpath:/` to provide backward compatibility.
   
   ### Determination of `<contextName>`
   
   To fully support the use cases you propose, we need some support from the 
runtime environment.
   
   #### Use Case 1
   
   I assume we are running in a Spring Boot environment. This environment is 
quite specific since Log4j Core is configured twice:
   
   * when the JVM starts it is configured **without** any access to Spring's 
environment. So a logger context is created, but we can not give it any 
significant name.
   * when the Spring Boot `Environment` is ready, the logger context is 
**reconfigured** programmatically by Spring Boot. Therefore we might expect 
Spring Boot to choose the appropriate configuration file among 
`log4j2-dev.xml`, `log4j2-prod.xml`. This can already be done by setting Spring 
Boot's `logger.config` property to a different value, depending on the 
environment.
   
   #### Use Case 2
   
   We might support this use case by improving the way 
[`ContextSelector`](https://logging.staged.apache.org/log4j/2.x/manual/extending.html#ContextSelector)
 determine the default `<contextName>`.
   
   Currently the `ClassLoaderContextSelector` uses `ClassLoader.hashCode()` as 
context name, which is pretty much useless. We could improve that by using 
[`ClassLoader.getName()`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/ClassLoader.html#getName())
 available since Java 9. The runtime environment could create classloaders 
named `order`, `quote` or `billing` to allow users to configure those services 
separately.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to