当前位置: 首页 > 知识库问答 >
问题:

在运行时更新log4j2模式

祁鸿哲
2023-03-14

我找了很长时间,所以在标记为重复之前,请务必阅读。

我有一个函数(Lambda.handle()),它是用一个参数id调用的。我想将该id作为前缀添加到每个日志消息中。每次调用函数时,它都会更改。因此,我想更新记录器模式,将此id添加为前缀。

我读过:

  • 如何配置
  • 如何重新配置
  • SO和log4j论坛上的许多帖子都在讨论如何在运行时更改配置。它们要么过时,要么根本不起作用。

以下代码基于 log4j2 文档。它打印:

INIT  MyLogger handle() - id ONE 
INIT  MyLogger handle() - id TWO 
INIT  MyLogger handle() - id THR 

如果我注释掉行initLoggerConfig(“INIT”);然后它打印:

ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2
ONE  MyLogger handle() - id ONE 
ONE  MyLogger handle() - id TWO 
ONE  MyLogger handle() - id THR 

我希望它打印:

ONE  MyLogger handle() - id ONE 
TWO  MyLogger handle() - id TWO 
THR  MyLogger handle() - id THR 

我是否注释掉ctxLocal=ctx;,没有影响。

以下是我通过将log4j自己的日志记录级别设置为ALL(builder.setStatusLevel(Level.ALL))而获得的完整日志;

这是代码

package foobar;

import java.util.Arrays;
import java.util.List;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.config.AppenderRef;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
import org.apache.logging.log4j.core.layout.PatternLayout;

class Lambda {
  private static final String LOGGER_NAME = "MyLogger";
  private LoggerContext ctx;

  public Lambda() {
    initLoggerConfig("INIT ");
  }

  public void handle(String id) {
    updateLoggerConfig(id);
    Logger logger = LogManager.getLogger(LOGGER_NAME);
    logger.error("handle() - id {}", id);
  }

  private void updateLoggerConfig(String prefix) {
    final LoggerContext ctxLocal = (LoggerContext) LogManager.getContext(false);
    // ctxLocal = ctx;
    Configuration config = ctxLocal.getConfiguration();
    Layout<String> layout = PatternLayout.newBuilder().withPattern(prefix + " %c %m\n").withConfiguration(config)
        .build();
    Appender appender = ConsoleAppender.createDefaultAppenderForLayout(layout);
    appender.start();
    config.addAppender(appender);
    AppenderRef ref = AppenderRef.createAppenderRef("File", null, null);
    AppenderRef[] refs = new AppenderRef[] { ref };
    LoggerConfig loggerConfig = LoggerConfig.createLogger(false, Level.ALL, getClass().getName(), "true", refs, null,
        config, null);
    loggerConfig.addAppender(appender, null, null);
    config.addLogger(LOGGER_NAME, loggerConfig);
    ctxLocal.updateLoggers();
  }

  void initLoggerConfig(String prefix) {
    ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
    builder.setStatusLevel(Level.ERROR);
    builder.setConfigurationName("BuilderTest");
    builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL).addAttribute("level",
        Level.DEBUG));
    AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
        ConsoleAppender.Target.SYSTEM_OUT);
    appenderBuilder.add(builder.newLayout("PatternLayout").addAttribute("pattern", prefix + " %c %m\n"));
    appenderBuilder.add(
        builder.newFilter("MarkerFilter", Filter.Result.DENY, Filter.Result.NEUTRAL).addAttribute("marker", "FLOW"));
    builder.add(appenderBuilder);
    builder.add(builder.newLogger(LOGGER_NAME, Level.ALL).add(builder.newAppenderRef("Stdout"))
        .addAttribute("additivity", false));
    builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
    ctx = Configurator.initialize(builder.build());
  }
}

public class TestMain {
  static Lambda lamb = new Lambda();
  private static Logger logger = LogManager.getLogger();

  public static void main(String[] args) {
    Configurator.setLevel(logger.getName(), Level.ALL);
    List<String> a = Arrays.asList("ONE ", "TWO ", "THR ");
    for (String i : a) {
      lamb.handle(i);
    }

  }
}

共有1个答案

梅修贤
2023-03-14

使用D.B .建议的查找,这是我如何修复它。

在PatternLayout中添加对您的“变量”的引用,在下面的情况下我将其命名为MyVarialbe(您需要使用%X{}的确切语法:

appenderBuilder.add(builder.newLayout(“PatternLayout”) .addAttribute(“pattern”, “ %X{MyVariable} %msg%n%throwable”));

在稍后的代码中,您可以随时通过以下操作为其设置值:

org . Apache . logging . log4j . thread context . put(" my variable ",extra info);

以编程方式使用log4j2很复杂。因为我也有同样的困难,而且这篇文章已经发表3个月了,希望这个回答能对其他人有所帮助。

 类似资料:
  • 问题内容: 大约一年前,我偶然发现了Java的一个不错的功能,我一生都找不到。 通过一些魔术接口,显然可以在运行时声明一些可替换的类或函数。 我找到了一个很好的示例指南,该人运行了一个简单的小程序,该程序打印了一条特定的消息,然后他使用一种我不记得的方法更新了该程序,然后突然该程序将旧的打印功能替换为新的打印功能。 我尝试浏览Java API来激发我的记忆力和谷歌搜索功能,但没有成功。有人可以帮忙

  • 问题内容: 该示例非常简单:我想通过仅显示文本(canvas.drawText())来让用户知道应用程序在做什么。然后,出现我的第一条消息,而不是其他消息。我的意思是,我有一个“ setText”方法,但它不会更新。 该视图的文本绘制仅通过在onDraw();中执行一个drawText来起作用,因此setText更改了文本但不显示它。 有人建议我用SurfaceView替换视图,但是仅进行几次更新

  • 我将Drools与Eclipse和Maven一起用于一个进行许多模式匹配的应用程序。我想使用KieScanner自动更新正在运行的KieSession,而无需重新启动应用程序。但这似乎不起作用。 我使用的是7.24.0。t043用于组织。kie和org。流口水。 我只使用我的本地Maven存储库,所以我已经指定了路径并在我的settings.xml.中设置为true,我还验证了使用最新版本创建一个

  • 我不熟悉JTable。 我想在button press事件中在运行时更新jtable数据。 这是我的密码。 但按下“更新”按钮后不会更新。 有人能解决我的问题吗? 提前谢谢。。

  • 部署Hyperledger Composer后,您可能希望升级到新版本。要更新已安装的Hyperledger Composer版本,必须卸载客户端、管理员和运行时CLI组件,并使用npm重新安装它们。 过程 1.使用以下命令卸载Hyperledger Composer组件: npm uninstall -g composer-cli npm uninstall -g composer-

  • 是的,我已经阅读了所有相关的问题。我正在使用log4j2(尝试了2.4版和更新到最新的2.6.2版)。 我有一个面向客户的小型实用程序。我渴望将暴露的配置保持在最低限度。但对于有问题的情况,我还想添加一个标志,以便在运行时启用调试日志。 这是我启用调试日志记录的代码 但它实际上并不适用于这些情况: 实用程序通常在30秒内完成,因此更改应该是即时的。这是log4j2。xml 使用AppenderRe