2009-03-25 1 views
2

Meine Anwendung verwendet log4j für die Protokollierung und ich in der Regel durch Überprüfen Sie die Anmeldung, ob ein bestimmtes Niveau aktiviert ist und melden Sie sich dann wie folgt ausLogging Komplexität und die Sorge um Message Leistung

if(Logger.isApplicationDebugEnabled()){ 
    Logger.logApplicationDebug("something"+values); 
} 

das jetzt, wenn Sie sich über unseren Zweigüberdeckung reduziert während jUnit Tests. Um dies zu überwinden, schlug mein Freund vor, "wenn" für die Protokollierung zu überprüfen.

  1. Zuerst einer meiner Freunde schlug vor, das if zu entfernen und direkt zu überprüfen. Das Problem bei diesem Ansatz ist, dass es die Anwendung aufgrund der Bildung von Strings verlangsamen könnte, die ohnehin nicht in den Protokolldateien landen würden.
  2. Der zweite Ansatz, an den ich dachte, war SLF4j sehr ähnlich.

    Logger.debug ("Nummer {0}, mit Datum {1, Datum}", 1234, neues Datum());

Das fühlte sich sehr attraktiv und einfach. (Diese Lösung intern verwendet MessageFormat.format (str, Objekt []) Methode. Aber ich bin besorgt über die Leistung dieses haben könnte. Beachten Sie auch, dass ‚Logger‘ ist mein interne Klasse und in jeder seiner Log-Methoden gibt es eine Überprüfung der Log-Aktivierung. Was meinst du? Ich ging durch Geschwindigkeitsvorlagen, aber es erfordert eine Karte der Parameter.Es gibt eine leichte Lösung, die nur Werte auf Param ersetzt Index Standort oder ist diese Lösung in Ordnung?

+0

Siehe auch http://stackoverflow.com/questions/105852/conditional-logging-with-minimal-cyclomatic-complexity für mögliche Lösungen zur Vermeidung von Args-Evaluierung. Die Antwort von Cletus passt jedoch besser zu Ihrem Fall. – VonC

+0

@Ajay Machen Sie eine Logik, wenn die Protokollierung aktiviert ist, die Sie nicht tun, wenn die Protokollierung ausgeschaltet ist? Wenn nicht, sollte es ausreichen, nur mit aktivierter Protokollierung zu laufen. – Nicolai

+0

@Nicolai. Nee! Ich habe keine Logik in Logging-Anweisungen. Ich benutze cobertura für die Messung von Code/Zweigabdeckung. Das Problem ist, Covertura Branch Berichterstattung erwartet die Junits mit Anmelden und ein weiteres Junit mit Abmelden laufen! – Ajay

Antwort

0

Ich kann die slf4j Fassade für log4j wird dringend empfohlen, die Sie diese Syntax

log.info ("Hallo {} von {}", "Welt", "me")

zu verwenden, ermöglicht die Es wird nur die Zeichenfolgenerweiterung ausgeführt, nachdem entschieden wurde, dass das Ereignis tatsächlich protokolliert werden sollte, sodass Sie den ifEnabled-Wrapper nicht angeben müssen. Verwenden Sie dann log4j als Backend für slf4j.

Zusätzlich hat sich viel schneller als der MessageFormatter gemessen.

+0

Wenn slf4j schneller als MessageFormatter ist, dann sind das gute Nachrichten! Ich werde sicherlich diese Option prüfen. Vielen Dank :) – Ajay

0

Die einzige Möglichkeit zu wissen ist zu messen.Gesundheitsraten sind fast immer falsch :)

Persönlich würde ich wahrscheinlich nur mit Ihrem ursprünglichen log4j-Code bleiben - lassen Sie sich nicht über die Berichterstattung aufhängen. Es ist vernünftig, sich davor zu schützen, zu viele Protokollaufrufe für Codepfade zu machen, die immer befolgt werden - aber ich würde mich nicht für Dinge wie Fehlerbedingungen interessieren, bei denen Sie bereits in einer seltsamen und hoffentlich seltenen Situation sind. Schreibe den Code, der am besten lesbar ist, und stelle sicher, dass deine App so gut funktioniert, wie du es brauchst. Wenn es nicht tut, profilieren Sie es, um herauszufinden, wo das Problem liegt. Wenn im Logging-Code ist, optimieren Sie das.

