2017-08-08 1 views
2

Dans le développement de jeu, de nombreuses méthodes sont appelées très souvent (par exemple 60 fois par seconde). Parfois, je voudrais enregistrer les exceptions captées, même dans de telles méthodes, mais pas si souvent. Mon idée était de consigner seulement la première occurrence d'une exception qui s'est produite dans une méthode spécifique mais je n'ai trouvé aucune solution pratique ou intégrée pour le faire (au moins dans Java).Pratique de journalisation pour les méthodes fréquemment appelées

+0

Pourquoi trouvez-vous pas seulement créer un drapeau? Si c'est vrai, vous vous connectez et définissez à false. – Nathan

+0

Merci, oui cela ferait l'affaire mais j'espérais une solution où cette logique est encapsulée dans l'enregistreur et non dans mon application. – Sebastian

+0

En général, ce type de logique ne serait pas géré dans l'enregistreur, mais un adaptateur de journalisation. Par exemple, si vous consignez des événements, vous voudrez sans doute repousser la responsabilité de * persister * le msg du journal vers quelque chose qui ne se trouve pas sur un chemin de code critique. Une fois que vous avez fait cela, l'idée d'étrangler ou d'agréger devient beaucoup plus facile. –

Répondre

1

Sauf si vous utilisez un enregistreur spécifique qui prend en charge cette fonctionnalité, le comportement que vous essayez d'obtenir peut être obtenu via un système de drapeau.

Par exemple, vous pouvez ajouter dans votre classe d'enregistrement d'une carte comme celle-ci:

Map<Class, MyTimer> logged = new HashMap<>(); 

Et dans votre fonction de journalisation (disons log(Object objectToLog)):

if (objectToLog instanceof Exception) { 
    MyTimer t = logged.get(objectToLog.class); 
    if (t == null || t.getDifferenceTimeWithNow() > MYLOG.DELAY) { 
     log(objectToLog); 
     logged.put(objectToLog.class, t.setToNow()); 
    } 
    else { 
     t.setToNow(); 
    } 
} 

De cette façon, le seul appel vous devez faire soixante fois par seconde est un Map#get simple, une comparaison if et un MyTimer#setToNow.

1

Pour résoudre ce problème dans mon projet de jeu fait maison, j'ai décidé de ne consigner que les «nouveaux» messages. J'ai utilisé l'approche suivante:

  1. Détecter l'appel de méthode de journal "location".
  2. Si le message de cet emplacement a changé depuis la dernière fois, consignez-le, ignorez autrement.

Je ne peux pas vous montrer mon code réel, car il n'a pas été sur Java et macros utilisées, mais avec log4jFilter s il peut être atteint comme ceci:

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; 
    } 
}