Jak zapisywać dzienniki w pliku tekstowym podczas korzystania z java.util.logging.Logger


147

Mam sytuację, w której chcę zapisywać wszystkie utworzone przeze mnie logi do pliku tekstowego.

Używamy interfejsu API java.util.logging.Logger do generowania dzienników.

Próbowałem:

private static Logger logger = Logger.getLogger(className.class.getName());
FileHandler fh;   
fh = new FileHandler("C:/className.log");   
logger.addHandler(fh); 

Ale nadal otrzymuję moje dzienniki tylko na konsoli ...



2
Wiele odpowiedzi sugeruje użycie FileHandler, tak jak pierwotnie próbowałeś to zrobić. Jedna rzecz, o której należy pamiętać (lekcja boleśnie wyciągnięta): FileHandler jest zsynchronizowany . Oznacza to, że w wysoce wielowątkowej aplikacji wszystko, czego potrzebujesz, aby mieć potencjalny zakleszczenie, to przekazanie obiektu do zarejestrowania, którego metoda toString () wywołuje metodę synchronizowaną. Uważaj na FileHandler.
Tim Boudreau

Odpowiedzi:


238

Wypróbuj tę próbkę. Mi to pasuje.

public static void main(String[] args) {  

    Logger logger = Logger.getLogger("MyLog");  
    FileHandler fh;  

    try {  

        // This block configure the logger with handler and formatter  
        fh = new FileHandler("C:/temp/test/MyLogFile.log");  
        logger.addHandler(fh);
        SimpleFormatter formatter = new SimpleFormatter();  
        fh.setFormatter(formatter);  

        // the following statement is used to log any messages  
        logger.info("My first log");  

    } catch (SecurityException e) {  
        e.printStackTrace();  
    } catch (IOException e) {  
        e.printStackTrace();  
    }  

    logger.info("Hi How r u?");  

}

Tworzy dane wyjściowe w MyLogFile.log

Apr 2, 2013 9:57:08 AM testing.MyLogger main  
INFO: My first log  
Apr 2, 2013 9:57:08 AM testing.MyLogger main  
INFO: Hi How r u?

Edytować:

Aby usunąć program obsługi konsoli, użyj

logger.setUseParentHandlers(false);

ponieważ ConsoleHandler jest zarejestrowany w nadrzędnym programie rejestrującym, z którego pochodzą wszystkie programy rejestrujące.


1
To działa dla mnie ... Ale dostaję również logi na konsoli. Jak usunąć stamtąd?
Pankaj

Czy mógłbyś zasugerować mi, co zrobić, jeśli chcę zachować wszystkie dzienniki. Właściwie z tego podejścia mój plik tekstowy jest zastępowany, jeśli uruchomię moją aplikację po raz drugi?
Pankaj

1
Jak to zrobić ... I google, ale znalazłem tyle mylące kod ... Czy mógłbyś proszę o pomoc ..
Pankaj

7
@bluemunch Możesz użyć alternatywnego konstruktora programu, FileHandler(path, true)aby dodać dziennik do istniejącego pliku dziennika.
Sri Harsha Chilakapati

1
@Line Yes. W tym przypadku zwykle używam metody narzędzia Create Logger.
Sri Harsha Chilakapati

16

Po pierwsze, gdzie zdefiniowałeś swój rejestrator i z jakiej klasy \ metody próbujesz go wywołać? Oto działający przykład, świeżo upieczony:

public class LoggingTester {
    private final Logger logger = Logger.getLogger(LoggingTester.class
            .getName());
    private FileHandler fh = null;

    public LoggingTester() {
        //just to make our log file nicer :)
        SimpleDateFormat format = new SimpleDateFormat("M-d_HHmmss");
        try {
            fh = new FileHandler("C:/temp/test/MyLogFile_"
                + format.format(Calendar.getInstance().getTime()) + ".log");
        } catch (Exception e) {
            e.printStackTrace();
        }

        fh.setFormatter(new SimpleFormatter());
        logger.addHandler(fh);
    }

