Утилизация логгера Log4perl, когда он мне больше не нужен

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

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

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


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


person BlairHippo    schedule 06.05.2011    source источник
comment
Метод DESTROY не следует вызывать вручную, потому что он будет вызываться самим perl, когда объект будет удален из памяти. Прямой вызов DESTROY не освободит память.   -  person Ivan Nevostruev    schedule 06.05.2011
comment
@Ivan: Ну, дерьмо. Вот вам и прекрасно выглядящий хак. Спасибо за совет.   -  person BlairHippo    schedule 06.05.2011
comment
Объекты регистратора представляют собой небольшой хэш ссылок на код. Если вы не делаете тонны вещей, я бы сказал, что дополнительная память не имеет значения по сравнению с любыми фактическими данными, которые ваша программа хранит в памяти. Не беспокойтесь об этом.   -  person Schwern    schedule 09.05.2011


Ответы (4)


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

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

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

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

person Schwern    schedule 09.05.2011
comment
Я справился с проблемой, разработав вокруг нее, но если бы я все еще был привязан к исходному дизайну, я бы использовал это решение. И хорошо иметь в кармане. Спасибо! (Кстати, я думаю, что мы знаем друг друга в RL.) - person BlairHippo; 10.05.2011

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

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

person Mike Schilli    schedule 22.05.2011

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

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

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

person bvr    schedule 06.05.2011
comment
Взорвать сайт с орбиты? :-) Это сработало бы, но, если я правильно понял, это также избавит от любых регистраторов, которые я хочу оставить. - person BlairHippo; 06.05.2011
comment
@BlairHippo - неправильно прочитал ваш вопрос, я думал, вы хотите полностью избавиться от Log::Log4perl. Если вы хотите удалить что-то, почему бы просто не дать ему новую конфигурацию и позволить себе повторно инициализироваться? - person bvr; 07.05.2011
comment
К сожалению, cleanup() не просто удаляет собственный кеш, он агрессивно вызывает DESTROY на каждом регистраторе. Это не нужно и делает вызов cleanup() опасным. Вы должны знать, что все регистраторы во всем процессе, даже в сторонних модулях, больше не используются. - person Schwern; 09.05.2011
comment
Я сообщил автору о проблеме агрессивного поведения очистки. github.com/mschilli/log4perl/issues/7 (Кроме того, очистка не задокументирована так что не стоит его использовать) - person Schwern; 09.05.2011

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

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

person buster    schedule 02.12.2011
comment
Хе. Если вы читаете другие ответы, эта функция является следствием этого вопроса. Я даже немного горжусь. :-) - person BlairHippo; 02.12.2011