Java 频繁调用方法的日志记录实践

Java 频繁调用方法的日志记录实践,java,logging,exception-handling,Java,Logging,Exception Handling,在游戏开发中,经常调用许多方法(例如每秒60次)。有时,即使在这种方法中,我也希望记录捕获到的异常,但并不经常 我的想法是只记录特定方法中第一次出现的异常,但我没有找到任何方便的或内置的解决方案(至少在java中是这样)。除非您使用支持此功能的特定记录器,否则您试图获得的行为可以通过标记系统实现 例如,您可以在日志类中添加如下映射: Map<Class, MyTimer> logged = new HashMap<>(); import java.util.*; imp

在游戏开发中,经常调用许多方法(例如每秒60次)。有时,即使在这种方法中,我也希望记录捕获到的异常,但并不经常


我的想法是只记录特定方法中第一次出现的异常,但我没有找到任何方便的或内置的解决方案(至少在java中是这样)。

除非您使用支持此功能的特定记录器,否则您试图获得的行为可以通过标记系统实现

例如,您可以在日志类中添加如下映射:

Map<Class, MyTimer> logged = new HashMap<>();
import java.util.*;
import org.apache.log4j.Level;
import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.LocationInfo;

public class DuplicateMessagesFilter extends Filter {
  Map<String,String> previousMessages = new HashMap<String,String>();

  @Override
  public int decide(LoggingEvent event) {
      LocationInfo locationInfo = event.getLocationInformation();
      String location = locationInfo.getFileName() + ":" + locationInfo.getLineNumber();
      String previousMessage = previousMessages.get(location);
      if(previousMessage != null && previousMessage.equals(event.getMessage())){
        return DENY;
      }

      previousMessages.put(location, event.getMessage());
      return ACCEPT;
  }
}

这样,你每秒只需要打60次电话,就是一个简单的
Map#get
,一个
if
比较和一个
MyTimer#setToNow
,为了解决这个问题,在我自制的游戏项目中,我决定只记录“新”消息。我采用了以下方法:

  • 检测日志方法调用“位置”
  • 如果来自此位置的消息与上次更改,请将其记录下来,否则忽略
  • 我无法向您展示我的实际代码,因为它不是在Java上使用的宏,而是通过
    log4j
    Filter
    s实现的:

    Map<Class, MyTimer> logged = new HashMap<>();
    
    import java.util.*;
    import org.apache.log4j.Level;
    import org.apache.log4j.spi.Filter;
    import org.apache.log4j.spi.LoggingEvent;
    import org.apache.log4j.spi.LocationInfo;
    
    public class DuplicateMessagesFilter extends Filter {
      Map<String,String> previousMessages = new HashMap<String,String>();
    
      @Override
      public int decide(LoggingEvent event) {
          LocationInfo locationInfo = event.getLocationInformation();
          String location = locationInfo.getFileName() + ":" + locationInfo.getLineNumber();
          String previousMessage = previousMessages.get(location);
          if(previousMessage != null && previousMessage.equals(event.getMessage())){
            return DENY;
          }
    
          previousMessages.put(location, event.getMessage());
          return ACCEPT;
      }
    }
    
    import java.util.*;
    导入org.apache.log4j.Level;
    导入org.apache.log4j.spi.Filter;
    导入org.apache.log4j.spi.LoggingEvent;
    导入org.apache.log4j.spi.LocationInfo;
    公共类DuplicateMessagesFilter扩展筛选器{
    Map previousMessages=new HashMap();
    @凌驾
    公共int决定(记录事件){
    LocationInfo LocationInfo=event.getLocationInformation();
    字符串位置=locationInfo.getFileName()+“:”+locationInfo.getLineNumber();
    字符串previousMessage=previousMessages.get(位置);
    if(previousMessage!=null&&previousMessage.equals(event.getMessage()){
    拒绝返回;
    }
    previousMessages.put(位置,event.getMessage());
    退货接受;
    }
    }
    
    为什么不创建一个标志?如果是真的,则记录日志并设置为false。谢谢,是的,这可以解决问题,但我希望有一个解决方案,将此逻辑封装在记录器中,而不是在我的应用程序中。通常,这种逻辑不会在记录器中处理,而是在日志适配器中处理。例如,如果您正在记录事件,您可能希望将持久化日志消息的责任推到不在关键代码路径上的某个位置。一旦你做到了这一点,节流或聚合的想法就变得容易多了。对我来说,“异常”这个名字意味着它是罕见的。在我看来,一秒钟发生60次罕见的事情是不可能的。也许你想考虑一下。