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]
