Удаление Log4perl logger, когда он мне больше не нужен

#perl #log4perl

#perl #log4perl

Вопрос:

Я использую Log4perl как часть пакета, чтобы фиксировать, что делает конкретное DBI-соединение. Мой текущий план состоит в том, чтобы создать новый объект logger для каждого соединения через Log::Log4perl->get_logger($mysql_connect_id) , который должен позволять различным соединениям записывать данные либо в разные файлы, либо в один и тот же файл, не портя друг друга.

Меня беспокоит то, что происходит, когда соединение отключено и этот регистратор больше не нужен. Если Log4perl просто хранит эти регистраторы бесконечно, это звучит как рецепт утечки памяти.

Каков наилучший способ избавиться от logger после того, как я уверен, что он больше не полезен? Или, наоборот, это вообще проблема — есть ли у Log4perl какой-то встроенный механизм удаления, который уже предотвращает такого рода утечки?


Редактировать: Упоминается в комментариях к вопросу, вероятно, стоит упомянуть здесь: Log::Log4perl::Logger имеет DESTROY метод, который кажется многообещающим. Однако он недокументирован и выдает кучу предупреждений «Использование неинициализированного значения в строковом уравнении», что заставляет меня насторожиться; это похоже на взлом. (Но если это лучший / единственный способ сделать это, я полагаю, возникает вопрос «Как мне отключить конкретное предупреждение, исходящее из определенного пакета?»)

Комментарии:

1. DESTROY метод не следует вызывать вручную, потому что он будет вызываться самим perl, когда объект будет удален из памяти. Вызов DESTROY напрямую не освободит память.

2. @Ivan: Ну и дерьмо. Вот и все для идеально красивого взлома. Спасибо за совет.

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

Ответ №1:

Единственный способ, который я вижу, — это манипулировать внутренним кэшем Log::Log4perl::Logger .

 delete $Log::Log4perl::Logger::LOGGERS_BY_NAME->{$category};
  

Это «безопасно» в том смысле, что оно будет работать с текущими версиями Log::Log4perl, но небезопасно в том смысле, что оно может прерваться при обновлении. Ранее это было предложено другим пользователем SO, но они удалили его.

Я бы посоветовал вам сделать запрос функции для возможности удаления отдельных записей кэша как части API. Если вы хотите ускорить это, отправьте исправление. Это довольно просто.

Комментарии:

1. Я справился с проблемой, разработав ее вокруг, но если бы я все еще был привязан к оригинальному дизайну, я бы использовал это решение. И это хорошая вещь, которая у меня в кармане. Спасибо! (Кстати — Я думаю, мы знаем друг друга по RL.)

Ответ №2:

Извините за задержку, я думаю, что я, наконец, исправил это сейчас. Теперь вы можете использовать недавно реализованный метод Log::Log4perl->remove_logger($logger) для удаления неиспользуемых регистраторов (не забудьте удалить оставшуюся ссылку на $logge r, которую вы храните).

Проверено на github и должно выйти со следующим выпуском (1.33). Спасибо, что довели это до моего сведения. Твой парень из log4perl, Майк.

Ответ №3:

Это выглядит как

 Log::Log4perl::Logger->cleanup();
  

вызов должен удалить все, что было инициализировано до сих пор. Это должно удалить все связанные ресурсы.

Комментарии:

1. Сбросить ядерную бомбу с орбиты сайта? 🙂 Этого было бы достаточно, но, если я правильно это читаю, это также избавит от любых регистраторов, которые я хочу сохранить.

2. @BlairHippo — неправильно прочитал ваш вопрос, я думал, вы хотите полностью избавиться от Log::Log4perl. Если вы хотите удалить что-то, почему бы просто не предоставить ему новую конфигурацию и не разрешить повторную инициализацию?

3. К сожалению, cleanup() не просто удаляет свой собственный кеш, он агрессивно вызывает DESTROY для каждого регистратора. Это не нужно и делает вызов cleanup() опасным. Вы должны знать, что все регистраторы повсюду во всем процессе, даже в модулях сторонних производителей, больше не используются.

4. Я сообщил автору о проблеме агрессивного поведения cleanup. github.com/mschilli/log4perl/issues/7 (Кроме того, очистка не документирована, поэтому вам не следует ее использовать)

Ответ №4:

Из документов по адресуhttp://search.cpan.org/dist/Log-Log4perl/lib/Log/Log4perl.pm :

Чтобы удалить logger из системы, используйте Log::Log4perl->remove_logger($logger). После того, как оставшаяся ссылка $logger исчезнет, регистратор самоуничтожится. Если рассматриваемый регистратор является скрытым регистратором, все его удобные ярлыки (DEBUG, INFO и т.д.) Станут неработоспособными.

Комментарии:

1. Хех. Если вы читали другие ответы, эта функция является следствием этого вопроса. На самом деле я немного горжусь. 🙂