Правильная регистрация в Python с помощью обработчиков файлов - PullRequest
5 голосов
/ 16 марта 2011

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

lsof | grep my.log 

показывает увеличение количества обработчиков в моем файле журнала, и через некоторое время мой сервер отказывает из-за этого ограничения на количество открытых файлов.

 self.logger = logging.getLogger("FPA")

        try:
            if self.logger.handlers[0].__class__.__name__=="FileHandler":
                pass
        except Exception, e:
            print 'new filehandler added'+str(e)
            ch = logging.FileHandler(FPA_LOG_TARGET)
            formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s - %(pathname)s @ line %(lineno)d")
            ch.setFormatter(formatter)
            self.logger.setLevel(logging.DEBUG)
            self.logger.addHandler(ch)

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

1 Ответ

1 голос
/ 21 марта 2011

Я не анализировал, если в течение длительного времени, но это похоже на проблему параллелизма.

Каждый процесс / поток сохраняет свой собственный список файловых дескрипторов для открытых файлов журнала.

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

Но главный вопрос в том, зачем вам это делать.

Прежде всего, вы можете использовать logging.conf файл, чтобы инициализировать все ваши логгеры / обработчики / форматеры и при необходимости (например, конкретный логер обширный, и вы хотите записать его в отдельный файл), добавить еще один регистратор с другим именем файла.Что весьма разумно, если вы добавите один регистратор в приложение django, добавив в основной __init__.py приложения:

import logging
log = logging.getLogger(__name__)

, а затем импортируйте log в остальной части кода приложения (просмотры, модели и т. д.)

Чтобы использовать logging.conf, добавьте следующие строки в ваши настройки.py:

import os
import logging
DIRNAME = os.path.abspath(os.path.dirname(__file__))
logging.config.fileConfig(os.path.join(DIRNAME, 'logging.conf'))

Да, это вручную, но вам не нужно менять код,но просто файл конфигурации.

Другой подход (если вы действительно хотите иметь один файл для каждого типа регистратора) - это создать отдельный процесс, который будет держать файлы открытыми, принимать соединения из приложения.В документации модуля ведения журнала есть хороший пример этого метода .

И последнее, но не менее важное: уже есть несколько хороших решений, которые могут быть полезны.Одним из них является использование django-sentry.Этот модуль может регистрировать все ваши исключения, 404 (с дополнительным промежуточным программным обеспечением - в комплекте) и захватывать все журналы (через включенный обработчик журналирования).

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

...