Как использовать стандартный и пользовательский логгер в django, но избежать дублирования логов
У меня есть два набора API в проекте Django, для которых я хочу использовать свой пользовательский логгер. Поэтому в каждом наборе представлений я буду делать logger.info(...)
или logger.error(...)
перед ответами.
Везде в проекте, например, на страницах администратора и в других инструментах, я бы хотел пока оставить протоколирование как есть.
Вот как я определил свои LOGGING
в settings.py.
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format':
'ts=%(asctime)s level=%(levelname)s caller=%(filename)s:%(funcName)s:%(lineno)s %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'standard',
},
},
'loggers': {
'my_logger': {
'handlers': ['console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
'propagate': False,
},
},
}
В моем представлении я вызываю регистратор следующим образом:
logger = logging.getLogger('my_logger')
logger.info("Some message")
Проблема в том, что в таком виде логирование в API дублируется для каждого запроса, мой логгер и существующий логгер django. Как я могу "отключить" стандартный django logger в API, но сохранить его везде?
Пример дублирования журналов:
ts=2022-06-07 09:50:14 level=INFO caller=views.py:retrieve:450 path=/api/v1/<path>/<uuid>/ method=GET status=200 user=71 msg=Some message
[07/Jun/2022 09:50:14] "GET /api/v1/<path>/<uuid>/ HTTP/1.1" 200 41633
Вы назвали свой пользовательский регистратор django
. Логгер django
является корневым логгером, который перехватывает все журналы, если только дочерние логгеры не настроены с помощью ключевого слова "propagate": False
. См. https://docs.djangoproject.com/en/4.0/ref/logging/#default-logging-conditions. Если вы дадите ему другое имя, то вы сможете вести журнал непосредственно в этот логгер, например
'loggers': {
'my_custom_logger': {
'propagate': False,
# other properties here
}
}
По вашему мнению, используйте
logger = logging.getLogger("my_custom_logger")
logger.ERROR("foo")
Эти сообщения журнала не должны распространяться на стандартный регистратор.
Согласно вашему обновленному вопросу, вы можете отключить записи логгера по умолчанию django.server
для URL-путей API, добавив объект Filter. См. https://docs.python.org/3/library/logging.html#filter-objects и https://docs.djangoproject.com/en/4.0/ref/logging/#filters: если метод фильтра .filter()
возвращает 0
или False
для данной записи журнала, она не будет записана в журнал.
Достаточно изменить конфигурацию на что-то вроде
'loggers': {
'django': {
'level': 'CRITICAL'
},
'my_logger': {
'handlers': ['console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO')
},
},
потому что тогда все пакеты/модули Django не должны ничего выводить (кроме CRITICAL
материала). Вам не нужен параметр propagate
, поскольку вы не настроили никаких обработчиков для корневого логгера (родителя логгера my_logger
) - propagate
будет только контролировать, запрашиваются ли обработчики родительских логгеров на обработку события, а в данном случае таких обработчиков нет.