web-dev-qa-db-fra.com

Comment créer mon propre Appender dans log4j?

Je suis nouveau dans log4j. Quelqu'un peut-il expliquer comment créer mon propre Appender? c'est-à-dire comment implémenter les classes et les interfaces et comment les remplacer?

52
unknown

Vous devez étendre la classe AppenderSkeleton, qui (en citant javadoc) "fournit le code des fonctionnalités courantes, telles que la prise en charge du filtrage par seuil et la prise en charge des filtres généraux".

Si vous lisez le code d'AppenderSkeleton, vous verrez qu'il gère presque tout, vous laissant juste:

  1. append vide protégé (événement LoggingEvent)
  2. public void close ()
  3. public booléen requiresLayout ()

La méthode principale est append. N'oubliez pas que vous n'avez pas besoin d'implémenter la logique de filtrage car elle est déjà implémentée dans doAppend qui à son tour appelle append. Ici, j'ai créé une classe (tout à fait inutile) qui stocke les entrées de journal dans une liste de tableaux, tout comme une démo.

public /*static*/ class MyAppender extends AppenderSkeleton {
    ArrayList<LoggingEvent> eventsList = new ArrayList();

    @Override
    protected void append(LoggingEvent event) {
        eventsList.add(event);
    }

    public void close() {
    }

    public boolean requiresLayout() {
        return false;
    }

}

Ok, testons-le:

public static void main (String [] args) {

    Logger l = Logger.getLogger("test");

    MyAppender app = new MyAppender();

    l.addAppender(app);

    l.warn("first");
    l.warn("second");
    l.warn("third");

    l.trace("fourth shouldn't be printed");

    for (LoggingEvent le: app.eventsList) {
        System.out.println("***" + le.getMessage());
    }
} 

Vous devriez avoir "premier", "deuxième", "troisième" imprimé; le quatrième message ne doit pas être imprimé car le niveau de journalisation de l'enregistreur racine est débogage tandis que le niveau d'événement est trace. Cela prouve que AbstractSkeleton implémente correctement la "gestion des niveaux" pour nous. Donc, cela semble définitivement la voie à suivre ... maintenant la question: pourquoi avez-vous besoin d'un appender personnalisé alors qu'il existe de nombreux journaux intégrés dans presque toutes les destinations? (btw un bon endroit pour commencer avec log4j: http://logging.Apache.org/log4j/1.2/manual.html )

72
AgostinoX

Si vous souhaitez faire des manipulations ou des décisions, vous pouvez le faire comme ceci:

@Override
protected void append(LoggingEvent event) {
        String message = null;
        if(event.locationInformationExists()){
            StringBuilder formatedMessage = new StringBuilder();
            formatedMessage.append(event.getLocationInformation().getClassName());
            formatedMessage.append(".");
            formatedMessage.append(event.getLocationInformation().getMethodName());
            formatedMessage.append(":");
            formatedMessage.append(event.getLocationInformation().getLineNumber());
            formatedMessage.append(" - ");
            formatedMessage.append(event.getMessage().toString());
            message = formatedMessage.toString();
        }else{
            message = event.getMessage().toString();
        }

        switch(event.getLevel().toInt()){
        case Level.INFO_INT:
            //your decision
            break;
        case Level.DEBUG_INT: 
            //your decision
            break;
        case Level.ERROR_INT:
            //your decision
            break;
        case Level.WARN_INT:
            //your decision
            break;
        case Level.TRACE_INT:
            //your decision
            break;
        default:
            //your decision
            break;
        }
}
6
Lior

Je voudrais dépenser la réponse @AgostinoX pour prendre en charge la configuration de fichiers pro et la possibilité de démarrer et d'arrêter la capture de journalisation:

public class StringBufferAppender extends org.Apache.log4j.AppenderSkeleton {

    StringBuffer logs = new StringBuffer();
    AtomicBoolean captureMode = new AtomicBoolean(false);

    public void close() {
        // TODO Auto-generated method stub

    }

    public boolean requiresLayout() {
        // TODO Auto-generated method stub
        return false;
    }


    @Override
    protected void append(LoggingEvent event) {
        if(captureMode.get())
            logs.append(event.getMessage());
    }

    public void start()
    {
        //System.out.println("[StringBufferAppender|start] - Start capturing logs");
        StringBuffer logs = new StringBuffer();
        captureMode.set(true);
    }

    public StringBuffer stop()
    {
        //System.out.println("[StringBufferAppender|start] - Stop capturing logs");
        captureMode.set(false);
        StringBuffer data = new StringBuffer(logs);
        logs = null;
        return data;
    }


}

Il ne vous reste plus qu'à définir dans le fichier log4j.property

log4j.rootLogger=...., myAppender  # here you adding your appendr name
log4j.appender.myAppender=com.roi.log.StringBufferAppender # pointing it to the implementation

que quand vous voulez l'activer pendant le runtume:

Logger logger = Logger.getRootLogger();
        StringBufferAppender appender = (StringBufferAppender)logger.getAppender("myAppender");
        appender.start();

et tout en voulant l'arrêter:

StringBuffer sb = appender.stop();
2
USer22999299

Pour créer un propre Appender, il vous suffit d'implémenter l'interface Appender et de la remplacer. Et étudiez également ce début de lien log

2
Aabi