    public void doLogging() {
        logger.info("info msg");
        logger.severe("error message");
        logger.fine("fine message"); //won't show because to high level of logging
    }
}   

W swoim kodzie zapomniałeś zdefiniować formatera, jeśli potrzebujesz prostego możesz to zrobić tak jak wspomniałem powyżej, ale jest inna opcja, możesz to samodzielnie sformatować, jest przykład (po prostu wstaw go zamiast tej linii fh .setFormatter (nowy kod SimpleFormatter ())):

fh.setFormatter(new Formatter() {
            @Override
            public String format(LogRecord record) {
                SimpleDateFormat logTime = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
                Calendar cal = new GregorianCalendar();
                cal.setTimeInMillis(record.getMillis());
                return record.getLevel()
                        + logTime.format(cal.getTime())
                        + " || "
                        + record.getSourceClassName().substring(
                                record.getSourceClassName().lastIndexOf(".")+1,
                                record.getSourceClassName().length())
                        + "."
                        + record.getSourceMethodName()
                        + "() : "
                        + record.getMessage() + "\n";
            }
        });

Lub jakakolwiek inna modyfikacja, jak chcesz. Mam nadzieję, że to pomoże.


9

Lokalizacją pliku dziennika można sterować za pomocą pliku logging.properties. I można to przekazać jako parametr JVM, np .:java -Djava.util.logging.config.file=/scratch/user/config/logging.properties

Szczegóły: https://docs.oracle.com/cd/E23549_01/doc.1111/e14568/handler.htm

Konfigurowanie obsługi plików

Aby wysłać dzienniki do pliku, dodaj FileHandler do właściwości handlers w pliku logging.properties. Umożliwi to globalne rejestrowanie plików.

handlers= java.util.logging.FileHandler Skonfiguruj procedurę obsługi, ustawiając następujące właściwości:

java.util.logging.FileHandler.pattern=<home directory>/logs/oaam.log
java.util.logging.FileHandler.limit=50000
java.util.logging.FileHandler.count=1
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter

java.util.logging.FileHandler.pattern określa położenie i wzorzec pliku wyjściowego. Domyślnym ustawieniem jest Twój katalog domowy.

java.util.logging.FileHandler.limit określa w bajtach maksymalną ilość zapisywaną przez program rejestrujący w dowolnym pliku.

java.util.logging.FileHandler.count określa liczbę plików wyjściowych, które mają być przełączane.

java.util.logging.FileHandler.formatter określa klasę programu formatującego java.util.logging, której klasa obsługi plików używa do formatowania komunikatów dziennika. SimpleFormatter tworzy krótkie, czytelne dla człowieka, podsumowania zapisów dziennika.


Aby poinstruować Javę, aby używała tego pliku konfiguracyjnego zamiast $ JDK_HOME / jre / lib / logging.properties:

java -Djava.util.logging.config.file=/scratch/user/config/logging.properties

Świetna odpowiedź z tego, co widzę, jedyna globalna. Zdecydowałem się przejść do zmiany logging.properties w samym JDK (choć w Javie 11 znajdują się one w katalogu conf z katalogu instalacyjnego Javy). Warto zauważyć, że domyślną lokalizacją takiego pliku logu będzie user.home / javaX.log (gdzie user.home to poręczność systemu, a X to kolejna liczba w kolejności - dla pierwszego będzie to 0).
Linia


5

Może tego potrzebujesz ...

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 * LogToFile class
 * This class is intended to be use with the default logging class of java
 * It save the log in an XML file  and display a friendly message to the user
 * @author Ibrabel <ibrabel@gmail.com>
 */
public class LogToFile {

