log4j2 isThreadContextMapInheritable 属性用法

Posted

技术标签:

【中文标题】log4j2 isThreadContextMapInheritable 属性用法【英文标题】:log4j2 isThreadContextMapInheritable property usage 【发布时间】:2018-08-17 16:35:43 【问题描述】:

我正在尝试根据设置为 ThreadContext 的键来记录 Java 应用程序的事件以分隔日志文件。但是即使在系统属性中将“log4j2.isThreadContextMapInheritable”设置为“true”后,我的密钥也没有到达子线程(在 MouseEvent 上创建)。请有人帮我解决这个问题。

我的主要方法:

public class Application 
static 
    System.setProperty("log4j2.isThreadContextMapInheritable","true");


private final static Logger LOGGER = LogManager.getLogger(Application.class);

public static void main(String[] args) throws Exception

    ThreadContext.put("cfg","RLS");
    LOGGER.info("New window opening!!!"+ThreadContext.get("cfg"));
    newWindow();


private static void newWindow() throws Exception 
    ButtonFrame buttonFrame = new ButtonFrame("Button Demo");
    buttonFrame.setSize( 350, 275 );     
    buttonFrame.setVisible( true );

ButtonFrame 类:

public class ButtonFrame extends JFrame
private final static Logger LOGGER = LogManager.getLogger(NewWindow.class);
JButton bChange;
JFrame frame = new JFrame("Our JButton listener example");

  public ButtonFrame(String title)
  
    super( title );
    setLayout( new FlowLayout() );
    bChange = new JButton("Click Me!");
      bChange.addMouseListener(new MouseListener() 
          @Override
          public void mouseClicked(MouseEvent e) 
              try 
                  LOGGER.info("Mouse clicked!!!"+ThreadContext.get("cfg"));
                  JDialog d = new JDialog(frame, "HI", true);
                  d.setLocationRelativeTo(frame);
                  d.setVisible(true);
               catch (Exception e1) 
                  e1.printStackTrace();
              
          

          @Override
          public void mousePressed(MouseEvent e) 

          @Override
          public void mouseReleased(MouseEvent e) 

          @Override
          public void mouseEntered(MouseEvent e) 

          @Override
          public void mouseExited(MouseEvent e) 
      );
    add( bChange );                    
    setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );   
  

log4j2.properties 文件:

appenders = rls,otr,routing

appender.rls.type = RollingFile
appender.rls.name = RollingFile_Rls
appender.rls.fileName = D:\\RLS\\rls_%dMMdd.log
appender.rls.filePattern = D:\\RLS\\rls_%dMMdd.log
appender.rls.layout.type = PatternLayout
appender.rls.layout.pattern = %dABSOLUTE %levellength=1 
%markerSimpleName [%C1:%L] %m%n
appender.rls.policies.type = Policies
appender.rls.policies.time.type = TimeBasedTriggeringPolicy
appender.rls.policies.time.interval = 1
appender.rls.policies.time.modulate = true
appender.rls.policies.size.type = SizeBasedTriggeringPolicy
appender.rls.policies.size.size = 100MB
appender.rls.strategy.type = DefaultRolloverStrategy
appender.rls.strategy.max = 5
appender.otr.type = RollingFile
appender.otr.name = RollingFile_Otr
appender.otr.fileName = D:\\RLS\\otr_%dMMdd.log
appender.otr.filePattern = D:\\RLS\\otr_%dMMdd.log
appender.otr.layout.type = PatternLayout
appender.otr.layout.pattern = %dABSOLUTE %levellength=1 
%markerSimpleName [%C1:%L] %m%n
appender.otr.policies.type = Policies
appender.otr.policies.time.type = TimeBasedTriggeringPolicy
appender.otr.policies.time.interval = 1
appender.otr.policies.time.modulate = true
appender.otr.policies.size.type = SizeBasedTriggeringPolicy
appender.otr.policies.size.size = 100MB
appender.otr.strategy.type = DefaultRolloverStrategy
appender.otr.strategy.max = 5

appender.routing.type = Routing
appender.routing.name = Route_Finder
appender.routing.routes.type = Routes
appender.routing.routes.pattern = $$ctx:cfg
appender.routing.routes.route1.type = Route
appender.routing.routes.route1.ref = RollingFile_Rls
appender.routing.routes.route1.key = RLS
appender.routing.routes.route2.type = Route
appender.routing.routes.route2.ref = RollingFile_Otr
appender.routing.routes.route2.key = $$ctx:cfg

loggers = rls,otr

logger.rls.name = logging
logger.rls.level = info
logger.rls.additivity = false
logger.rls.appenderRefs=rls
logger.rls.appenderRef.rls.ref = Route_Finder

logger.rls.name = logging
logger.rls.level = info
logger.rls.additivity = false
logger.rls.appenderRefs=rls
logger.rls.appenderRef.rls.ref = Route_Finder

logger.otr.name = other
logger.otr.level = info
logger.otr.additivity = false
logger.otr.appenderRefs=otr
logger.otr.appenderRef.otr.ref = Route_Finder

rootLogger.level = trace
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = stdout

【问题讨论】:

找到解决方案:属性键应该是'isThreadContextMapInheritable'而不是'log4j2.isThreadContextMapInheritable' 【参考方案1】:

您可以将log4j2.component.properties 文件放在类路径中以控制 Log4j 2 行为的各个方面。 比如log4j2.component.properties的内容:

# https://logging.apache.org/log4j/2.x/manual/configuration.html#SystemProperties

# If true use an InheritableThreadLocal to implement the ThreadContext map.
# Otherwise, use a plain ThreadLocal. 
# (Maybe ignored if a custom ThreadContext map is specified.)
# Default is false

# Modern 2.10+
log4j2.isThreadContextMapInheritable=true

# Legacy for pre-2.10
isThreadContextMapInheritable=true

这优先于系统属性,但它可以被环境变量LOG4J_IS_THREAD_CONTEXT_MAP_INHERITABLE 覆盖,如 documentation.

【讨论】:

【参考方案2】:

添加 OP 的评论作为答案

通过将系统属性isThreadContextMapInheritable 设置为true,可以将ThreadContext 映射配置为使用InheritableThreadLocal

在我们启动应用程序时将系统属性设置为-DisThreadContextMapInheritable=true,或者在应用程序代码中使用以下代码:System.setProperty("isThreadContextMapInheritable", "true");

https://logging.apache.org/log4j/2.x/manual/thread-context.html https://logging.apache.org/log4j/2.x/manual/configuration.html#SystemProperties

【讨论】:

以上是关于log4j2 isThreadContextMapInheritable 属性用法的主要内容,如果未能解决你的问题,请参考以下文章

log4j2漏洞复现与利用

日志框架之log4j2的使用

如何在 IDE 中使用一个 log4j2 配置文件进行运行时,使用另一个 log4j2 配置文件进行打包/部署?

Log4j2配置

Log4j2 简单使用

你知道 log4j2 各项配置的全部含义吗?带你了解 log4j2 的全部组件