【问题标题】:Why is Log4J (jul) attempting to MessageFormat a String message from Supplier为什么 Log4J (jul) 试图对来自供应商的字符串消息进行消息格式化
【发布时间】:2015-10-09 21:03:54
【问题描述】:

使用 Java 1.8 和 Log4J 2.4 JUL 适配器(log4j-jul-2.4.jar、log4j-core-2.4.jar、log4j-api-2.4.jar)

public class SimpleTest {

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

    // writing the configuration file on the fly
    try (java.io.PrintStream p = new java.io.PrintStream("./log4j-jul-test.xml")) {
      p.println("<Configuration>");
      p.println("  <Appenders>");
      p.println("    <Console name='Console' target='SYSTEM_OUT'>");
      p.println("      <PatternLayout pattern='JUL: %d %t %-5level %m%n' />");
      p.println("    </Console>");
      p.println("  </Appenders>");
      p.println("  <Loggers>");
      p.println("    <Root level='debug'>");
      p.println("      <AppenderRef ref='Console' />");
      p.println("    </Root>");
      p.println("  </Loggers>");
      p.println("</Configuration>");
    }
    System.setProperty("log4j.configurationFile", "log4j-jul-test.xml");


    // specifying the java.util.logging.LogManager implementation
    // COMMENT THE LINE BELOW TO SEE HOW THE STANDARD JAVA LOGGER REACTS
    System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");

    // getting the plain Java logger
    java.util.logging.Logger logger = java.util.logging.Logger.getLogger("test");

    // works with both standard and JUL loggers
    logger.info(() -> "This 1st line will be logged");  

    // works only with standard Java logger. JUL is attempting to MessageFormat it but shouldn't 
    logger.info(() -> "This 2nd line will {NOT} be logged by JUL");
    // JUL will report that An exception occurred processing Appender Console
    // java.lang.IllegalArgumentException: can't parse argument number: NOT
    //     at java.text.MessageFormat.makeFormat(MessageFormat.java:1429)
    //     at java.text.MessageFormat.applyPattern(MessageFormat.java:479)

    // works with both standard and JUL logger
    logger.log(java.util.logging.Level.INFO, "This 3rd line will {0} be logged", "successfully");
  }
}

上面的代码非常简单,可以快速运行。试试看!

有谁知道为什么 Log4J JUL 试图 MessageFormat 提供的 String 显然不应该,因为标准 Java 记录器没有? (现在无论如何都可以传递任何参数)

注意方法签名是:
java.util.logging.Logger.info(SupplierString >)

【问题讨论】:

  • 我在 JUL 案例中没有发现任何错误。它只是打印INFO: This 2nd line will {NOT} be logged by JUL
  • 嗨 Sotirios,我在 Log4J 模式布局的代码/配置文件中添加了一个指示符,日志条目“JUL: ...”的前缀,你能再试一次看看是否输出有那个前缀?
  • 我在评论setProperty 行时指的是。默认记录器会记录它。
  • 嗨 Sotirios,是的,Java 标准实现确实显示了第 2 行,问题是使用 Log4J2 JUL LogManager 时,不会输出同一行。

标签: java logging lambda log4j2 java.util.logging


【解决方案1】:

java.util.logging.Logger 的 Javadoc 说

大多数记录器输出方法都采用“msg”参数。此 msg 参数可以是原始值或本地化键。在格式化期间,如果记录器具有(或继承)本地化 ResourceBundle,并且如果 ResourceBundle 具有 msg 字符串的映射,则 msg 字符串将替换为本地化值。否则使用原始的 msg 字符串。通常,格式化程序使用 java.text.MessageFormat 样式格式化来格式化参数,例如,格式字符串“{0} {1}”会将两个参数格式化为字符串。

因为这个 Log4j 预计为 jul 编写的代码也需要这个,因此将提供的 String 转换为 MessageFormatMessage。但是,在查看 JDK 提供的 Formatter 时,它们实际上似乎都不支持 MessageFormat 格式。这值得在 Log4j 用户列表中讨论。

【讨论】:

  • 感谢您的建议。我已将此报告为 Apache Log4J 2 JIRA issues.apache.org/jira/browse/LOG4J2-1158 中的 bug
  • '然而,在查看 JDK 提供的格式化程序时,它们实际上似乎都不支持 MessageFormat 格式化。支持在j.u.l.Formatter.formatMessage 方法中。 JDK 格式化程序扩展了该基类,因此所有使用 formatMessage 的格式化程序都支持 MessageFormat 格式化。
猜你喜欢
  • 1970-01-01
  • 2011-04-08
  • 2021-12-07
  • 2022-11-07
  • 1970-01-01
  • 2021-12-07
  • 2012-11-06
  • 1970-01-01
  • 2019-01-19
相关资源
最近更新 更多