    protected static final Logger logger=Logger.getLogger("MYLOG");
    /**
     * log Method 
     * enable to log all exceptions to a file and display user message on demand
     * @param ex
     * @param level
     * @param msg 
     */
    public static void log(Exception ex, String level, String msg){

        FileHandler fh = null;
        try {
            fh = new FileHandler("log.xml",true);
            logger.addHandler(fh);
            switch (level) {
                case "severe":
                    logger.log(Level.SEVERE, msg, ex);
                    if(!msg.equals(""))
                        JOptionPane.showMessageDialog(null,msg,
                            "Error", JOptionPane.ERROR_MESSAGE);
                    break;
                case "warning":
                    logger.log(Level.WARNING, msg, ex);
                    if(!msg.equals(""))
                        JOptionPane.showMessageDialog(null,msg,
                            "Warning", JOptionPane.WARNING_MESSAGE);
                    break;
                case "info":
                    logger.log(Level.INFO, msg, ex);
                    if(!msg.equals(""))
                        JOptionPane.showMessageDialog(null,msg,
                            "Info", JOptionPane.INFORMATION_MESSAGE);
                    break;
                case "config":
                    logger.log(Level.CONFIG, msg, ex);
                    break;
                case "fine":
                    logger.log(Level.FINE, msg, ex);
                    break;
                case "finer":
                    logger.log(Level.FINER, msg, ex);
                    break;
                case "finest":
                    logger.log(Level.FINEST, msg, ex);
                    break;
                default:
                    logger.log(Level.CONFIG, msg, ex);
                    break;
            }
        } catch (IOException | SecurityException ex1) {
            logger.log(Level.SEVERE, null, ex1);
        } finally{
            if(fh!=null)fh.close();
        }
    }

    public static void main(String[] args) {

        /*
            Create simple frame for the example
        */
        JFrame myFrame = new JFrame();
        myFrame.setTitle("LogToFileExample");
        myFrame.setSize(300, 100);
        myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        myFrame.setLocationRelativeTo(null);
        JPanel pan = new JPanel();
        JButton severe = new JButton("severe");
        pan.add(severe);
        JButton warning = new JButton("warning");
        pan.add(warning);
        JButton info = new JButton("info");
        pan.add(info);

        /*
            Create an exception on click to use the LogToFile class
        */
        severe.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent ae) {
                int j = 20, i = 0;
                try {
                    System.out.println(j/i);
                } catch (ArithmeticException ex) {
                    log(ex,"severe","You can't divide anything by zero");
                }

            }

        });

        warning.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent ae) {
                int j = 20, i = 0;
                try {
                    System.out.println(j/i);
                } catch (ArithmeticException ex) {
                    log(ex,"warning","You can't divide anything by zero");
                }

            }

        });

        info.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent ae) {
                int j = 20, i = 0;
                try {
                    System.out.println(j/i);
                } catch (ArithmeticException ex) {
                    log(ex,"info","You can't divide anything by zero");
                }

            }

        });

        /*
            Add the JPanel to the JFrame and set the JFrame visible
        */
        myFrame.setContentPane(pan);
        myFrame.setVisible(true);
    }
}

4
import java.io.IOException;
import org.apache.log4j.Appender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;

/**
 * @author Kiran
 * 
 */
public class MyLogger {

    public MyLogger() {
    }

