Implementieren der Protokollierung in einer Java-Anwendung

Haftungsausschluss: ich entschuldige mich, dass diese Frage so lange. Ich habe den code wie ich erforscht haben, Vorschläge, die hier gemacht und getan, weitere Forschung, da fragte meine ursprüngliche Frage.

Ich arbeite an einem open-source-Projekt in Java implementieren wollen, um die Protokollierung in meiner Anwendung zu erleichtern, bug-tracking und Debuggen, wenn/falls Benutzer melden Probleme mit der app. Ich bin auf der Suche den java.util.logging-Paket aus dem standard-Java-API. Ich habe bereits einige zusätzliche logging-code, wenn Ausnahmen gefangen werden. Ich habe zum Beispiel

Logger.getLogger(FindCardsPanel.class.getName()).log(Level.SEVERE, "Storage I/O error", ex);

Der einzige Unterschied in den einzelnen code-Zeile ist der name der Klasse und die message-Zeichenfolge.

Habe ich gelesen, dass der richtige Weg, um einen logger zu verwenden ist mit einem für jede Klasse namens string. Das macht ein wenig Sinn, denn es ermöglicht viel Flexibilität bei der Filterung von log-Meldungen.

Mein Aktuelles problem ist, dass alle Meldungen gehen derzeit stderr. Ich brauche, um Ihnen zu schreiben in eine Datei statt. Ich habe mit der FileHandler-Klasse, die dies fördern. Aber da habe ich Dutzende von Klassen, ich habe Dutzende von logger-Namen. Muss ich hinzufügen, den FileHandler zu jedem dieser? Das scheint, wie es wird eine Menge Arbeit, vor allem, wenn ich entscheiden, zu hinzufügen, eine andere Klasse zu meinem code-Basis.

Ich verstehe, dass es ist eine Art von Baum-Hierarchie von Loggern. Geschieht das automatisch? Wenn nicht, wie erstelle ich meine eigene Hierarchie? Und ob oder ob nicht es ist die automatische, wo in der Hierarchie-füge ich meine FileHandler, so dass alle logging geht in die gleiche Datei?

Edit:

Basierend auf den angegebenen link von @spdaley, ich habe das folgende SSCCE:

LoggingSSCCE.java:

package loggingsscce;

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;

public class LoggingSSCCE {
    private static String LOG_FILE_NAME = "loggingsscce.log";

    public static void main(String[] args) throws IOException {
        LoggingSSCCE.initLogger();

        LogTest lta = new LogTestA();
        lta.doLog();

        LogTest ltb = new LogTestB();
        ltb.doLog();
    }

    private static void initLogger() throws IOException {
        FileHandler handler = null;

        try {
            boolean append = true;
            handler = new FileHandler(LoggingSSCCE.LOG_FILE_NAME, append);
            handler.setFormatter(new SimpleFormatter());

            Logger logger = Logger.getLogger("");
            logger.setLevel(Level.ALL);
            logger.addHandler(handler);
        } finally {
            handler.close();
        }
    }
}

LogTest.java:

package loggingsscce;

interface LogTest {
    public void doLog();
}

LogTestA.java:

package loggingsscce;

import java.util.logging.Level;
import java.util.logging.Logger;

class LogTestA implements LogTest {
    @Override
    public void doLog() {
        Logger.getLogger(LogTestA.class.getName()).log(Level.INFO, "LogTestA.doLog()");
    }
}

LogTestB.java:

package loggingsscce;

import java.util.logging.Level;
import java.util.logging.Logger;

class LogTestB implements LogTest {
    @Override
    public void doLog() {
        Logger.getLogger(LogTestA.class.getName()).log(Level.INFO, "LogTestB.doLog()");
    }
}

Wenn ich dieses in NetBeans, das output-Fenster zeigt

run:
Sep 09, 2012 5:36:56 PM loggingsscce.LogTestA doLog
INFO: LogTestA.doLog()
Sep 09, 2012 5:36:56 PM loggingsscce.LogTestB doLog
INFO: LogTestB.doLog()
BUILD SUCCESSFUL (total time: 0 seconds)

