Как писать логи в текстовом файле при использовании java.util.logging.Logger

147

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

Мы используем java.util.logging.Logger API для генерации логов.

Я попытался:

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.
Тим Будро

Ответы:

239

Попробуйте этот образец. Меня устраивает.

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, но я нашел так много запутанного кода ... Не могли бы вы помочь ..
Pankaj
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";
            }
        });

Или любая другая модификация, как вам нравится. Надеюсь, поможет.

DenisD
источник
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, но он должен быть настроен на уровне проекта
Pini Cheyni
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);
    }
}
Ibrabel
источник
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?");
    }
}
kanaparthikiran
источник
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);
AurA
источник
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);
    }
}
BullyWiiPlaza
источник
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);
    }

}
Андрей Красный
источник