Лучшие практики для ведения журнала Java из нескольких потоков? - PullRequest
25 голосов
/ 19 февраля 2009

Я хочу иметь диагностический журнал, который создается несколькими задачами, управляющими данными. Эти задачи могут быть в нескольких потоках. Каждая задача должна записать элемент (возможно, с подэлементами) в журнал; войти и выйти быстро. Если бы это была ситуация с одной задачей, я бы использовал XMLStreamWriter , так как это кажется наилучшим соответствием для простоты / функциональности без необходимости хранить всплывающий XML-документ в памяти.

Но это не единственная задача, и я не уверен, как лучше всего убедиться, что это «потокобезопасный», где «потокобезопасность» в этом приложении означает, что каждый элемент журнала должен записываться в журнал правильно и последовательно (один за другим, без чередования).

Есть предложения? У меня есть смутное представление о том, что нужно использовать очередь элементов журнала (каждый из которых может быть быстро создан: мое приложение занято реальной работой, чувствительной к производительности), и у меня есть отдельный поток, который обрабатывает журнал. элементы и отправляет их в файл, чтобы регистрация не прерывала производителей.

Ведение журнала не обязательно должно быть XML, но я хочу, чтобы оно было структурированным и машиночитаемым.

edit: я помещаю "threadsafe" в кавычки. Log4j кажется очевидным выбором (новым для меня, но старым для сообщества), зачем изобретать велосипед ...

Ответы [ 12 ]

0 голосов
/ 07 ноября 2018

Это старый вопрос, но вот мое решение, использующее Log4J программно.

LogFactory class

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import java.util.Properties;

public class LogFactory {

    private final static ThreadLocal<Logger> logFactory = new ThreadLocal<>();

    public static void createNewLogger(String className) {

        Logger log = Logger.getLogger("Thread" + className);

        Properties props = new Properties();
        props.setProperty("log4j.appender.file", "org.apache.log4j.RollingFileAppender");

        props.setProperty("log4j.appender.file.maxFileSize", "100MB");
        props.setProperty("log4j.appender.file.Append", "false");
        props.setProperty("log4j.", "100MB");
        props.setProperty("log4j.appender.file.maxBackupIndex", "100");
        props.setProperty("log4j.appender.file.File", "logs/" + className + ".log");
        props.setProperty("log4j.appender.file.threshold", "info");
        props.setProperty("log4j.appender.file.layout", "org.apache.log4j.PatternLayout");
        props.setProperty("log4j.appender.file.layout.ConversionPattern", "%d{yyyy-MM-dd HH-mm-ss} | %-5p | %C{1}:%L | %m%n");
        props.setProperty("log4j.appender.stdout", "org.apache.log4j.ConsoleAppender");
        props.setProperty("log4j.appender.stdout.Target", "System.out");
        props.setProperty("log4j.logger." + "Thread" + className, "INFO, file");
        PropertyConfigurator.configure(props);
        logFactory.set(log);
    }

    public static Logger getLogger() {
        return logFactory.get();
    }

}

Затем для инициализации регистратора используйте следующий подход

logFactory.createNewLogger(String.valueOf(Thread.currentThread().getId()));
logFactory.getLogger().info(" TEST . Thread id is: " + id);
0 голосов
/ 19 февраля 2009

Самостоятельно разрабатывать это потокобезопасным способом - это не тривиально, поэтому вам действительно следует использовать существующую среду ведения журналов, которая является поточно-ориентированной. Наиболее часто используемым является Log4J , который является поточно-ориентированным (см. FAQ ).

...