aber die "loggingsscce.log" - Datei ist leer.

So was bin ich?

Noch ein edit:

Fand ich ein Beispiel, bei http://onjava.com/pub/a/onjava/2002/06/19/log.html?page=2 die ich geändert:

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.LogManager;
import java.util.logging.SimpleFormatter;

public class HelloWorld {
  private static Logger theLogger = Logger.getLogger(HelloWorld.class.getName());

  public static void main( String[] args ) throws IOException {
    Logger rootLogger = Logger.getLogger("");
    Handler handler = new FileHandler("hello.log");

    handler.setFormatter(new SimpleFormatter());
    rootLogger.addHandler(handler);

    //The root logger's handlers default to INFO. We have to
    //crank them up. We could crank up only some of them
    //if we wanted, but we will turn them all up.
    Handler[] handlers = Logger.getLogger( "" ).getHandlers();
    for ( int index = 0; index < handlers.length; index++ ) {
      handlers[index].setLevel( Level.FINE );
    }

    //We also have to set our logger to log finer-grained
    //messages
    theLogger.setLevel(Level.FINE);
    HelloWorld hello = new HelloWorld("Hello world!");
    hello.sayHello();
  }

  private String theMessage;

  public HelloWorld(String message) {
    theMessage = message;
  }

  public void sayHello() {
    theLogger.fine("Hello logging!");
    System.err.println(theMessage);
  }
}

Diese erzeugt die folgende Ausgabe von der Kommandozeile:

lib_lab_ref08@LBP-REF87XVMDP1 /e/devel/src/java/stackoverflow
$ javac HelloWorld.java

lib_lab_ref08@LBP-REF87XVMDP1 /e/devel/src/java/stackoverflow
$ java HelloWorld
Sep 09, 2012 6:13:33 PM HelloWorld sayHello
FINE: Hello logging!
Hello world!

lib_lab_ref08@LBP-REF87XVMDP1 /e/devel/src/java/stackoverflow
$ cat hello.log
Sep 09, 2012 6:13:33 PM HelloWorld sayHello
FINE: Hello logging!

lib_lab_ref08@LBP-REF87XVMDP1 /e/devel/src/java/stackoverflow
$

Also diese einzelne Klasse Beispiel funktioniert Prima. Was ist der Unterschied, wenn ich mehrere Klassen in mehrere Dateien, wie in meinem vorherigen code?

Änderungen LoggingSSCCE Klasse:

Habe ich ein statisches Feld:

private static FileHandler HANDLER = null;

Verändert und die initLogger() Methode:

private static void initLogger() throws IOException {
    LoggingSSCCE.HANDLER = new FileHandler(LoggingSSCCE.LOG_FILE_NAME);
    LoggingSSCCE.HANDLER.setFormatter(new SimpleFormatter());

    Logger logger = Logger.getLogger("");
    logger.setLevel(Level.ALL);
    logger.addHandler(LoggingSSCCE.HANDLER);
}

Dies funktioniert mit dem folgenden Inhalt "loggingsscce.log":

Sep 09, 2012 6:50:16 PM loggingsscce.LogTestA doLog
INFO: LogTestA.doLog()
Sep 09, 2012 6:50:16 PM loggingsscce.LogTestB doLog
INFO: LogTestB.doLog()

Ich bin immer noch Schwierigkeiten haben, die diese arbeiten alle in mein komplizierter Swing-Projekt. Ich vermute, dass mein FileHandler wird geschlossen, vielleicht durch den garbage collector?

Klingt wie Sie ' re suchen für eine logging-Bibliothek wie log4j.
Klingt wie Sie versuchen, zu verwenden standard-Java-Protokollierung anstelle von log4j. Ich würde check out Wie man java-Logger in eine Datei ausgegeben werden standardmäßig und sehen, ob das Ihre Frage beantwortet.
Danke für den link. Diese Frage ist genau das, was ich versuche zu tun. Leider ist die Antwort nicht für mich arbeiten. Ich habe geschrieben ein SSCCE zu illustrieren.

InformationsquelleAutor Code-Apprentice | 2012-09-09

Schreibe einen Kommentar