Как вести журнал в файл с помощью Django и Gunicorn? Использование TimedRotatingFileHandler пропускает логи
У меня есть приложение Django, которое регистрирует INFO с помощью TimedRotatingFileHandler. На сервере разработки он работает нормально, но при запуске в продакшене с помощью gunicorn не все строки журнала попадают в файл. Я также использую консольный обработчик, который корректно записывает все, и похоже, что файл, используемый TimedRotatingFileHandler, содержит только некоторые из этих строк и отбрасывает многое из того, что появляется из консольного логгера
Также он демонстрирует другое странное поведение; мой dictConfig регистрации имеет полуночное вращение. Я ожидал, что mylog.log будет писаться до полуночи, а затем его содержимое будет ротироваться в файл mylog.log. Это поведение при запуске на сервере разработки, который поставляется вместе с Django. Что происходит при запуске моего приложения с gunicorn, так это то, что оно постоянно пишет как в файл mylog.log, так и в файл mylog.log.2022-02-01. Содержимое mylog.log не появляется в другом файле. Это похоже на то, что журнал распределяется между mylog.log и mylog.log.2022-02-01 в течение дня...
Моя конфигурация:
'handlers': {
'console': {
'level': 'INFO',
'formatter': 'verbose',
'class': 'logging.StreamHandler',
},
'file': {
'level': 'INFO',
'formatter': 'verbose',
'filename': mylog.log,
'when': 'midnight',
'encoding': 'utf-8',
'backupCount': 7,
'class': 'logging.handlers.TimedRotatingFileHandler',
},
},
'loggers': {
'': {
'handlers': ['console', 'file'],
'level': level,
},
},
Проблема связана с тем, что рабочие gunicorn выполняются в другом процессе, а TimedRotatingFileHandler не работает с многопроцессорностью? Или плохая конфигурация?
Каков "стандартный" или предлагаемый способ вести журнал в файл внутри обработчика запроса в Django, в то время как приложение работает на gunicorn?
Возможно, это потому, что Python не поддерживает координацию между записью в один файл из нескольких процессов, поэтому материал может быть перезаписан. Я бы использовал либо SocketHandler, либо QueueHandler для всех модулей Django и вашего webapp, и имел бы отдельный процесс, слушающий {либо приемник сокета, либо QueueListener), который пишет в TimedRotatingFileHandler. В официальной документации есть поваренная книга , в которой приведены рецепты для сценария с несколькими процессами, включая рабочий код для приемников сокетов и т.д., который вы можете адаптировать под свои конкретные нужды. Я использую Supervisor для поддержания запущенного процесса слушателя.