Comme indiqué dans ce lien: Comment créer un propre Appender dans log4j?
Pour créer un appender personnalisé dans log4j 1.x, nous devons étendre la classe AppenderSkeleton et implémenter sa méthode append.
De même, nous pouvons créer un appender personnalisé dans log4j2, car nous n'avons pas de classe AppenderSkelton à étendre et tous les autres appender étendent une classe AppenderBase.
Cela fonctionne assez différemment dans log4j2 que dans log4j-1.2.
Dans log4j2, vous créeriez un plugin pour cela. Le manuel contient une explication avec un exemple pour un appender personnalisé: http://logging.Apache.org/log4j/2.x/manual/extending.html#Appenders
Il peut être pratique d’étendre org.Apache.logging.log4j.core.appender.AbstractAppender
, mais cela n’est pas obligatoire.
Lorsque vous annotez votre classe Appender personnalisée avec @Plugin(name="MyCustomAppender", ....
, le nom du plug-in devient le nom de l'élément de configuration. Ainsi, une configuration avec votre appender personnalisé ressemblerait alors à ceci:
<Configuration packages="com.yourcompany.yourcustomappenderpackage">
<Appenders>
<MyCustomAppender name="ABC" otherAttribute="...">
...
</Appenders>
<Loggers><Root><AppenderRef ref="ABC" /></Root></Loggers>
</Configuration>
Notez que l'attribut packages
de la configuration est une liste séparée par des virgules de tous les packages avec les plugins log4j2 personnalisés. Log4j2 recherchera ces classes dans le chemin de classe pour les classes annotées avec @Plugin.
Voici un exemple d'appender personnalisé qui s'imprime sur la console:
package com.yourcompany.yourcustomappenderpackage;
import Java.io.Serializable;
import Java.util.concurrent.locks.*;
import org.Apache.logging.log4j.core.*;
import org.Apache.logging.log4j.core.config.plugins.*;
import org.Apache.logging.log4j.core.layout.PatternLayout;
// note: class name need not match the @Plugin name.
@Plugin(name="MyCustomAppender", category="Core", elementType="appender", printObject=true)
public final class MyCustomAppenderImpl extends AbstractAppender {
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Lock readLock = rwLock.readLock();
protected MyCustomAppenderImpl(String name, Filter filter,
Layout<? extends Serializable> layout, final boolean ignoreExceptions) {
super(name, filter, layout, ignoreExceptions);
}
// The append method is where the appender does the work.
// Given a log event, you are free to do with it what you want.
// This example demonstrates:
// 1. Concurrency: this method may be called by multiple threads concurrently
// 2. How to use layouts
// 3. Error handling
@Override
public void append(LogEvent event) {
readLock.lock();
try {
final byte[] bytes = getLayout().toByteArray(event);
System.out.write(bytes);
} catch (Exception ex) {
if (!ignoreExceptions()) {
throw new AppenderLoggingException(ex);
}
} finally {
readLock.unlock();
}
}
// Your custom appender needs to declare a factory method
// annotated with `@PluginFactory`. Log4j will parse the configuration
// and call this factory method to construct an appender instance with
// the configured attributes.
@PluginFactory
public static MyCustomAppenderImpl createAppender(
@PluginAttribute("name") String name,
@PluginElement("Layout") Layout<? extends Serializable> layout,
@PluginElement("Filter") final Filter filter,
@PluginAttribute("otherAttribute") String otherAttribute) {
if (name == null) {
LOGGER.error("No name provided for MyCustomAppenderImpl");
return null;
}
if (layout == null) {
layout = PatternLayout.createDefaultLayout();
}
return new MyCustomAppenderImpl(name, filter, layout, true);
}
}
Pour plus de détails sur les plugins: http://logging.Apache.org/log4j/2.x/manual/plugins.html
Si le manuel ne suffit pas, il peut être utile de consulter le code source des ajouts intégrés dans log4j-core.
Il semble que les extensions de plug-ins sont analysées au démarrage et ne peuvent pas être ajoutées lors de l'exécution. Est-ce vrai?
pour ajouter un nouvel appender en cours d’exécution, vous pouvez utiliser la propriété monitorInterval pour mettre à jour la configuration du journal, c'est-à-dire toutes les 60 secondes:
<Configuration monitorInterval="60">
Pour que les utilisateurs aient besoin de sortir vers TextArea, voici un tweak qui fonctionne
Rendre le TextArea statique
NetBeans Swing TextArea n'est pas statique, pose problème
Ajouter une méthode statique dans votre cadre
public class MyFrame extends javax.swing.JFrame {
...
public static void outputToTextArea(String message) {
jTextArea.append(message);
}
Appeler dans l'appendeur
@Override
public void append(LogEvent event) {
final byte[] bytes = getLayout().toByteArray(event);
MyFrame.outputToTextArea(new String(bytes));
}