+0

ernsthaft Ich bin nicht besorgt über die Branchendeckung, da ich weiß, dass Protokollaufrufe nicht zählen. Aber mein Klient stimmt wirklich nicht zu und Sie wissen über QA-Abteilungen! Ich muss Log-Anrufe an den richtigen Orten platzieren :) – Ajay

+0

Wow, du bist Client ist wirklich mehr besorgt über die Filialabdeckung als den am besten geeigneten Code? Unheimlich. –

2

Ok, ich werde die offensichtliche Frage stellen: Warum nicht einfach Debug-Logging aktivieren - oder alle Ebenen wirklich - während Sie Ihre Komponententests ausführen? Dies hat den Vorteil, Code Coverage-Tests zu erhöhen UND auf Probleme bei der Protokollierung zu testen (was alles andere als unmöglich ist).

Die Überprüfung, ob die Protokollierung aktiviert ist, gibt es aus einem bestimmten Grund: Es kann teuer sein (innerhalb großer Schleifen), nicht nur die endgültige Protokollfolge zu konstruieren, sondern auch die einzelnen Parameter selbst zu konstruieren. Mit MessageFormat oder java.util.Formatter oder was auch immer wird das zweite Problem nicht los. Ich würde Sie wirklich ermutigen, den Scheck zu behalten.

+1

+1 auf Fehler im Protokollierungscode. Ich habe bei der Erstellung einer Zeichenfolge mehr als den Anteil an Nullzeigern gesehen –

+0

Beim Ausführen von Junits habe ich die Protokollierung auf allen Ebenen aktiviert. 1. Das Problem liegt in der Filialabdeckung. Ich muss alle junits mit log4j aktiviert und wieder mit log4j deaktiviert. 2. Ich mache eine if-Prüfung in meiner Logger-Klasse und dann nur Format aufrufen. – Ajay

+1

Das Ausführen von Komponententests mit und ohne Protokollierung ist trotzdem eine gute Idee. Wie Mario sagt: Protokolle können Null-Zeiger-Ausnahmen und so weiter verursachen. – cletus

2

Ich habe tatsächlich getan, was Sie an einem Projekt vorschlagen, und ich habe positive Erfahrungen mit diesem Ansatz. Ich habe eine zusätzliche Ebene über commons-logging erstellt, die die Nachrichtenformatierung mit MessageFormat unter der Haube erlaubt.

Dies sind die Ergebnisse, die ich erhalten, nachdem so ziemlich das gleiche Nutzungsmuster Messung beschreiben Sie, 10000 Anrufungen von so etwas wie:

 
    for (int i = 0; i < 10000; i ++) { 
     log.debug("Example message: {0} from {1} at {2}!", i, "test", new Date()); 
    } 

  1. mit Protokollierung auf: commons-logging = 664ms, SLF4J = 559ms, MyLog = 3134ms
  2. mit abzumelden: commons-logging = 6 ms, SLF4J = 7 ms, MyLog = 7ms

Offensichtlich "MyLog" war wesentlich langsamer mit Debugging-Ausgabe eingeschaltet, aber mit ihnen beim Debuggen aus wenn sie aus ist. Nur um klar zu stellen, in "MyLog", ich überprüfe explizit für isDebugEnabled() vor dem eigentlichen Formatieren der Nachricht.

Der resultierende Logging-Code ist nun jedoch viel übersichtlicher und unser gesamtes Team produziert viel nützlichere und detailliertere Nachrichten. Zuvor war es nicht ungewöhnlich, separate Methoden zum Erstellen längerer Logger-Nachrichten zu verwenden.

Angesichts der Tatsache, dass es praktisch keine zusätzlichen Leistungseinbußen gibt, wenn die Protokollierung ausgeschaltet ist, kann ich mich selbst sehen, wie ich diese Technik in Zukunft verwende.