有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在上下文范围内使用log4j2自定义筛选器对象?

我正试图按照the documentation的要求,使自定义过滤器在自定义范围内工作
考虑到默认过滤器被正确调用,而自定义过滤器没有被正确调用,我开始认为以这种方式使用自定义过滤器存在问题。我拥有的是:

阈值过滤器自定义。java(与ThresholdFilter相同,仅为调试而创建):

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
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.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.filter.AbstractFilter;
import org.apache.logging.log4j.message.Message;

@Plugin(name = "ThresholdFilterCustom", category = "Core", elementType = "filter", printObject = true)
public final class ThresholdFilterCustom extends AbstractFilter {

  private final Level level;

  private ThresholdFilterCustom(Level level, Result onMatch, Result onMismatch) {
    super(onMatch, onMismatch);
    this.level = level;
  }

  public Result filter(Logger logger, Level level, Marker marker, String msg, Object[] params) {
    return filter(level);
  }

  public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) {
    return filter(level);
  }

  public Result filter(Logger logger, Level level, Marker marker, Message msg, Throwable t) {
    return filter(level);
  }

  @Override
  public Result filter(LogEvent event) {
    return filter(event.getLevel());
  }

  private Result filter(Level level) {
    //    Look here! It should always match! not even filtering!
    return onMatch;
  }

  @Override
  public String toString() {
    return level.toString();
  }

  /**
   * Create a ThresholdFilterCustom.
   * @param loggerLevel The log Level.
   * @param match The action to take on a match.
   * @param mismatch The action to take on a mismatch.
   * @return The created ThresholdFilterCustom.
   */
  @PluginFactory
  public static ThresholdFilterCustom createFilter(@PluginAttribute(value = "level", defaultString = "ERROR") Level level,
      @PluginAttribute(value = "onMatch", defaultString = "NEUTRAL") Result onMatch,
      @PluginAttribute(value = "onMismatch", defaultString = "DENY") Result onMismatch) {
    return new ThresholdFilterCustom(level, onMatch, onMismatch);
  }
}

log4j2。xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
  <Filters>
      <ThresholdFilterCustom level="DEBUG" onMatch="ACCEPT" onMismatch="DENY" />
<!--      <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY" />-->
  </Filters>
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
    </Console>
  </Appenders>
  <Loggers>
    <Root level="INFO">
      <AppenderRef ref="Console" />
    </Root>
  </Loggers>
</Configuration>

如果我取消注释

<!--  <ThresholdFilterCustom level="DEBUG" onMatch="ACCEPT" onMismatch="DENY" />-->

我没有看到记录器记录的消息。在控制台中调试(“日志消息”)

但如果我取消注释

<!--  <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY" />-->

I查看记录器记录的消息。调试(“logmessage”),即使它们之间的行为应该相同。为什么会这样?这可能是log4j2问题吗

在使用调试器时,我看到定制过滤器中甚至没有调用过滤器函数,但定制过滤器正在实例化

如果我把它们放在记录器中,它们工作正常。但是,当把它们放在上下文中时,它们就不起作用了


共 (1) 个答案

  1. # 1 楼答案

    答案是here

    对于降落在这里的人来说:这是固定的。简言之,这些方法的javadoc似乎混淆了。要实现上下文范围的过滤器,其他方法应该被覆盖,那些不是过滤器的方法(LogEvent)

    根据拉尔夫·戈尔斯的评论:

    The plugin is being properly constructed and is being called. However, you did not override all the filter methods. Most of them default to return NEUTRAL, which is what the method did in this case. It probably would make more sense to have AbstractFilter default to calling one of the other methods so that no so many methods need to be overridden.

    他的另一个答案是:

    When the global Filters are evaluated a LogEvent has not been constructed. So if you want to only support the global filter then you need to implement all the methods that don't take a LogEvent. Likewise, to use the Filter in other places you need to only implement the method that accepts a LogEvent. Yes, I think the Javadoc has it backwards.

    What I mean with regard to the default methods is that there are 3 filter methods that explicitly return NEUTRAL.

    public Result filter(final Logger logger, final Level level, final
    Marker marker, final Message msg,final Throwable t); 
    public Result filter(final Logger logger, final Level level final Marker 
    marker, final Object msg,final Throwable t);
    public Result filter(final Logger logger, final Level level, final Marker 
    marker, final String msg, final Object... params);
    

    So all 3 of these need to be implemented In a Filter such as the one you created. All the other methods that accept a Logger end up calling the method above that accepts the varargs Object (i.e. an Object array) as the last parameter. It would make sense to me that the first 2 methods should also call the third method as the default instead of returning NEUTRAL. However, that would mean losing the explicit knowledge that one of the parameters was a Throwable, which I believe is why it is implemented as it is. I didn't mean that you need to do anything about this, except that right now you must implement all 3 methods above.