Логи - способ узнать, что делает Django-приложение в продакшене. В уроке соберём практичную схему: словарь LOGGING, логи запросов с id, структурированный JSON и отдельную конфигурацию для каждого окружения.
От print к logging
У print нет уровня, времени, источника и трассировки. Стандартный модуль logging даёт уровни, именованные логгеры, несколько назначений и форматов. Сам Django пишет через него (django.request, django.db.backends).
| Блок | Роль |
|---|---|
| Logger | Объект, который вы вызываете; имя - getLogger(__name__) |
| Handler | Куда уходит запись: консоль, файл, почта, коллектор |
| Formatter | Как она выглядит: текст или JSON |
| Filter | Отбрасывает записи или добавляет поля, например request_id |
Логирование в коде
import logging
import sys
logging.basicConfig(
stream=sys.stdout,
level=logging.INFO,
format='%(levelname)s %(name)s %(message)s',
)
log = logging.getLogger('shop.orders')
log.debug('hidden')
log.info('order %s created', 42)
log.warning('stock low: %d left', 3)Вывод:
INFO shop.orders order 42 created
WARNING shop.orders stock low: 3 leftСтрока DEBUG отброшена, потому что порог - INFO. Значения передавайте аргументами (%s), а не через f-строку.
| Уровень | Когда |
|---|---|
| DEBUG | Детали, только в разработке |
| INFO | Обычные события: заказ создан |
| WARNING | Неожиданно, но работает |
| ERROR | Операция не удалась |
| CRITICAL | Система не работает |
# shop/services.py
import logging
logger = logging.getLogger(__name__) # -> 'shop.services'
def pay(order_id):
logger.info('paying order %s', order_id)
try:
charge(order_id)
except TimeoutError:
logger.exception('payment gateway timeout, order %s', order_id)
raise