Django логирование ошибок в файл
Пакет Logging является очень полезным инструментом в наборе инструментов программиста. Он может помочь вам лучше понять суть программы и обнаружить сценарии, о которых вы, возможно, даже не задумывались при разработке.
Логи предоставляют разработчикам дополнительный набор глаз, которые постоянно смотрят на поток, через который проходит приложение. Они могут хранить информацию о том, какой пользователь или IP получил доступ к приложению. Если возникает ошибка, то они могут предоставить больше информации, чем трассировка стека, сообщив вам, в каком состоянии находилась программа до того, как она достигла строки кода, где произошла ошибка.
Записывая полезные данные из нужных мест, вы можете не только легко отлаживать ошибки, но и использовать данные для анализа производительности приложения, планирования масштабирования или просмотра схем использования для планирования маркетинга.
В этой статье вы узнаете, почему использование модуля logging является лучшим способом добавления логов в ваше приложение, а также узнаете как быстро начать работу с ним.
Make a basic logging call¶
To send a log message from within your code, you place a logging call into it.
Don’t be tempted to use logging calls in settings.py .
The way that Django logging is configured as part of the setup() function means that logging calls placed in settings.py may not work as expected, because logging will not be set up at that point. To explore logging, use a view function as suggested in the example below.
First, import the Python logging library, and then obtain a logger instance with logging.getLogger() . Provide the getLogger() method with a name to identify it and the records it emits. A good option is to use __name__ (see Use logger namespacing below for more on this) which will provide the name of the current Python module as a dotted path:
It’s a good convention to perform this declaration at module level.
And then in a function, for example in a view, send a record to the logger:
When this code is executed, a LogRecord containing that message will be sent to the logger. If you’re using Django’s default logging configuration, the message will appear in the console.
The WARNING level used in the example above is one of several logging severity levels : DEBUG , INFO , WARNING , ERROR , CRITICAL . So, another example might be:
Records with a level lower than WARNING will not appear in the console by default. Changing this behavior requires additional configuration.
Логирование переменных
Хотя вы можете использовать любой стиль форматирования, f-строки, представленные в Python 3.6, являются лучшим способом форматирования строк, поскольку они могут помочь сделать форматирование коротким и легким для чтения:
Customize logging configuration¶
Although Django’s logging configuration works out of the box, you can control exactly how your logs are sent to various destinations - to log files, external services, email and so on - with some additional configuration.
- logger mappings, to determine which records are sent to which handlers
- handlers, to determine what they do with the records they receive
- filters, to provide additional control over the transfer of records, and even modify records in-place
- formatters, to convert LogRecord objects to a string or other form for consumption by human beings or another system
There are various ways of configuring logging. In Django, the LOGGING setting is most commonly used. The setting uses the dictConfig format , and extends the default logging configuration .
See Configuring logging for an explanation of how your custom settings are merged with Django’s defaults.
See the Python logging documentation for details of other ways of configuring logging. For the sake of simplicity, this documentation will only consider configuration via the LOGGING setting.
formatters (форматы)
Этот раздел определяет, как будут выглядеть строки в логгах. Мы не будем рассматривать все возможные варианты форматирования. В этой статье описывается все, что поддерживается. Давайте посмотрим на формат журнала консоли:
Вот что здесь используется:
Использование Handlers
У созданного вами logger может быть несколько обработчиков, а это значит, что вы можете настроить его на сохранение в файл журнала, а также на отправку по электронной почте.
Подобно logger, вы также можете установить уровень severity в обработчиках. Это полезно, если вы хотите установить несколько обработчиков для одного и того же logger, но хотите иметь разные уровни severity для каждого из них. Например, вы можете захотеть, чтобы журналы с уровнем WARNING и выше регистрировались на консоли, но все с уровнем ERROR и выше также должно быть сохранены в файл. Вот пример кода, который делает это:
Здесь logger.warning() создает LogRecord, который содержит всю информацию о событии, и передает ее всем имеющимся обработчикам: c_handler и f_handler.
c_handler является StreamHandler с уровнем WARNING и берет информацию из LogRecord для генерации вывода в указанном формате и выводит его на консоль. f_handler — это FileHandler с уровнем ERROR, и он игнорирует LogRecord, так как его уровень — WARNING.
Имя logger, соответствующее переменной __name__, записывается как __main__, то есть имя, которое Python присваивает модулю, с которого начинается выполнение. Если этот файл импортируется каким-либо другим модулем, то переменная __name__ будет соответствовать его имени logging_example. Вот как это будет выглядеть:
Еще один пример конфигурации логгирования
В заключение хочу привести еще одну конфигурацию указанную в официальной документации и описать ее.
Эта конфигурация выполняет следующее:
Определяет два formatters (форматера):
Определяет один filters (фильтр) – project.logging.SpecialFilter с названием special. Если конструктор фильтра требует наличия дополнительных аргументов, вы можете указать их в словаре настройки фильтра. В этом случае будет передан аргумент foo со значением bar при создании экземпляра SpecialFilter.
Определяет три handlers (обработчика):
Настраивает три loggers (логгера):
а затем настройте handlers консоли на использование rich.logging.RichHandler вместо logging.StreamHandler
Ваша жизнь после этого станет намного ярче 🙂
Заключение
В данный статье я описал простую но эффективную систему контроля над изменяемыми данными в Django проектах. Надеюсь она вам пригодиться при реализации подобной задачи.
Django — один из самых популярных веб фреймворков Python, используемый многими организациями. Поскольку он использует встроенное средство ведения логов Python logging, использование логов в Django совсем несложная задача.
В этой статье мы создадим небольшое тестовое приложение которое поможет мне рассказать о том как настраивать логгирование в Django. Мы сделаем следующее:
django.db.backends
Первые шаги с логгированием
Самое простое для включения логирования, которое мы можем сделать, это просто импортировать модуль Python logging и начать регистрацию. Начните с обновления файла app/views.py следующим кодом:
disable_existing_loggers
Examples¶
The full documentation for dictConfig format is the best source of information about logging configuration dictionaries. However, to give you a taste of what is possible, here are several examples.
To begin, here’s a small configuration that will allow you to output all log messages to the console:
This configures the parent root logger to send messages with the WARNING level and higher to the console handler. By adjusting the level to INFO or DEBUG you can display more messages. This may be useful during development.
Next we can add more fine-grained logging. Here’s an example of how to make the logging system print more messages from just the django named logger:
By default, this config sends messages from the django logger of level INFO or higher to the console. This is the same level as Django’s default logging config, except that the default config only displays log records when DEBUG=True . Django does not log many such INFO level messages. With this config, however, you can also set the environment variable DJANGO_LOG_LEVEL=DEBUG to see all of Django’s debug logging which is very verbose as it includes all database queries.
You don’t have to log to the console. Here’s a configuration which writes all logging from the django named logger to a local file:
If you use this example, be sure to change the 'filename' path to a location that’s writable by the user that’s running the Django application.
Finally, here’s an example of a fairly complex logging setup:
This logging configuration does the following things:
Identifies the configuration as being in ‘dictConfig version 1’ format. At present, this is the only dictConfig format version.
Defines two formatters:
simple , that outputs the log level name (e.g., DEBUG ) and the log message.
The format string is a normal Python formatting string describing the details that are to be output on each logging line. The full list of detail that can be output can be found in Formatter Objects .
verbose , that outputs the log level name, the log message, plus the time, process, thread and module that generate the log message.
Defines two filters:
- project.logging.SpecialFilter , using the alias special . If this filter required additional arguments, they can be provided as additional keys in the filter configuration dictionary. In this case, the argument foo will be given a value of bar when instantiating SpecialFilter .
- django.utils.log.RequireDebugTrue , which passes on records when DEBUG is True .
Defines two handlers:
- console , a StreamHandler , which prints any INFO (or higher) message to sys.stderr . This handler uses the simple output format.
- mail_admins , an AdminEmailHandler , which emails any ERROR (or higher) message to the site ADMINS . This handler uses the special filter.
Configures three loggers:
- django , which passes all messages to the console handler.
- django.request , which passes all ERROR messages to the mail_admins handler. In addition, this logger is marked to not propagate messages. This means that log messages written to django.request will not be handled by the django logger.
- myproject.custom , which passes all messages at INFO or higher that also pass the special filter to two handlers – the console , and mail_admins . This means that all INFO level messages (or higher) will be printed to the console; ERROR and CRITICAL messages will also be output via email.
django.template
Независимо от того, как часто я работал с шаблонами Django, я никогда не собирал их без ошибок с первого раза. Логгер django.template обрабатывает ошибки, связанные с отображением шаблонов.
Disabling logging configuration¶
If you don’t want to configure logging at all (or you want to manually configure logging using your own approach), you can set LOGGING_CONFIG to None . This will disable the configuration process for Django’s default logging .
Setting LOGGING_CONFIG to None only means that the automatic configuration process is disabled, not logging itself. If you disable the configuration process, Django will still make logging calls, falling back to whatever default logging behavior is defined.
Here’s an example that disables Django’s logging configuration and then manually configures logging:
Note that the default configuration process only calls LOGGING_CONFIG once settings are fully-loaded. In contrast, manually configuring the logging in your settings file will load your logging config immediately. As such, your logging config must appear after any settings on which it depends.
Django provides a working default logging configuration that is readily extended.
django.security.*
Создание виртуальной среды
Виртуальные среды Python — это отличный способ поддерживать чистоту всей системы. Они изолируют зависимости вашего проекта и защищают системную установку Python от лишних проблем с зависимостями.
Поскольку в этой статье мы будем использовать Python 3, перед созданием виртуальной среды Python проверьте, что вы используете версию Python не ниже 3.6.1:
Затем создайте каталог, чтобы сохранить наш проект:
Отлично. Прежде чем перейти к следующему разделу, давайте создадим и активируем нашу новую виртуальную среду:
Теперь все хорошо, перейдем к установке Django.
Добавление нового модуля Django
Теперь, когда у нас есть главный каркас приложения, давайте создадим модуль с именем hello:
Эта команда создаст новую папку с именем hello вместе с несколькими дополнительными файлами Python. Замените содержимое hello/views.py следующим:
Это создает наше первоначальное представление (view), но нам все еще нужно сообщить об этом Django. Создайте новый файл в hello/urls.py и добавьте в него следующее:
Это связывает наше представление с базовым URL. Теперь все, что нам нужно сделать, это подключить его к файлу loggers/urls.py, чтобы Django знал, как все маршрутизировать. Откройте loggers/urls.py и замените его содержимое следующим:
Затем запустите веб-сервер, как мы делали раньше:
Вместо стандартного экрана приветствия Django, мы увидим наш вывод строки «Hello logging world.»
Теперь, когда у нас есть простое приложение, давайте посмотрим, как включить логгирование в Django.
loggers (логгеры)
В нашем примере мы не использовали один параметр который необходимо упомянуть здесь это filters
filters (фильтры)
Фильтр могут быть добавлены к логгеру или обработчику, можно использовать несколько фильтров.
Давайте сейчас обновим конфигурацию и посмотрим что получилось.
Другие методы настройки
Вы можете настроить ведение журнала, как показано выше, используя функции модуля и класса или создав файл конфигурации или словарь и загрузив его с помощью fileConfig() или dictConfig() соответственно. Это полезно, если вы хотите часто менять конфигурацию ведения журнала в работающем приложении.
Вот пример файла конфигурации:
В приведенном выше файле есть два logger, один обработчик и один форматер. После того, как определены их имена, они настраиваются путем добавления слов logger, handler и formatter перед их именами, разделенными подчеркиванием.
Чтобы загрузить этот файл конфигурации, вы должны использовать fileConfig():
Путь к файлу конфигурации передается в качестве параметра методу fileConfig(), а параметр disable_existing_loggers используется для сохранения или отключения logger, которые присутствуют при вызове функции. По умолчанию установлено значение True, если не упомянуто.
Вот та же конфигурация в формате YAML для подхода с dictionary:
Пример, который показывает, как загрузить конфигурацию из файла yaml:
version
Схема dictConfig не требует версии, но ее установка обеспечивает обратную совместимость. В настоящее время единственным допустимым значением здесь является 1.
Формат вывода
format может принимать строку с атрибутами LogRecord в любом порядке. Весь список доступных атрибутов можно найти здесь.
Вот еще один пример, где вы можете добавить информацию о дате и времени:
%(asctime)s добавляет время создания LogRecord. Формат можно изменить с помощью атрибута datefmt, который использует тот же язык форматирования, что и функции форматирования в модуле datetime, например time.strftime():
Вы можете найти больше информации о формате datetime в этом руководстве.
django.security.csrf
Этот логгер не наследуется от SuspiciousOperation. Он обрабатывает любые исключения, которые происходят из-за атак Cross-Site Request Forgery (CSRF).
Так же для каждого модуля в вашем приложение вы можете описать свой логгер (например для ведение отдельных файлов). Это делается следующим образом:
что бы он работал нужно добавить настройки отправки почты также в файл settings.py (в нашем примере мы будет использовать сервер yandex, но можно использовать любой другой, с соотвествующими настройками)
Имена используемых параметров сами говорят за себя их предназначение. Очень важно понимать что бы все заработало сервер на котором запускается Django должен уметь отправлять почту (на нем должна быть настроена отправка почты по SMTP). Настройка отправки почты на сервере выходит за рамки данной статьи. Что бы немного облегчить поиск проблем связанных с настройкой отправки почты на сервере можно имитировать отправку почты Django. То есть вместо реальной отправки писем записывать их в локальный файл. Для этого нужно указать соотвествующий почтовой бекенд email_backend и файл для записи в настройках.
Так же можно добавить фильтр django.utils.log.RequireDebugFalse, который сделает так что бы письма отправлялись только когда отключен режим DEBUG то есть установлен DEBUG=False
Если по каким то причинам почта не отправляется, можно поискать причины отправив тестовое письмо вручную, через следующую функцию:
Overview¶
Django uses and extends Python’s builtin logging module to perform system logging. This module is discussed in detail in Python’s own documentation; this section provides a quick overview.
Вывод стека
Модуль регистрации также позволяет вам захватывать стек выполнения в приложении. Информация об исключении может быть получена, если параметр exc_info передан как True, а функции ведения журнала вызываются таким образом:
Если для exc_info не задано значение True, выходные данные вышеприведенной программы не сообщат нам ничего об исключении, которое в реальном сценарии может быть не таким простым, как ZeroDivisionError. Представьте, что вы пытаетесь отладить ошибку в сложной кодовой базе с помощью журнала, который показывает только это:
Использование logging.exception() покажет лог на уровне ERROR. Если вы не хотите этого, вы можете вызвать любой из других методов ведения журнала от debug() до critical() и передать параметр exc_info как True.
Тестирование новой конфигурации
Этого достаточно, чтобы включить логгирование в любом проекте Django. Сейчас вы можете самостоятельно поиграться с настройками обработчиков и логгеров в созданном тестовом приложение.
Далее, рассмотрим более подробно стандартные логгеры (logging) для ведения логов, которые предоставляет Django.
Configuring logging¶
Python’s logging library provides several techniques to configure logging, ranging from a programmatic interface to configuration files. By default, Django uses the dictConfig format .
In order to configure logging, you use LOGGING to define a dictionary of logging settings. These settings describe the loggers, handlers, filters and formatters that you want in your logging setup, and the log levels and other properties that you want those components to have.
By default, the LOGGING setting is merged with Django’s default logging configuration using the following scheme.
If the disable_existing_loggers key in the LOGGING dictConfig is set to True (which is the dictConfig default if the key is missing) then all loggers from the default configuration will be disabled. Disabled loggers are not the same as removed; the logger will still exist, but will silently discard anything logged to it, not even propagating entries to a parent logger. Thus you should be very careful using 'disable_existing_loggers': True ; it’s probably not what you want. Instead, you can set disable_existing_loggers to False and redefine some or all of the default loggers; or you can set LOGGING_CONFIG to None and handle logging config yourself .
Logging is configured as part of the general Django setup() function. Therefore, you can be certain that loggers are always ready for use in your project code.
Модуль Logging
Добавить logging в вашу программу на Python так же просто, как написать эту строчку:
Модуль logging предоставляет вам логер по умолчанию, который позволяет вам начать работу без дополнительных настроек. Соответствующие методы для каждого уровня можно вызвать, как показано в следующем примере:
Вывод вышеупомянутой программы будет выглядеть так:
Заключение
Модуль logging считается очень гибким. Его дизайн очень практичен и должен подходить для любого случая использования. Вы можете добавить базовое ведение логов в небольшой проект или даже создать собственные настраиваемые уровни журналов, классы обработчиков и многое другое, если вы работаете над большим проектом.
Если вы не использовали логирование в своих приложениях до сих пор, сейчас самое время начать. Если все сделаете правильно, ведение логов, несомненно, устранит много проблем как в процессе разработки так и в процессе эксплуатации и поможет вам найти возможности поднять ваше приложение на новый уровень.
В этой статье я бы хотел рассказать как можно реализовать автоматический контроль над изменениями данных в проектах построенных с использованием Django.
Спонсор поста АРЕНДА ВЫДЕЛЕННОГО ВИРТУАЛЬНОГО СЕРВЕРА VDS (VPS)
Задача состоит в том что бы создать такую систему которая позволяло бы автоматически получать информацию о том какие данные изменились, а так же кто и когда их изменил. Допустим, если в таблице которую мы хотим контролировать, изменилось какое нибудь поле (на скриншете были изменены данные в таблицах TicketComment и User), нужно что бы создалась запись об этом в соответствующей таблице (в нашем случае она будет называть ChangeLog). В этой запись должна быть информация о том что поменялось и о том кто поменял.
Общая идея реализации заключается в создание сигналов Django которые можно подключать к выбранным таблицам (которые мы хотим контролировать) и они будут записывать в соответствующую таблицу информацию об изменяемых данных и дополнительные необходимые данные.
Более подробно план состоит в следующем:
Для этих целей у нас будет отдельное приложение, которые будет называться changelog.
И так создадим модель для логируемых данных. В ней мы создадим соотвествующие поля и отдельный классовый метод add через который мы будет создать новые записи в этой таблица
changelog/models.py
Опишем используемые поля:
- changed — дата и время создание новой записи
- model — таблица в которой изменились данные
- record_id — id измененой записи
- user — пользователь который поменял данные
- action_on_model — действие которое было совершено (Создание/Изменение/Удаление)
- data — измененные данные
- ipaddress — ip адрес с которого пришел запрос
Далее создадим класс ChangeLogAdmin для джанговской админки.
changelog/admin.py
Далее начинается самое интересное. При изменение данных которые мы будет отлавливать через соотвествующие сигналы на нужно определить какие именно данные были изменены. Этот механизм мы реализуем внутри миксина ChangeloggableMixin, который мы будем подключать к контролируемой таблице. Сам механизм реализуется достаточно просто. У нас есть поле _original_values в котором будет находится оригинальное значение и затем при изменение данных нам нужно определить что именно изменилось. В нашем примере это реализуется в методе get_changed_fields. Он возвращает словарь в котором будет записано имя измененного поля (в качестве ключа) и его новое значение. При необходимости легко добавить старое значение поля.
changelog/mixins.py
Далее создадим middleware для получения имени пользователя и его ip адрес.
changelog/middleware.py
Наш класс LoggedInUser через который мы будем получать нужные значение мы реализуем через шаблон Singleton, так как мы будет его вызывать, через middleware LoggedInUserMiddleware во время запроса а затем его же в соответствующем сигнале. В первом вызове мы получаем соответсвующие данные через request, а во втором вызове мы используем их.
Далее нужно записать LoggedInUserMiddleware в файл настроек settings.py
Далее создадим функции которые будут подключаться через сигналы к контролируемым таблица. В нашем случае это будет journal_save_handler для контроля на созданием новой записи и редактирования существующей и journal_delete_handler для контроля над удаляемыми данными.
changelog/signals.py
Теперь вся системы логирования готова. Осталось подключить ее к какой нибудь таблице следующим образом:
handlers (обработчики)
django
django.request
Basic logging configuration¶
When configuring logging, it makes sense to
Create a LOGGING dictionary¶
In your settings.py :
It nearly always makes sense to retain and extend the default logging configuration by setting disable_existing_loggers to False .
Configure a handler¶
This example configures a single handler named file , that uses Python’s FileHandler to save logs of level DEBUG and higher to the file general.log (at the project root):
Different handler classes take different configuration options. For more information on available handler classes, see the AdminEmailHandler provided by Django and the various handler classes provided by Python.
Logging levels can also be set on the handlers (by default, they accept log messages of all levels). Using the example above, adding:
would define a handler configuration that only accepts records of level DEBUG and higher.
Configure a logger mapping¶
To send records to this handler, configure a logger mapping to use it for example:
The mapping’s name determines which log records it will process. This configuration ( '' ) is unnamed. That means that it will process records from all loggers (see Use logger namespacing below on how to use the mapping name to determine the loggers for which it will process records).
It will forward messages of levels DEBUG and higher to the handler named file .
Note that a logger can forward messages to multiple handlers, so the relation between loggers and handlers is many-to-many.
in your code, you will find that message in the file general.log in the root of the project.
Configure a formatter¶
By default, the final log output contains the message part of each log record . Use a formatter if you want to include additional data. First name and define your formatters - this example defines formatters named verbose and simple :
See LogRecord attributes for the LogRecord attributes you can include.
To apply a formatter to a handler, add a formatter entry to the handler’s dictionary referring to the formatter by name, for example:
Use logger namespacing¶
The unnamed logging configuration '' captures logs from any Python application. A named logging configuration will capture logs only from loggers with matching names.
The namespace of a logger instance is defined using getLogger() . For example in views.py of my_app :
will create a logger in the my_app.views namespace. __name__ allows you to organize log messages according to their provenance within your project’s applications automatically. It also ensures that you will not experience name collisions.
A logger mapping named my_app.views will capture records from this logger:
A logger mapping named my_app will be more permissive, capturing records from loggers anywhere within the my_app namespace (including my_app.views , my_app.utils , and so on):
You can also define logger namespacing explicitly:
and set up logger mappings accordingly.
Using logger hierarchies and propagation¶
Logger naming is hierarchical. my_app is the parent of my_app.views , which is the parent of my_app.views.private . Unless specified otherwise, logger mappings will propagate the records they process to their parents - a record from a logger in the my_app.views.private namespace will be handled by a mapping for both my_app and my_app.views .
To manage this behavior, set the propagation key on the mappings you define:
propagate defaults to True . In this example, the logs from my_app.views.private will not be handled by the parent, but logs from my_app.views will.
Стандартные логгеры
В среде веб-сервера у нас часто есть рутинная информация, которую мы должны регистрировать. Django предоставляет несколько стандартных логгеров (loggers) для ведения логов.
Configure responsive logging¶
Logging is most useful when it contains as much information as possible, but not information that you don’t need - and how much you need depends upon what you’re doing. When you’re debugging, you need a level of information that would be excessive and unhelpful if you had to deal with it in production.
You can configure logging to provide you with the level of detail you need, when you need it. Rather than manually change configuration to achieve this, a better way is to apply configuration automatically according to the environment.
For example, you could set an environment variable DJANGO_LOG_LEVEL appropriately in your development and staging environments, and make use of it in a logger mapping thus:
- so that unless the environment specifies a lower log level, this configuration will only forward records of severity WARNING and above to its handler.
Other options in the configuration (such as the level or formatter option of handlers) can be similarly managed.
Базовая конфигурация
Вы можете использовать метод basicConfig (**kwargs) для настройки ведения логов:
«Вы можете заметить, что модуль logging нарушает руководство по стилю PEP8 и использует соглашения camelCase в именнование переменных. Это потому, что он был адоптирован из пакета Log4j (утилиты ведения логов в Java). Это известная проблема в пакете, но к тому времени, когда было решено добавить ее в стандартную библиотеку, она уже была принята пользователями, и изменение ее в соответствии с требованиями PEP8 вызовет проблемы обратной совместимости ». (Источник)
Вот некоторые из часто используемых параметров для basicConfig():
Теперь будут регистрироваться все события на уровне DEBUG или выше.
Вы можете настроить корневой logger еще больше, используя дополнительные параметры для basicConfig(), которые можно найти здесь.
Следует отметить, что вызов basicConfig() для настройки корневого logger работает, только если корневой logger не был настроен ранее. По сути, эта функция может быть вызвана только один раз.
debug(), info(), warning(), error() и crit() также автоматически вызывают basicConfig() без аргументов, если он ранее не вызывался. Это означает, что после первого вызова одной из вышеперечисленных функций вы больше не сможете изменить настройки корневого logger.
Классы и функции
До сих пор мы видели logger по умолчанию с именем root, который используется модулем logging всякий раз, когда его функции вызываются непосредственно таким образом: logging.debug(). Вы можете (и должны) определить свой собственный logger, создав объект класса Logger, особенно если ваше приложение имеет несколько модулей. Давайте посмотрим на некоторые классы и функции в модуле.
Наиболее часто используемые классы, определенные в модуле logging, следующие:
Из всего перечисленного мы в основном имеем дело с объектами класса Logger, которые создаются с помощью функции уровня модуля logging.getLogger(name). Многократные вызовы getLogger() с одним и тем же именем возвращают ссылку на один и тот же объект Logger, что избавляет нас от передачи объектов logger в каждую часть, где это необходимо. Вот пример:
Этот код создает пользовательский logger с именем example_logger, но в отличие от корневого logger, имя настраиваемого регистратора не является частью выходного формата по умолчанию и должна быть добавлена в конфигурацию. Конфигурирование его в формате для отображения имени logger даст вывод, подобный этому:
Опять же, в отличие от корневого logger, пользовательский logger нельзя настроить с помощью basicConfig(). Вы должны настроить его с помощью Handlers и Formatters:
AdminEmailHandler ¶
The built-in AdminEmailHandler deserves a mention in the context of security. If its include_html option is enabled, the email message it sends will contain a full traceback, with names and values of local variables at each level of the stack, plus the values of your Django settings (in other words, the same level of detail that is exposed in a web page when DEBUG is True ).
It’s generally not considered a good idea to send such potentially sensitive information over email. Consider instead using one of the many third-party services to which detailed logs can be sent to get the best of multiple worlds – the rich information of full tracebacks, clear management of who is notified and has access to the information, and so on.
django.server
Security implications¶
The logging system handles potentially sensitive information. For example, the log record may contain information about a web request or a stack trace, while some of the data you collect in your own loggers may also have security implications. You need to be sure you know:
- what information is collected
- where it will subsequently be stored
- how it will be transferred
- who might have access to it.
To help control the collection of sensitive information, you can explicitly designate certain sensitive information to be filtered out of error reports – read more about how to filter error reports .
The cast of players¶
A Python logging configuration consists of four parts:
Loggers¶
A logger is the entry point into the logging system. Each logger is a named bucket to which messages can be written for processing.
A logger is configured to have a log level. This log level describes the severity of the messages that the logger will handle. Python defines the following log levels:
- DEBUG : Low level system information for debugging purposes
- INFO : General system information
- WARNING : Information describing a minor problem that has occurred.
- ERROR : Information describing a major problem that has occurred.
- CRITICAL : Information describing a critical problem that has occurred.
Each message that is written to the logger is a Log Record. Each log record also has a log level indicating the severity of that specific message. A log record can also contain useful metadata that describes the event that is being logged. This can include details such as a stack trace or an error code.
When a message is given to the logger, the log level of the message is compared to the log level of the logger. If the log level of the message meets or exceeds the log level of the logger itself, the message will undergo further processing. If it doesn’t, the message will be ignored.
Once a logger has determined that a message needs to be processed, it is passed to a Handler.
Handlers¶
The handler is the engine that determines what happens to each message in a logger. It describes a particular logging behavior, such as writing a message to the screen, to a file, or to a network socket.
Like loggers, handlers also have a log level. If the log level of a log record doesn’t meet or exceed the level of the handler, the handler will ignore the message.
A logger can have multiple handlers, and each handler can have a different log level. In this way, it is possible to provide different forms of notification depending on the importance of a message. For example, you could install one handler that forwards ERROR and CRITICAL messages to a paging service, while a second handler logs all messages (including ERROR and CRITICAL messages) to a file for later analysis.
Filters¶
A filter is used to provide additional control over which log records are passed from logger to handler.
By default, any log message that meets log level requirements will be handled. However, by installing a filter, you can place additional criteria on the logging process. For example, you could install a filter that only allows ERROR messages from a particular source to be emitted.
Filters can also be used to modify the logging record prior to being emitted. For example, you could write a filter that downgrades ERROR log records to WARNING records if a particular set of criteria are met.
Filters can be installed on loggers or on handlers; multiple filters can be used in a chain to perform multiple filtering actions.
Formatters¶
Ultimately, a log record needs to be rendered as text. Formatters describe the exact format of that text. A formatter usually consists of a Python formatting string containing LogRecord attributes ; however, you can also write custom formatters to implement specific formatting behavior.
Заключение
В этой статье мы рассмотрели основы ведения логов с помощью Django. Логирование очень важно для поиска ошибок во время создания приложения, а так же может облегчить задачу поиска тех или иных прошедших события во время эксплуатации любого приложения. Надеюсь эта статья была вам полезна.
Python programmers will often use print() in their code as a quick and convenient debugging tool. Using the logging framework is only a little more effort than that, but it’s much more elegant and flexible. As well as being useful for debugging, logging can also provide you with more - and better structured - information about the state and health of your application.
Создание простого приложение
Команда django-admin создаст для нас начальный скелет приложения:
в вашем каталоге test вы увидите новую папку приложения:
В качестве последнего шага, чтобы убедиться, что все работает, перейдем в каталог test и запустим встроенный веб-сервер Django:
Custom logging configuration¶
If you don’t want to use Python’s dictConfig format to configure your logger, you can specify your own configuration scheme.
The LOGGING_CONFIG setting defines the callable that will be used to configure Django’s loggers. By default, it points at Python’s logging.config.dictConfig() function. However, if you want to use a different configuration process, you can use any other callable that takes a single argument. The contents of LOGGING will be provided as the value of that argument when logging is configured.
Установка Django
В виртуальной среде установим Django:
Проверим как установилась Django выводом версии:
Теперь перейдем к созданию простого приложения loggers.
Настройка логгирования в Django
Мы можем изменить настройки логирование непосредственно в представление (view), сразу после импоритирования. По умолчанию Django использует формат dictConfig для настройки handlers, loggers, filters и formatters. Эти настройки задаются с помощью словаря LOGGING, который объединяется с конфигурацией ведения журнала Django по умолчанию. Выглядеть это будет следующим образом:
Или что бы настройки логгирования применились для всего проекта лучше всего это сделать в файле настроек loggers/settings.py. Просто добавив в конец файла следующие строки:
Рассмотрим это настройки более подробно.
Читайте также: