[ 
https://issues.apache.org/jira/browse/LOG4J2-3330?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Mircea Lemnaru updated LOG4J2-3330:
-----------------------------------
    Description: 
I needed to set the log level for a certain logger in the application and for 
that I tried using the following code:

{{Configurator.setLevel(logger,level)}} but it did not seem to set the proper 
logging level.

After looking over the source code I have noticed the following behaviour:

Inside setLevel there is this line:
{code:java}
LoggerContext loggerContext = LoggerContext.getContext(false);{code}
Which fetches the LoggerContext for the caller class.

In turn , LoggerContext.getContext has the following content:

 
{code:java}
public static LoggerContext getContext(final boolean currentContext)
{ return (LoggerContext) LogManager.getContext(currentContext); }
{code}
 

Which delegates the context fetching to LogManager

LogManager in turn get's the context by passing a hardcoded class name as the 
stack marker:
{code:java}
private static final String FQCN = LogManager.class.getName();{code}
Because of this , the methods LoggerContext.getContext and 
LogManager.getContext behave differently in environments with multiple 
LoggerContexts and ClassLoaders

Test: 
 # Calling LoggerContext.getContext - returns LoggerContextA - corresponding to 
the classloader of LoggerContext because if we look at the stack trace:

{code:java}
getCallerClass:151, StackLocator (org.apache.logging.log4j.util)
getCallerClass:70, StackLocatorUtil (org.apache.logging.log4j.util)
getCallerClass:58, StackLocatorUtil (org.apache.logging.log4j.util)
getContext:138, ClassLoaderContextSelector 
(org.apache.logging.log4j.core.selector)
getContext:123, ClassLoaderContextSelector 
(org.apache.logging.log4j.core.selector)
getContext:230, Log4jContextFactory (org.apache.logging.log4j.core.impl)
getContext:47, Log4jContextFactory (org.apache.logging.log4j.core.impl)
getContext:176, LogManager (org.apache.logging.log4j)
getContext:231, LoggerContext (org.apache.logging.log4j.core) <---- returns this
handle:24, LogLevelChangeHandler (com.ispring.log.event) <----- real caller 
class{code}
Because of the fact that the context is fetched by providing the hardcoded FQCN 
which is LogManager ... getCallerClass(FQCN) will return LoggerContext instead 
of returning LogLevelChangeHandler ( the real caller )

2. Calling LogManager.getContext - returns LoggerContextB - corresponding to 
the classloader of LogLevelChangeHandler which is the correct behaviour since 
LogLevelChangeHandler is the class that is actually requesting the context.

If we look at the stack trace:
{code:java}
getCallerClass:151, StackLocator (org.apache.logging.log4j.util)
getCallerClass:70, StackLocatorUtil (org.apache.logging.log4j.util)
getCallerClass:58, StackLocatorUtil (org.apache.logging.log4j.util)
getContext:138, ClassLoaderContextSelector 
(org.apache.logging.log4j.core.selector)
getContext:123, ClassLoaderContextSelector 
(org.apache.logging.log4j.core.selector)
getContext:230, Log4jContextFactory (org.apache.logging.log4j.core.impl)
getContext:47, Log4jContextFactory (org.apache.logging.log4j.core.impl)
getContext:176, LogManager (org.apache.logging.log4j) <-- break point 
handle:25, LogLevelChangeHandler (com.ispring.log.event) <--- the correct class 
to be returned{code}
Because of the behaviour mentioned above , calling Configurator.setLevel 
doesn't have de desired effect in environments with multiple LoggerContexts ( 
webapp deployed in tomcat ) because it's setting the level one some 
LoggerContext which is not the one used by the application classes.

  was:
I needed to set the log level for a certain logger in the application and for 
that I tried using the following code:

Configurator.setLevel(logger,level) but it did not seem to set the proper 
logging level.

After looking over the source code I have noticed the following behaviour:

Inside setLevel there is this line:

LoggerContext loggerContext = LoggerContext.getContext(false);

Which fetches the LoggerContext for the caller class.

In turn , LoggerContext.getContext has the following content:

public static LoggerContext getContext(final boolean currentContext) {
return (LoggerContext) LogManager.getContext(currentContext);
}

Which delegates the context fetching to LogManager

LogManager in turn get's the context by passing a hardcoded class name as the 
stack marker:

private static final String FQCN = LogManager.class.getName();

Because of this , the methods LoggerContext.getContext and 
LogManager.getContext behave differently in environments with multiple 
LoggerContexts and ClassLoaders

Test: 
 # Calling LoggerContext.getContext - returns LoggerContextA - corresponding to 
the classloader of LoggerContext because if we look at the stack trace:

getCallerClass:151, StackLocator (org.apache.logging.log4j.util)
getCallerClass:70, StackLocatorUtil (org.apache.logging.log4j.util)
getCallerClass:58, StackLocatorUtil (org.apache.logging.log4j.util)
getContext:138, ClassLoaderContextSelector 
(org.apache.logging.log4j.core.selector)
getContext:123, ClassLoaderContextSelector 
(org.apache.logging.log4j.core.selector)
getContext:230, Log4jContextFactory (org.apache.logging.log4j.core.impl)
getContext:47, Log4jContextFactory (org.apache.logging.log4j.core.impl)
getContext:176, LogManager (org.apache.logging.log4j)
getContext:231, LoggerContext (org.apache.logging.log4j.core) <---- returns this
handle:24, LogLevelChangeHandler (com.ispring.log.event) <----- real caller 
class

