|
23 | 23 | import co.elastic.apm.agent.matcher.WildcardMatcher; |
24 | 24 | import co.elastic.apm.agent.matcher.WildcardMatcherValueConverter; |
25 | 25 | import org.apache.logging.log4j.Level; |
| 26 | +import org.apache.logging.log4j.core.config.ConfigurationFactory; |
26 | 27 | import org.apache.logging.log4j.core.config.Configurator; |
27 | 28 | import org.apache.logging.log4j.status.StatusLogger; |
28 | 29 | import org.stagemonitor.configuration.ConfigurationOption; |
@@ -300,16 +301,22 @@ public void assertValid(Boolean value) { |
300 | 301 | public static void init(List<ConfigurationSource> sources, String ephemeralId) { |
301 | 302 | // The initialization of log4j may produce errors if the traced application uses log4j settings (for |
302 | 303 | // example - through file in the classpath or System properties) that configures specific properties for |
303 | | - // loading classes by name. Since we shade our usage of log4j, such non-shaded classes may not (and should not) |
304 | | - // be found on the classpath. |
| 304 | + // loading custom classes by name, which may not be found within the agent ClassLoader's classpath. |
305 | 305 | // All handled Exceptions should not prevent us from using log4j further, as the system falls back to a default |
306 | 306 | // which we expect anyway. We take a calculated risk of ignoring such errors only through initialization time, |
307 | 307 | // assuming that errors that will make the logging system non-usable won't be handled. |
308 | 308 | String initialListenersLevel = System.setProperty(INITIAL_LISTENERS_LEVEL, "OFF"); |
309 | 309 | String initialStatusLoggerLevel = System.setProperty(INITIAL_STATUS_LOGGER_LEVEL, "OFF"); |
310 | 310 | String defaultListenerLevel = System.setProperty(DEFAULT_LISTENER_LEVEL, "OFF"); |
311 | 311 | try { |
312 | | - Configurator.initialize(new Log4j2ConfigurationFactory(sources, ephemeralId).getConfiguration()); |
| 312 | + // org.apache.logging.log4j.core.config.ConfigurationFactory is a singleton that allows overriding its instance |
| 313 | + // through setConfigurationFactory. This API is not considered thread safe, but since we do it so early on when |
| 314 | + // there is only the main thread it should be OK. Once we override the default factory instance, any logger |
| 315 | + // created thereafter will be configured through our custom factory, regardless of its context. |
| 316 | + // Initializing only per context (the caller class loader by default, can be changed to thread or other), for |
| 317 | + // example through org.apache.logging.log4j.core.config.Configurator, means that loggers in non-initialized |
| 318 | + // contexts will either get the app-configuration for log4j, if such exists, or none. |
| 319 | + ConfigurationFactory.setConfigurationFactory(new Log4j2ConfigurationFactory(sources, ephemeralId)); |
313 | 320 | } catch (Throwable throwable) { |
314 | 321 | System.err.println("[elastic-apm-agent] ERROR Failure during initialization of agent's log4j system: " + throwable.getMessage()); |
315 | 322 | } finally { |
|
0 commit comments