Единственный совершенный код – это код, который так и не написали. Будучи разработчиком, вы стопроцентно будете совершать ошибки, и, кроме того, вам придется их исправлять.
Если вы программируете на Python, то вы всегда можете понять, что происходит, просто взглянув на сообщения об ошибках. Но что, если вы допустите ошибку и даже не будете знать, где конкретно вы ее допустили?
Возможно, что-то пошло не так на фоне, но вы не можете понять, что конкретно. Конечно, вы всегда можете перезапустить код, но будет еще лучше, если у вас будет возможность проверить журналы.
Что такое ведение журналов?
Если вдруг в вашем приложении возникнет ошибка, или оно начнет вести себя странным образом, файлы журналов вам очень сильно пригодятся. Вы можете просмотреть их и узнать, где именно в приложении возникает проблема и как эту проблему можно воспроизвести.
Воспроизведя проблему, вы можете копнуть глубже и найти какое-то рациональное решение. В противном случае на поиск решения может уйти несколько часов, а поиск файлов журнала займет всего несколько минут.
Как ведение журналов работает в Django
Благо, Django поддерживает функцию ведения журналов, и его разработчики уже проделали большую часть тяжелой работы. У Django есть встроенный модуль Python под названием logging, который используется для ведения записей в системном журнале.
Этот модуль состоит из четырех основных частей:
- Регистраторы
- Обработчики
- Фильтры
- Средства форматирования
Каждый из этих компонентов до мелочей описан в официальной документации Django. Я не хочу, чтобы вы ошибочно полагали, что это очень сложно, поэтому я кратко поясню каждый компонент:
1. Регистраторы
Регистраторы – это, попросту говоря, точка входа в систему протоколирования. Это то, с чем вы, как разработчики, собственно говоря, будете работать.
Когда регистратор получает сообщение, уровень ведения журнала сравнивается с уровнем ведения журнала регистратора. Если эти уровни совпадают, или если уровень ведения журнала превышает уровень ведения журнала регистратора, то сообщение отправляется обработчику для дальнейшей работы с ним. Вот так выглядят уровни ведения журнала:
- DEBUG: низкоуровневая информация о системе
- INFO: общая информация о системе
- WARNING: информация о несерьезных проблемах
- ERROR: информация о серьезных проблемах
- CRITICAL: информация об опасных проблемах
2. Обработчики
Обработчики, строго говоря, определяют, что будет происходить с каждым сообщением в регистраторе. Как и у регистраторов, у обработчиков также есть уровни ведения журнала. При этом мы, в принципе, может определить, как будет обрабатываться каждый уровень.
Например, сообщения уровня ERROR могут отправляться разработчику в режиме реального времени, а сообщения уровня INFO могут просто отправляться на хранение в системный файл.
По сути, обработчик указывает системе, что нужно сделать с сообщением, например, вывести его на экран, добавить в файл или отправить через сетевой сокет.
3. Фильтры
Фильтр можно разместить между регистратором и обработчиком. Его используют для того, чтобы фильтровать записи журнала.
Например, вы можете установить фильтр в рамках уровня CRITICAL, чтобы обрабатывать сообщения из определенного источника.
4. Средства форматирования
Как уже можно было понять из названия, средства форматирования отвечают за описание формата текста, который будет отображаться.
А теперь, когда мы разобрались с основами, давайте рассмотрим пример и копнем немного глубже. Здесь вы можете найти исходный код.
Отмечу, что данная статья предполагает наличие базовых знаний Django.
Настройка проекта
Для начала вам нужно создать виртуальную среду под названием venv внутри папки вашего проекта django-logging-tutorial. Сделать это можно с помощью команды, приведенной ниже.
mkdir django-logging-tutorial
virtualenv venv
source venv/bin/activate
Создайте новый проект Django и назовите его django-logging-tutorial. Обратите внимание, что в имени папки используется тире, а в имени проекта – нижнее подчеркивание. Здесь, чтобы настроить наш проект, мы также запускаем ряд команд.
Как настроить файлы журналов
Давайте для начала настроим файл проекта под названием settings.py. Обратите внимание на комментарии в коде, которые я там оставил. Они помогут вам лучше понять, что там происходит.
Этот код также приводится в третьем примере официальной документации, и он отлично подойдет для большинства наших проектов. Но я немного его изменил, чтобы он стал более надежным.
LOGGING = {
'version': 1,
# The version number of our log
{ # Номер версии вашего журнала }
'disable_existing_loggers': False,
# django uses some of its own loggers for internal operations. In case you want to disable them just replace the False above with true.
{ # Django использует ряд собственных регистраторов для внутренних операций. Если вы хотите их отключить, просто замените в строке выше false на true. }
# A handler for WARNING. It is basically writing the WARNING messages into a file called WARNING.log
{ # Обработчик уровня WARNING. Попросту говоря, это запись сообщений уровня WARNING в файл под названием WARNING.log. }
'handlers': {
'file': {
'level': 'WARNING',
'class': 'logging.FileHandler',
'filename': BASE_DIR / 'warning.log',
},
},
# A logger for WARNING which has a handler called 'file'. A logger can have multiple handler
{ # Регистратор уровня WARNING, у которого есть обработчик под названием «file». У регистратора может быть несколько обработчиков. }
'loggers': {
# notice the blank '', Usually you would put built in loggers like django or root here based on your needs
{ # обратите внимание на пробел. Как правило, встроенные регистраторы, такие как Django или root, размещаются в зависимости от ваших потребностей. }
'': {
'handlers': ['file'], #notice how file variable is called in handler which has been defined above { # обратите внимание на то, как файловая переменная вызывается в обработчике, который был определен выше }
'level': 'WARNING',
'propagate': True,
},
},
}
Если вы читали мои комментарии, то могли заметить, что часть, которая относится к регистратору, пустая. По сути, это значит, что использоваться может любой регистратор.
Однако не стоит усердствовать с этим подходом, так как большую часть нашей работы можно выполнить с помощью встроенных регистраторов Django, например, django.request или django.db.backends.
Кроме того, дабы упростить задачу, я использовал только файл для хранения журналов. Но все зависит от вашего сценария использования. Вы также можете отправлять электронные письма в случае, если вы обнаружили сообщения уровня CRITICAL или ERROR.
Я бы посоветовал вам прочитать ту часть документации, где говориться об обработчиках, чтобы узнать о них больше. Сначала вам может показаться, что чтение этой документации – непосильный труд, но чем быстрее вы свыкнетесь с мыслью, что прочитать ее нужно, тем больше других интересных и лучших подходов вы сможете найти.
Если вы работаете с документацией впервые, не стоит беспокоиться. Все когда-то бывает в первый раз.
Я пояснил большую часть кода комментариями, но мы еще не упомянули, что же такое propagate. Так что же это?
Если значение propagate установлено как True, то дочерний элемент будет передавать все свои запросы на внесение в журнал родительскому элементу. Это значит, что мы можем определить обработчик в корне (в родительском элементе) дерева регистратора, и все запросы на внесение в журнал в поддереве (в дочернем элементе) будут отправляться обработчику, который был определен в родительском элементе.
Кроме того, очень важно отметить важность иерархии. Мы также может просто установить значение этого параметра в нашем проекте как True, поскольку в нашем случае это совершенно не важно, так как поддерева просто нет.
Как вызывать журналы в Python
А теперь, мы должны создать несколько журнальных сообщений, чтобы опробовать нашу конфигурацию, заданную в settings.py, в деле.
Давайте создадим домашнюю страницу по умолчанию, которая будет просто отображать фразу «Hello FreeCodeCamp.org Reader :)», а каждый раз, когда кто-нибудь будет посещать эту страницу, мы будем записывать в наш файл warning.log сообщение уровня WARNING: «Homepage was accessed at 2021-08-29 22:23:33.551543 hours!».
Перейдите к вашему приложению logging_example и добавьте в файл views.py следующий код. Убедитесь в том, что вы добавили logging_example в INSTALLED_APPS, который находится внутри setting.py.
from django.http import HttpResponse
import datetime
# import the logging library { # импорт библиотеки logging }
import logging
# Get an instance of a logger { # получаем экземпляр регистратора }
logger = logging.getLogger(__name__)
def hello_reader(request):
logger.warning('Homepage was accessed at '+str(datetime.datetime.now())+' hours!')
return HttpResponse("<h1>Hello FreeCodeCamp.org Reader :)</h1>")
Добавьте в проект urls.py следующий код для того, чтобы, когда мы получали доступ к домашней странице, вызывалась правильная функция.
from django.contrib import admin
from django.urls import path
from logging_example import views
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.hello_reader, name="hello_reader")
]
Время для тестирования
И наконец, наша несложная настройка завершена. Все, что нам теперь нужно сделать, это запустить наш сервер и проверить наш журнал.
Запустить сервер разработки можно с помощью следующей команды:
python manage.py runserver
А теперь перейдите на свою домашнюю страницу 127.0.0.1:8000, где вы увидите сообщение, появление которого мы запрограммировали. После чего проверьте файл warning.log, расположенный по созданному нами пути. Вот так будет выглядеть результат:
Homepage was accessed at 2021-08-29 22:38:29.922510 hours!
Homepage was accessed at 2021-08-29 22:48:35.088296 hours!
Вот и все! Теперь вы знаете, как вести журнал в Django.