    public static void main(String[] args) {
        Logger logger = Logger.getLogger("MyLog");
        Appender fh = null;
        try {
            fh = new FileAppender(new SimpleLayout(), "MyLogFile.log");
            logger.addAppender(fh);
            fh.setLayout(new SimpleLayout());
            logger.info("My first log");
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        logger.info("Hi How r u?");
    }
}

1
Dzięki, to mi pomogło, ale Log4j 2 wychodzi teraz i musiałem szukać wersji 1.2.
SoluableNonagon

3
int SIZE = "<intialize-here>"
int ROTATIONCOUNT = "<intialize-here>"

Handler handler = new FileHandler("test.log", SIZE, LOG_ROTATIONCOUNT);
logger.addHandler(handler);     // for your code.. 

// you can also set logging levels
Logger.getLogger(this.getClass().getName()).log(Level.[...]).addHandler(handler);

1

Mam nadzieję, że ludzie uznają to za pomocne

public static void writeLog(String info) {
    String filename = "activity.log";
    String FILENAME = "C:\\testing\\" + filename;
    BufferedWriter bw = null;
    FileWriter fw = null;
    try {
        fw = new FileWriter(FILENAME, true);
        bw = new BufferedWriter(fw);
        bw.write(info);
        bw.write("\n");
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (bw != null)
                bw.close();
            if (fw != null)
                fw.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

1
tak, straciłem pół godziny i mój spryt próbował zmusić log4j do zapisu do cholernego pliku. większość narzędzi jest zbyt skomplikowana w stosunku do problemu, który rozwiązują.
Mihai Raulea

0

Oto moja klasa logowania oparta na zaakceptowanej odpowiedzi :

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.*;

public class ErrorLogger
{
    private Logger logger;

    public ErrorLogger()
    {
        logger = Logger.getAnonymousLogger();

        configure();
    }

    private void configure()
    {
        try
        {
            String logsDirectoryFolder = "logs";
            Files.createDirectories(Paths.get(logsDirectoryFolder));
            FileHandler fileHandler = new FileHandler(logsDirectoryFolder + File.separator + getCurrentTimeString() + ".log");
            logger.addHandler(fileHandler);
            SimpleFormatter formatter = new SimpleFormatter();
            fileHandler.setFormatter(formatter);
        } catch (IOException exception)
        {
            exception.printStackTrace();
        }

        addCloseHandlersShutdownHook();
    }

    private void addCloseHandlersShutdownHook()
    {
        Runtime.getRuntime().addShutdownHook(new Thread(() ->
        {
            // Close all handlers to get rid of empty .LCK files
            for (Handler handler : logger.getHandlers())
            {
                handler.close();
            }
        }));
    }

    private String getCurrentTimeString()
    {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        return dateFormat.format(new Date());
    }

    public void log(Exception exception)
    {
        logger.log(Level.SEVERE, "", exception);
    }
}

0

Oto przykład, jak nadpisać konfigurację Loggera z kodu. Nie wymaga zewnętrznego pliku konfiguracyjnego.

FileLoggerTest.java:

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

public class FileLoggerTest {

    public static void main(String[] args) {

        try {
            String h = MyLogHandler.class.getCanonicalName();
            StringBuilder sb = new StringBuilder();
            sb.append(".level=ALL\n");
            sb.append("handlers=").append(h).append('\n');
            LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(sb.toString().getBytes("UTF-8")));
        } catch (IOException | SecurityException ex) {
            // Do something about it
        }

        Logger.getGlobal().severe("Global SEVERE log entry");
        Logger.getLogger(FileLoggerTest.class.getName()).log(Level.SEVERE, "This is a SEVERE log entry");
        Logger.getLogger("SomeName").log(Level.WARNING, "This is a WARNING log entry");
        Logger.getLogger("AnotherName").log(Level.INFO, "This is an INFO log entry");
        Logger.getLogger("SameName").log(Level.CONFIG, "This is an CONFIG log entry");
        Logger.getLogger("SameName").log(Level.FINE, "This is an FINE log entry");
        Logger.getLogger("SameName").log(Level.FINEST, "This is an FINEST log entry");
        Logger.getLogger("SameName").log(Level.FINER, "This is an FINER log entry");
        Logger.getLogger("SameName").log(Level.ALL, "This is an ALL log entry");

    }
}

MyLogHandler.java

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;

public final class MyLogHandler extends FileHandler {

    public MyLogHandler() throws IOException, SecurityException {
        super("/tmp/path-to-log.log");
        setFormatter(new SimpleFormatter());
        setLevel(Level.ALL);
    }

    @Override
    public void publish(LogRecord record) {
        System.out.println("Some additional logic");
        super.publish(record);
    }

}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.