Як писати журнали в текстовий файл при використанні java.util.logging.Logger


147

У мене ситуація, коли я хочу записати всі створені мною журнали в текстовий файл.

Ми використовуємо API java.util.logging.Logger для створення журналів.

Я намагався:

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

Але все одно отримую мої журнали лише на консолі….



2
Ряд відповідей пропонує використовувати FileHandler, як ви спочатку намагалися зробити. Одне, що слід пам’ятати (урок болісно вивчений): FileHandler синхронізований . Це означає, що у сильно багатопотоковому додатку все, що вам потрібно мати потенційний тупик, - це передати об'єкт для реєстрації, метод toString () викликає синхронізований метод. Остерігайтеся FileHandler.
Тім Будро

Відповіді:


238

Спробуйте цей зразок. Це працює для мене.

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?");  

}

Здійснює вихід на 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?

Редагувати:

Щоб видалити обробник консолі, використовуйте

logger.setUseParentHandlers(false);

оскільки ConsoleHandler зареєстрований у батьківському реєстраторі, з якого виходять усі реєстратори.


1
Це працює для мене ... Але я теж отримую журнали на консолі. Як видалити звідти?
Панкай

Підкажіть, будь ласка, що мені робити, якщо я хочу зберігати всі журнали. Насправді з цього підходу мій текстовий файл замінюється, якщо я запускаю заявку вдруге?
Панкай

1
Як це зробити ... Я google це, але я знайшов стільки заплутаного коду ... Не могли б ви допомогти ..
Панкай

7
@bluemunch Ви можете використовувати альтернативний конструктор, FileHandler(path, true)щоб журнал додав до існуючого файлу журналу.
Шрі Харша Чілакапаті

1
@Line Так. У цьому випадку я зазвичай зберігаю утиліту створення журналу створення журналу.
Шрі Харша Чілакапаті

16

По-перше, де ви визначили свій реєстратор і з якого класу \ метод намагаєтесь його викликати? Є робочий приклад, свіжоспечений:

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
    }
}   

У своєму коді ви забули визначити формат, якщо вам потрібен простий, ви можете зробити це, як я вже згадував вище, але є інший варіант, ви можете відформатувати його самостійно, є приклад (просто вставте його замість цього рядка fh .setFormatter (новий 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";
            }
        });

Або будь-яка інша модифікація, що завгодно. Сподіваюся, це допомагає.


9

Розташування файлу журналу можна керувати через файл logging.properties. І може передаватися як параметр JVM ex:java -Djava.util.logging.config.file=/scratch/user/config/logging.properties

Детальніше: https://docs.oracle.com/cd/E23549_01/doc.1111/e14568/handler.htm

Налаштування обробника файлів

Щоб надіслати журнали до файлу, додайте FileHandler до властивості обробників у файл logging.properties. Це дозволить вести журнал файлів у всьому світі.

handlers= java.util.logging.FileHandler Налаштуйте обробник, встановивши наступні властивості:

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 вказує розташування та візерунок вихідного файлу. За замовчуванням встановлено ваш домашній каталог.

java.util.logging.FileHandler.limit вказує в байтах максимальну кількість, яку записує реєстратор у будь-який один файл.

java.util.logging.FileHandler.count визначає, скільки вихідних файлів переходити через цикл.

java.util.logging.FileHandler.formatter визначає клас форматора java.util.logging, який використовує клас обробника файлів для форматування повідомлень журналу. SimpleFormatter пише короткі "читабельні для людини" підсумки журналів записів.


Щоб доручити java використовувати цей файл конфігурації замість $ JDK_HOME / jre / lib / logging.properties:

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

Чудова відповідь, з того, що я бачу, єдиний глобальний. Я вирішив перейти зі зміною logging.properties в самому JDK (хоча в Java 11 вони розташовані в каталозі conf з каталогу встановлення Java). Варто зазначити, що таким файлом журналу за замовчуванням буде user.home / javaX.log (де user.home - це власність системи, а X - наступний номер у порядку - для першого він буде 0).
Рядок

5

Хороша бібліотека з іменем log4j для Java .
Це забезпечить численні функції. Перейдіть за посиланням, і ви знайдете своє рішення.


Уже є log4j2, але його потрібно налаштувати на рівні проекту
Піні Чейні

5

Можливо, це те, що вам потрібно ...

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
Дякую, це мені допомогло, але Log4j 2 виходить зараз, і мені довелося ловити ринок по сайту, щоб знайти версію 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

Сподіваюсь, люди вважають це корисним

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
так, втратили півгодини, і моя дотепність намагається змусити log4j писати у вигаданий файл. Більшість інструментів занадто складні для вирішення проблеми, яку вони вирішують.
Михай Раулія

0

Ось мій клас журналу на основі прийнятої відповіді :

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

Ось приклад того, як замінити конфігурацію Logger з коду. Не потрібен зовнішній файл конфігурації ..

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);
    }

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.