Определите файл, используемый FileHandler - PullRequest
6 голосов
/ 12 июля 2009

Я создаю java.util.logging.FileHandler, которому разрешено циклически перебирать файлы. Когда запускается несколько экземпляров моего приложения, для каждого экземпляра приложения создается новый файл журнала. Мне нужно знать, какой файл используется приложением, потому что я хочу загрузить файл журнала на свои серверы для дальнейшего просмотра. Как я могу сказать, какой файл используется определенным FileHandler?

Ответы [ 4 ]

2 голосов
/ 12 июля 2009

Самый простой способ - это ввести какой-то идентификатор в само имя файла, то есть аргумент pattern при создании FileHandler. Поскольку это экземпляры одного и того же приложения, один из способов их различения - по их идентификатору процесса, поэтому вы можете сделать эту часть шаблона. Лучший подход - передать идентификатор через командную строку и использовать его для создания имени файла. Таким образом, вы управляете файлами, создаваемыми в некотором смысле. Наконец, если ваше приложение знает, почему оно отличается от всех остальных, например, оно подключается к определенному серверу базы данных, тогда вы можете просто использовать это имя сервера базы данных как часть имени файла.

РЕДАКТИРОВАТЬ: Кажется, нет никакого API, чтобы получить имя файла, используемого FileHandler. Я бы посоветовал изучить расширения журналирования в x4juli (который портирует большую часть функциональности log4j на спецификации java.util.logging):

Вы должны иметь возможность заменить экземпляр их FileHandler, который предоставляет метод getFile ():

1 голос
/ 27 июня 2012

На самом деле, вы можете сделать это намного проще, просто расширив FileHandler самостоятельно. Например ...

MyFileHandler.java:

import java.io.IOException;
import java.util.logging.FileHandler;
public class MyFileHandler extends FileHandler {
    protected String _MyFileHandler_Patern;
    public MyFileHandler(String pattern) throws IOException {
        _MyFileHandler_Patern = pattern;
    }
    public String getMyFileHandlerPattern() {
        return _MyFileHandler_Patern;
    }
}

DeleteMe.java:

import java.io.IOException;
import java.util.logging.Handler;
import java.util.logging.Logger;
public class DeleteMe {
    public static void main(String[] args) throws IOException {
        Logger log = Logger.getLogger(DeleteMe.class.getName());
        MyFileHandler output = new MyFileHandler("output.log");
        log.addHandler(output);
        for (Handler handler : log.getHandlers()) {
            if (handler instanceof MyFileHandler) {
                MyFileHandler x = (MyFileHandler) handler;
                if ("output.log".equals(x.getMyFileHandlerPattern())) {
                    System.out.println("found hanlder writing to output.log");
                }
            }
        }
    }
}
0 голосов
/ 21 июля 2015

Вот мой довольно хакерский способ обойти это. Он работает по умолчанию, если вы не используете строки формата, и должен работать, если вы используете строки формата g и u в имени файла, но не в других.

public class FriendlyFileHandler extends FileHandler {

    /***
     * In order to ensure the most recent log file is the file this one owns,
     * we flush before checking the directory for most recent file.
     * 
     * But we must keep other log handlers from flushing in between and making
     * a NEW recent file.
     */
    private static Object[] flushLock = new Object[0];

    private String pattern;

    public FriendlyFileHandler(String pattern, int maxLogLengthInBytes, int count) throws IOException,
            SecurityException {
        super(pattern, maxLogLengthInBytes, count);

        this.pattern = pattern;
    }

    /***
     * Finds the most recent log file matching the pattern.
     * This is just a guess - if you have a complicated pattern 
     * format it may not work.
     * 
     * IMPORTANT: This log file is still in use. You must 
     * removeHandler() on the logger first, .close() this handler, 
     * then add a NEW handler to your logger. THEN, you can read 
     * the file. 
     * 
     * Currently supported format strings: g, u
     * 
     * @return A File of the current log file, or null on error.
     */
    public synchronized File getCurrentLogFile() {

        synchronized(flushLock) {

            // so the file has the most recent date on it.
            flush();


            final String patternRegex =
                    // handle incremental number formats
                    pattern.replaceAll("%[gu]", "\\d*") +
                    // handle default case where %g is appended to end
                    "(\\.\\d*)?$";

            final Pattern re = Pattern.compile(patternRegex);
            final Matcher matcher = re.matcher("");

            // check all files in the directory where this log would be
            final File basedir = new File(pattern).getParentFile();
            final File[] logs = basedir.listFiles(new FileFilter() {

                @Override
                public boolean accept(final File pathname) {
                    // only get files that are part of the pattern
                    matcher.reset(pathname.getAbsolutePath());

                    return matcher.find();
                }

            });

            return findMostRecentLog(logs);
        }
    }

    private File findMostRecentLog(File[] logs) {

        if (logs.length > 0) {
            long mostRecentDate = 0;
            int mostRecentIdx = 0;

            for (int i = 0; i < logs.length; i++) {
                final long d = logs[i].lastModified();

                if (d >= mostRecentDate) {
                    mostRecentDate = d;
                    mostRecentIdx = i;
                }

            }

            return logs[mostRecentIdx];
        }
        else {
            return null;
        }

    }


    @Override
    public synchronized void flush() {

        // only let one Handler flush at a time.
        synchronized(flushLock) {
            super.flush();
        }
    }

}
0 голосов
/ 20 мая 2011

ОК, я должен сказать, что FileHandler, не предоставляющий способ определить файл журнала, серьезно тупой.

Я закончил написание функции с именем "chooseFile ()", которая ищет / tmp для следующего доступного имени файла журнала и возвращает этот файл. Затем вы можете передать имя этого файла в новый FileHandler ().

/**
 * Utility: select a log file.  File is created immediately to reserve
 * its name.
 */
static public File chooseFile(final String basename) throws IOException {
    final int nameLen = basename.length();
    File tmpDir = new File(System.getProperty("java.io.tmpdir"));
    String[] logs = tmpDir.list(new FilenameFilter() {
        public boolean accept(File d, String f) { 
            return f.startsWith(basename);
        }
    });
    int count = 0;
    if (logs.length > 0) {
        for (String name : logs) {
            int n = atoi(name.substring(nameLen));
            if (n >= count) count = n + 1;
        }
    }
    String filename = String.format("%s%d.log", basename, count); 
    File logFile = new File(tmpDir, filename);
    logFile.createNewFile();
    return logFile;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...