Какая оптимизация логирования параметров в больших проектах является best practice
Что проверяют
Понимаете ли вы, во что обходится логирование под нагрузкой и как не утопить сервис и хранилище логов. Следом обычно спрашивают, чем плоха f-строка в logger.debug и как не допустить утечки персональных данных.
Как отвечать
Главная оптимизация для параметров: ленивое форматирование. Пишите logger.debug("user %s, payload %s", user_id, payload), а не f-строку. Модуль logging подставит аргументы, только если запись пройдёт по уровню, а f-строка собирается всегда, даже при выключенном DEBUG. Если параметр дорого вычислять, оберните вызов в if logger.isEnabledFor(logging.DEBUG):.
Остальной каркас:
- логгер на модуль:
logging.getLogger(__name__), настройка один раз при старте черезlogging.config.dictConfig, уровни по окружению; - структурированный формат: JSON через
structlogилиpython-json-logger, параметры отдельными полями черезextra, а не склеенными в строку; - контекст запроса:
request_idиuser_idхранят вcontextvarsи добавляют фильтром ко всем записям, в том числе в асинхронном коде; - без блокировок: запись в файл или по сети синхронна, поэтому в нагруженном сервисе ставят
QueueHandlerиQueueListener, которые уносят ввод-вывод в отдельный поток. В контейнерах проще писать в stdout, а сбор и хранение отдать Loki, ELK или Vector; - объём: большие тела запросов обрезают, повторяющиеся события сэмплируют, DEBUG на проде не держат включённым постоянно;
- безопасность: пароли, токены, номера карт и персональные данные маскирует
logging.Filterдо записи.
Если логи всё же пишутся в файлы, ротацию делают RotatingFileHandler, TimedRotatingFileHandler или системный logrotate.
Где спотыкаются
Используют f-строки и str(big_object) в DEBUG-логах и удивляются нагрузке на CPU при выключенном уровне отладки.
Советуют асинхронное логирование через asyncio. Обработчики logging синхронные, и правильный инструмент это очередь с отдельным потоком, а не корутины.
Логируют весь request.body или **kwargs целиком. Так в логи попадают токены и персональные данные, а вычистить их из централизованного хранилища намного сложнее, чем не записать.