【问题标题】:log4j2 configuration will not load custom pattern converterlog4j2 配置不会加载自定义模式转换器
【发布时间】:2014-07-23 19:03:40
【问题描述】:

我正在尝试为 log4j 2.0 创建自定义模式转换器,但在让我的 log4j 配置识别模式时遇到问题。这是自定义转换器:

package com.test.log4j.plugins;

import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.pattern.ConverterKeys;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;

@Plugin(name="MarkerNamePatternConverter", category="Converter")
@ConverterKeys({"markername"})
public class MarkerNamePatternConverter extends LogEventPatternConverter {

    public static MarkerNamePatternConverter newInstance(final String[] options) {
        return new MarkerNamePatternConverter("markername", "markername");
    }

    protected MarkerNamePatternConverter(String name, String style) {
        super(name, style);
    }

    @Override
    public void format(LogEvent event, StringBuilder toAppendTo) {
        Marker marker = event.getMarker();
        if (marker != null) {
            // MarkerPatternConverter appends Marker.toString()
            // which includes the parents of the marker.  We just
            // want the marker's name
            toAppendTo.append(marker.getName());
        }
    }
}

这是我的 log4j 配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="trace" packages="com.test.log4j.plugins">
  <Appenders>
    <Console name="console" target="SYSTEM_OUT">
      <PatternLayout pattern=" %-6level %markername  %d{YYYY-MM-dd HH:mm:ss}  %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="debug">
      <AppenderRef ref="console"/>
    </Root>
  </Loggers>
</Configuration>

请注意,我在配置中包含了包含自定义转换器的包,缺少该包似乎是使用自定义插件时出现问题的常见原因。

执行测试代码时,配置状态输出并不表示插件已加载或找到,log4j 将 %markername 视为“%marker”后跟“name”的转换模式。例如,

Marker marker = MarkerManager.getMarker("TEST");
log.info(marker, "test message");

产生以下输出:

INFO   TESTname  2014-07-23 14:47:57  test message

我尝试将转换键更改为不以标准转换模式开头的值,例如“fmarker”,当执行 log4j 时会产生以下错误:

2014-07-23 14:44:55,814 ERROR Unrecognized format specifier [fmarker]
2014-07-23 14:44:55,816 ERROR Unrecognized conversion specifier [fmarker] starting at     position 18 in conversion pattern.
INFO   %fmarker  2014-07-23 14:44:55  test message

文档表明插件是在构建时而不是运行时收集的,但我没有发现任何表明我需要做一些特定的事情来找到我的自定义转换器,而不是:

  1. 使用@Plugin 和@ConverterKeys 对其进行注释
  2. 将插件的类别指定为“转换器”
  3. 包含一个静态的“newInstance(String[])”方法
  4. 实现“格式”方法
  5. 使用配置的“packages”参数指定插件包。

有一个 Maven 插件的文档,但我的简单测试只是在 Eclipse 中开发的一个基本 Java 项目。

关于我做错了什么有什么想法吗?

【问题讨论】:

    标签: java logging plugins converter log4j2


    【解决方案1】:

    长话短说,从 2.0-rc2 版本开始,packages 属性不再起作用。相反,log4j-core 中有一个注释处理器,它将(应该?)在构建期间运行,并将为您的 jar 文件中的自定义插件生成一个元数据文件。当 log4j2 启动时,它会在所有 jar 文件中查找元数据文件,并快速发现所有可用的插件。

    注解处理器在使用 Maven 或普通 javac 编译时可以工作,但在 Eclipse 中编译时可能无法正常工作。您需要通过右键单击项目 > 属性 > Java 编译器 > 注释处理来启用注释处理。

    不过,我不能 100% 确定这将在 Eclipse 中起作用。目前,一种替代方法是使用 Maven 构建您的自定义插件。

    我将尝试在即将发布的版本中使 packages 属性再次起作用。

    在此处跟踪此问题:https://issues.apache.org/jira/browse/LOG4J2-741

    更新 (7/28) 这已在主干中修复,并将包含在 2.0.1 版本中。

    【讨论】:

    • 谢谢 Remko。在 Eclipse 中启用注释处理不起作用,但使用 Maven 构建后一切正常。在您回复之前,我确实编写了一个将插件动态添加到插件注册表的类,但我猜这不是您推荐的解决方案。感谢您的帮助。
    • 请注意,Scala 等替代语言可能不支持 Java 注释处理器,并且目前在定义自定义插件时运气不佳。
    【解决方案2】:

    我也花了几个小时来解决这个问题......

    显然,这都是关于类加载的!

    使用这个技巧:

    使用 -verbose:class 运行您的应用(它将按顺序打印 JVM 加载的所有类)

    例如

    java -verbose:class -cp <your_jar> <your_main_class> ...
    

    搜索 log4j2 转换器类;在你的情况下,它应该是这样的:

    [Loaded com.test.log4j.plugins.MarkerNamePatternConverter from jar:file: ...]     
    

    您可能会注意到转换器类的加载相对较晚(我假设应该在加载 log4j2 插件之后)。

    要解决此问题,您可以尝试以下方法之一:

    1. 显式加载转换器类,即 Class.forName(...)
    2. 更改转换器类位置:将其放在主类旁边或下方(根据包层次结构)

    我尝试了这两个选项 - 第二个对我有用!

    祝你好运

    【讨论】:

      猜你喜欢
      • 2023-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-04
      • 2014-05-10
      • 2012-09-20
      • 2012-09-06
      • 1970-01-01
      相关资源
      最近更新 更多