简体   繁体   English

在 log4j 中仅记录一次相同的异常记录器

[英]Log the same exception only once to logger in log4j

I want to implement solution that only logs the exception only once a day.我想实施每天只记录一次异常的解决方案。 I created a cache manager for that as well.我也为此创建了一个缓存管理器。

But I am facing the problem that how to intercept the LOGGER.error and not execute this method again.但我面临的问题是如何拦截 LOGGER.error 并且不再执行此方法。

In my application there are so many places, this LOGGER.error statement is used and I don't want to touch everywhere to check the condition like if same exception is there in cache or not.在我的应用程序中有很多地方,使用了这个 LOGGER.error 语句,我不想到处触摸来检查条件,比如缓存中是否存在相同的异常。

I want the solution like instead of touching everywhere it should done something centrally using filter or intercepting method.我想要的解决方案不是触及任何地方,而是应该使用过滤器或拦截方法集中完成某些事情。

We are using log4j for logging我们使用 log4j 进行日志记录

Filtering log messages is not performed by the logging APIs (like SLF4J or Log4j2 API), but by the logging backends (like Logback or Log4j2 Core).过滤日志消息不是由日志 API(如 SLF4J 或 Log4j2 API)执行,而是由日志后端(如 Logback 或 Log4j2 Core)执行。

All backends define some sort of Filter , eg org.apache.logging.log4j.core.Filter for Log4j2 Core.所有后端都定义了某种Filter ,例如org.apache.logging.log4j.core.Filter用于 Log4j2 Core。 The filter you are trying to implement would look like:您尝试实现的过滤器如下所示:

@Plugin(name = "ThrownBurstFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
public class ThrownBurstFilter extends AbstractFilter {

   private final long                         minInterval;
   private final Map<StackTraceElement, Long> locationTimeouts = new ConcurrentHashMap<>();

   private ThrownBurstFilter(final Result onMatch, final Result onMismatch, final long minInterval) {
      super(onMatch, onMismatch);
      this.minInterval = minInterval;
   }

   @PluginBuilderFactory
   public static Builder newBuilder() {
      return new Builder();
   }

   @Override
   public Result filter(LogEvent event) {
      final Throwable t = event.getThrown();
      if (t != null) {
         final StackTraceElement[] stackTrace = t.getStackTrace();
         final StackTraceElement location = stackTrace != null && stackTrace.length > 0 ? stackTrace[0] : null;
         if (location != null) {
            final long now = System.currentTimeMillis();
            final long nextTimeout = now + minInterval * 1000L;
            final Long timeout = locationTimeouts.putIfAbsent(location, nextTimeout);
            if (timeout == null || timeout <= now) {
               locationTimeouts.put(location, nextTimeout);
               return onMismatch;
            }
            return onMatch;
         }
      }
      return onMismatch;
   }

   public static class Builder extends AbstractFilterBuilder<Builder> implements org.apache.logging.log4j.core.util.Builder<ThrownBurstFilter> {

      /**
       * Minimum interval between events in seconds.
       */
      @PluginBuilderAttribute
      private long minInterval = 3600;

      public Builder setMinInterval(long minInterval) {
         this.minInterval = minInterval;
         return this;
      }

      @Override
      public ThrownBurstFilter build() {
         return new ThrownBurstFilter(getOnMatch(), getOnMismatch(), minInterval);
      }
   }
}

You need to compile it with annotation processors enabled and you can use it in a configuration file like this:您需要在启用注释处理器的情况下对其进行编译,并且可以在这样的配置文件中使用它:

<Loggers>
    <Root level="DEBUG">
        <ThrownBurstFilter minInterval="86400" onMatch="DENY" onMismath="NEUTRAL"/>
    </Root>
</Loggers>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM