2017-01-29 3 views
1

Ich schreibe eine App, die log4j 2.5 verwendet und alles hat gut funktioniert. Um die Leistung zu verbessern, wollte ich Logger async machen, wollte aber die Disruptorabhängigkeit nicht hinzufügen, daher entschied ich mich für Async Appenders. Ich fand einige Beispiele, wie man sie benutzt, aber ich schätze, dass etwas schief gegangen ist :(log4j doppelte Nachrichten bei der Verwendung von AsyncAppender

Ich benutze keine XML-Konfigurationsdatei, sondern erstelle stattdessen alle meine Logger im Code. Was ich mache Zuerst erstelle ich meine Appender und hinterher erstelle ich Async Appender für jede von ihnen wo ich ihren Namen referenziere

Erhalte ich doppelte Nachrichten, weil ich für jeden Appender sowohl den Appender selbst als auch einen AsyncAppender habe, der meine Nachrichten sendet zu diesem appender

Mein Code:

addAppenderToLogger(fileAppender, logger) 
addAppenderToLogger(rollingFileAppender, logger) 

AsyncAppender.createAppender(
    names.map(name => AppenderRef.createAppenderRef(
    name, Level.getLevel("INFO"), null 
)), errorRef, true, 0, 2048, s"async-appender", false, null, config, true 
) 

Ich erstelle 1 AsyncAppender für meine beiden Appender.

Beispiel für doppelte Protokolle:

2017-01-26 13: 21: 33.619 [Executor Aufgabenstart Arbeiter-1] INFO Kurztext - Start ID 973376

2017- zu markieren, 01-26 13: 21: 33,619 [Executor Task Start Worker-2] INFO Kurztext - Beginn der Tag-ID 2497995

2017-01-26 13: 21: 33,619 [Executor Aufgabe Start Worker-1] INFO Kurztext - Beginn der Tag ID 973376

2017.01.26 13: 21: 33.619 [Executor Aufgabenstart Arbeiter-2] INFO Kurztext - Start ID 2497995

Antwort

1

markieren Wenn Sie sowohl die FileAppender hinzufügen und die AsyncAppender zu Ihrem Logger direkt, dann wird dies der Flaschenhals und Sie verlieren den Vorteil der asynchronen Protokollierung.

Fügen Sie nur den AsyncAppender zu Ihren Loggern hinzu und lassen Sie den AsyncAppender über einen AppenderRef auf den FileAppender zeigen.


Bei der programmgesteuerten Konfiguration machen einige Log4j2-Tests etwas Ähnliches wie das, was Sie versuchen. Zum Beispiel this one:

final LoggerContext context = LoggerContext.getContext(false); 
final Configuration config = context.getConfiguration(); 
final PatternLayout layout = PatternLayout.createDefaultLayout(config); 
final Appender appender = WriterAppender.createAppender(layout, null, writer, writerName, false, true); 
appender.start(); 
config.addAppender(appender); 

final Level level = null; 
final Filter filter = null; 
for (final LoggerConfig loggerConfig : config.getLoggers().values()) { 
    loggerConfig.addAppender(appender, level, filter); 
} 
config.getRootLogger().addAppender(appender, level, filter); 

Ich hoffe, das ist nützlich.

+0

Was ich vorher gemacht habe, war, die Appender zu erstellen und sie dem Logger hinzuzufügen, danach einen Async Appender mit 'AppenderRefs' zu erstellen und dann die ursprünglichen Appender zu entfernen. Das schien zu funktionieren, aber es ist eine ziemlich hässliche Lösung (Erstellen und Entfernen). Ich habe jetzt versucht, was du getan hast, aber ich bekomme eine NullPointerException. Wo soll ich die Appender erstellen? Im Hauptlogger? Und den AsyncAppender, den ich im Context Logger meiner App erstelle? Da es einfach nicht ausreicht, sie als Variablen zu erstellen, wird eine NullPointerException erstellt. – sid802

+0

Der Stammlogger sollte sich auf den AsyncAppender beziehen und der AsyncAppender sollte auf den FileAppender verweisen. Andere Logger, die vom selben LoggerContext (~ 1 auf 1 mit Anwendung) erhalten wurden, leiten Ereignisse an ihre Parent-Logger (den Root-Logger) weiter. –

+0

Aber wie kann ich meinen AsyncAppender auf den FileAppender verweisen, wenn er nicht in einem Logger/Kontext registriert wurde? Zum Beispiel: val FileAppender = createFileAppender (name) val RollingFileAppender = createRollingFileAppender (Name, folderNameExt) val curLogger = ctx.getLogger (name) addAppenderToLogger (createAsyncAdapter (Array (fileAppender.getName, rollingFileAppender.getName) , fileAppender.getName), curLogger) ctx.getLogger (name) .setLevel (die ganze) führt zu einer Nullpointer weil zur Laufzeit, wird die createAsyncAdapter nicht die mit Beispiel – sid802

Verwandte Themen