Буферизованные регистраторы (Java) - PullRequest
4 голосов
/ 17 ноября 2011

Мне нравится идея создания системы журналирования, которая помещает операторы журнала во внутренний буфер до тех пор, пока он не достигнет заранее определенной емкости, а затем сбрасывает (сбрасывает) весь буфер сразу.

Это потому, что мне нравится разбрасывать множество операторов TRACE по всем моим методам (чтобы я мог видеть, что происходит через каждые несколько строк; облегчает отладку, по крайней мере, для меня).И я боюсь, что из-за (потенциально) сотен / тысяч операторов журнала, запускаемых повсеместно, столь высокий спрос на ввод-вывод может затормозить мои программы.

«Буферизованное» решение для ведения журнала может облегчить это.

Три вопроса:

  1. Уже существует что-то подобное?Ненавижу изобретать колесо здесь, но онлайн-поиск ничего не дал.
  2. Я думал о том, что могу очень легко потерять операторы журнала, когда программа неожиданно останавливается (исключения во время выполнения и т. Д.), Ирегистратор не был сброшен.В этом случае я бы хотел, чтобы регистратор переопределил finalize (), чтобы, если программа завершает работу с элементами, все еще находящимися в своем буфере, она могла очистить (опубликовать) их перед выходом.Мысли?
  3. Это ужасная идея?Если так, то почему!

Ответы [ 6 ]

5 голосов
/ 17 ноября 2011

Не изобретайте это колесо, если вы можете его избежать.Посмотрите на Log4j или лучше slf4j .

Log4j и slf4j очень эффективны, если вы не отслеживаете, поэтому в производственной системе вы можете уменьшить уровеньведения журнала и все еще имеют хорошую производительность.

Оба log4j и slf4j записывают немедленно в файлы журнала и сбрасывают, не делайте буферизацию по умолчанию, по очень хорошей причине, что вы хотите видеть в файле журнала исключение, котороевызвал ваш крах.Если вы действительно хотите добавить буферизацию, вы можете сделать это ( FileAppender # bufferedIO * )

Что касается finalize (), то он не гарантированно вызывается при выходе.С System # runFinalizersOnExit .

устарело.Этот метод небезопасен.Это может привести к вызову финализаторов для живых объектов, в то время как другие потоки одновременно манипулируют этими объектами, что приводит к ошибочному поведению или тупику.Включить или отключить финализацию при выходе;это означает, что финализаторы всех объектов, которые имеют финализаторы, которые еще не были вызваны автоматически, должны быть запущены до выхода из среды выполнения Java. По умолчанию финализация при выходе отключена .

Мой акцент.Таким образом, нет, похоже, что у буферизованного регистратора были бы врожденные проблемы.

2 голосов
/ 17 ноября 2011

Я засвидетельствую третий вопрос, который вы задали. Это ужасная идея, и она не имеет ничего общего с вашим умением программиста. Он имеет отношение к числу сценариев, которым подвергались такие проекты, как log4j, и различным граничным случаям, которые они учитывали. Я думаю, что это мероприятие довольно большое для вас и вызовет много головных болей в будущем.

1 голос
/ 17 ноября 2011

Log4J уже поддерживает буферизацию ввода-вывода. Несколько хороших советов по производительности на Log4J здесь

0 голосов
/ 18 ноября 2011

Как уже упоминалось - не изобретайте велосипед заново - используйте log4j или, что еще лучше, logback (его преемник), но делайте это с умом.Простые приложения по умолчанию, которые записывают и сразу записывают на диск, влияют на общую производительность вашего приложения.Обычно appender выполняет тяжелую работу с потоком вызывающей стороны.Чтобы избежать этого, вы либо пишете свой собственный appender, который делает это асинхронно (с буферизацией), либо используете оболочки - в зависимости от среды вы можете обернуть некоторые appenders асинхронным поведением без написания одной строки кода.У меня есть такой appender здесь (см. Внизу страницы), вы можете свободно использовать код или просто получить представление.Мой appender работает с TCP-сокетами, но проблема та же - предотвратить блокировку вызывающей стороны и выполнить сброс в отдельном потоке, чтобы приложение наверху никогда не чувствовало этого.

0 голосов
/ 17 ноября 2011

Мы делаем то же самое с нашими производственными серверами, за исключением того, что они запускают сообщения журнала через сетевое соединение.У нас просто есть ограниченная связанная очередь, и мы принимаем решения об удалении отладочных сообщений и сохранении ошибок, если очередь заполнена.Тогда у нас есть поток в фоновом режиме, запускающий сообщения на сервер.

  1. Я не знаю о такой вещи, как часть log4j или slf4j.

  2. Единственный способ потерять сообщения - это сбой JVM, и в этом случае у модуля записи буфера возникнут те же проблемы.Если вы пишете, что поток не является демоном, он может закончить писать сообщения журнала, когда приложение закрывается, прежде чем завершить работу.

  3. Единственная причина, по которой это будет ужасной идеей, - если действительно нетне проблема с производительностью вашей регистрации.Возможно, было бы хорошо убедиться, что вы изолировали свои входящие вызовы в собственную оболочку регистрации , в случае, если вам нужно поставить их в очередь на будущее.Но в краткосрочной перспективе просто напишите в log4j или что-то еще.Вы также можете поместить некоторую статистику в этот класс упаковки, чтобы увидеть, удерживают ли сообщения в журнале процесс вообще, а затем принимают обоснованное решение для повышения его производительности с помощью очередей.

0 голосов
/ 17 ноября 2011

Не знаю о существующих фреймворках, AFAIK нет "буфера" в локальной памяти.Но посмотрите стандартный Log4J и т. Д.

finalize() - это не то, что нужно.Используйте Runtime.addShutdownHook().Посмотрите что я выучил недавно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...