Because of the fact that the context is fetched by providing the hardcoded FQCN 
which is LogManager ... getCallerClass(FQCN) will return LoggerContext instead 
of returning LogLevelChangeHandler ( the real caller )

2. Calling LogManager.getContext - returns LoggerContextB - corresponding to 
the classloader of LogLevelChangeHandler which is the correct behaviour since 
LogLevelChangeHandler is the class that is actually requesting the context.

If we look at the stack trace:

getCallerClass:151, StackLocator (org.apache.logging.log4j.util)
getCallerClass:70, StackLocatorUtil (org.apache.logging.log4j.util)
getCallerClass:58, StackLocatorUtil (org.apache.logging.log4j.util)
getContext:138, ClassLoaderContextSelector 
(org.apache.logging.log4j.core.selector)
getContext:123, ClassLoaderContextSelector 
(org.apache.logging.log4j.core.selector)
getContext:230, Log4jContextFactory (org.apache.logging.log4j.core.impl)
getContext:47, Log4jContextFactory (org.apache.logging.log4j.core.impl)
getContext:176, LogManager (org.apache.logging.log4j) <-- break point 
handle:25, LogLevelChangeHandler (com.ispring.log.event) <--- the correct class 
to be returned

Because of the behaviour mentioned above , calling Configurator.setLevel 
doesn't have de desired effect in environments with multiple LoggerContexts ( 
webapp deployed in tomcat ) because it's setting the level one some 
LoggerContext which is not the one used by the application classes.


> Configurator.setLevel not fetching the correct LoggerContext
> ------------------------------------------------------------
>
>                 Key: LOG4J2-3330
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-3330
>             Project: Log4j 2
>          Issue Type: Bug
>          Components: Core
>    Affects Versions: 2.17.1
>            Reporter: Mircea Lemnaru
>            Priority: Major
>
> I needed to set the log level for a certain logger in the application and for 
> that I tried using the following code:
> {{Configurator.setLevel(logger,level)}} but it did not seem to set the proper 
> logging level.
> After looking over the source code I have noticed the following behaviour:
> Inside setLevel there is this line:
> {code:java}
> LoggerContext loggerContext = LoggerContext.getContext(false);{code}
> Which fetches the LoggerContext for the caller class.
> In turn , LoggerContext.getContext has the following content:
>  
> {code:java}
> public static LoggerContext getContext(final boolean currentContext)
> { return (LoggerContext) LogManager.getContext(currentContext); }
> {code}
>  
> Which delegates the context fetching to LogManager
> LogManager in turn get's the context by passing a hardcoded class name as the 
> stack marker:
> {code:java}
> private static final String FQCN = LogManager.class.getName();{code}
> Because of this , the methods LoggerContext.getContext and 
> LogManager.getContext behave differently in environments with multiple 
> LoggerContexts and ClassLoaders
> Test: 
>  # Calling LoggerContext.getContext - returns LoggerContextA - corresponding 
> to the classloader of LoggerContext because if we look at the stack trace:
> {code:java}
> getCallerClass:151, StackLocator (org.apache.logging.log4j.util)
> getCallerClass:70, StackLocatorUtil (org.apache.logging.log4j.util)
> getCallerClass:58, StackLocatorUtil (org.apache.logging.log4j.util)
> getContext:138, ClassLoaderContextSelector 
> (org.apache.logging.log4j.core.selector)
> getContext:123, ClassLoaderContextSelector 
> (org.apache.logging.log4j.core.selector)
> getContext:230, Log4jContextFactory (org.apache.logging.log4j.core.impl)
> getContext:47, Log4jContextFactory (org.apache.logging.log4j.core.impl)
> getContext:176, LogManager (org.apache.logging.log4j)
> getContext:231, LoggerContext (org.apache.logging.log4j.core) <---- returns 
> this
> handle:24, LogLevelChangeHandler (com.ispring.log.event) <----- real caller 
> class{code}
> Because of the fact that the context is fetched by providing the hardcoded 
> FQCN which is LogManager ... getCallerClass(FQCN) will return LoggerContext 
> instead of returning LogLevelChangeHandler ( the real caller )
> 2. Calling LogManager.getContext - returns LoggerContextB - corresponding to 
> the classloader of LogLevelChangeHandler which is the correct behaviour since 
> LogLevelChangeHandler is the class that is actually requesting the context.
> If we look at the stack trace:
> {code:java}
> getCallerClass:151, StackLocator (org.apache.logging.log4j.util)
> getCallerClass:70, StackLocatorUtil (org.apache.logging.log4j.util)
> getCallerClass:58, StackLocatorUtil (org.apache.logging.log4j.util)
> getContext:138, ClassLoaderContextSelector 
> (org.apache.logging.log4j.core.selector)
> getContext:123, ClassLoaderContextSelector 
> (org.apache.logging.log4j.core.selector)
> getContext:230, Log4jContextFactory (org.apache.logging.log4j.core.impl)
> getContext:47, Log4jContextFactory (org.apache.logging.log4j.core.impl)
> getContext:176, LogManager (org.apache.logging.log4j) <-- break point 
> handle:25, LogLevelChangeHandler (com.ispring.log.event) <--- the correct 
> class to be returned{code}
> Because of the behaviour mentioned above , calling Configurator.setLevel 
> doesn't have de desired effect in environments with multiple LoggerContexts ( 
> webapp deployed in tomcat ) because it's setting the level one some 
> LoggerContext which is not the one used by the application classes.



--
This message was sent by Atlassian Jira
(v8.20.1#820001)

Reply via email to