Почему Python TimedRotatingFileHandler не сворачивается, если запущены задания Celery?
Python 3.12.3, Celery 5.3.6, Django 4.2.11, Ubuntu 22.04.4
У меня есть инфраструктура из серверов Django и Celery, одновременно работающих на сервере Ubuntu.
Для ведения логов я использую DiscordHandler и настроенный TimedRotatingFileHandler, определенный так:
class CustomizedTimedRotatingFileHandler(TimedRotatingFileHandler):
'''
log_name.date.log.log -> log_name.date.log
'''
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.namer = lambda name: name.replace(".log", "") + ".log"
Журналирование проекта настроено в файле настроек:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
**{
f"{k}_file": {
"level": "INFO",
"class": "api.logging.CustomizedTimedRotatingFileHandler",
"filename": "log/sync.log",
"when": "midnight",
"backupCount": 2,
"formatter": v,
} for k, v in {"django": "verbose", "celery": "celery"}.items()
}
},
'loggers': {
'django': {
'handlers': ['django_file'],
'level': 'INFO',
'propagate': True,
},
'django.server': {
'handlers': ['django_file'],
'level': 'INFO',
'propagate': False,
},
'celery': {
'handlers': ['celery_file'],
'level': 'INFO',
'propagate': False,
}
}
}
Прямо сейчас у меня есть 2 лог-файла, а затем файл today (в который попадают логи только из Django, а не из Celery).
Я просмотрел логи дискорда и увидел, что в полночь работало несколько сельдерейных заданий. И это не первый случай, на самом деле, все разы дело было в том, что в полночь были текущие задания, которые прерывали ролловер.
Как получить правильную регистрацию файлов? Единственное, что я могу предположить, это то, что я должен вручную сделатьRollover (как задачу celery).
Любая помощь приветствуется
Предполагается, что при использовании рабочих Celery несколько рабочих процессов ведут логирование в один и тот же физический файл, что не поддерживается (при использовании нескольких потоков блокировки заботятся о сериализации доступа - при использовании нескольких процессов это не так). См. раздел поваренной книги по этому вопросу - вероятно, вам следует настроить QueueHandler
или SocketHandler
, который отправляет события от всех рабочих процессов в отдельный процесс логирования, который единственный пишет в файл журнала.