Ведение журнала

Краткое руководство по ведению журнала

Django использует встроенный loggingмодуль Python для ведения системного журнала. Использование этого модуля подробно обсуждается в собственной документации Python. Однако, если вы никогда не использовали фреймворк ведения журналов Python (или даже если использовали), вот краткое руководство.

Состав игроков

Конфигурация ведения журнала Python состоит из четырех частей:

Логгеры

Регистратор - это точка входа в систему регистрации. Каждый регистратор представляет собой именованную корзину, в которую можно записывать сообщения для обработки.

Регистратор настроен на уровень ведения журнала . Этот уровень журнала описывает серьезность сообщений, обрабатываемых регистратором. Python определяет следующие уровни журнала:

  • DEBUG: Системная информация низкого уровня для отладки.
  • INFO: Общая информация о системе
  • WARNING: Информация, описывающая возникшую незначительную проблему.
  • ERROR: Информация, описывающая возникшую серьезную проблему.
  • CRITICAL: Информация, описывающая возникшую критическую проблему.

Каждое сообщение, записываемое в регистратор, является записью журнала . Каждая запись журнала также имеет уровень журнала, указывающий серьезность этого конкретного сообщения. Запись журнала также может содержать полезные метаданные, описывающие регистрируемое событие. Это может включать такие детали, как трассировка стека или код ошибки.

Когда сообщение отправляется регистратору, уровень журнала сообщения сравнивается с уровнем журнала регистратора. Если уровень журнала сообщения соответствует уровню журнала самого регистратора или превышает его, сообщение будет подвергнуто дальнейшей обработке. В противном случае сообщение будет проигнорировано.

Как только регистратор определил, что сообщение необходимо обработать, оно передается обработчику .

Обработчики

Обработчик - это механизм, который определяет, что происходит с каждым сообщением в регистраторе. Он описывает конкретное поведение журналирования, такое как запись сообщения на экран, в файл или в сетевой сокет.

Как и регистраторы, обработчики также имеют уровень ведения журнала. Если уровень журнала записи журнала не соответствует или превышает уровень обработчика, обработчик проигнорирует сообщение.

У регистратора может быть несколько обработчиков, и каждый обработчик может иметь свой уровень журнала. Таким образом, можно предоставить различные формы уведомления в зависимости от важности сообщения. Например, вы можете установить один обработчик, который пересылает ERRORи CRITICALсообщения службе подкачки, в то время как второй обработчик регистрирует все сообщения (включая ERRORи CRITICALсообщения) в файле для последующего анализа.

Фильтры

Фильтр используется для обеспечения дополнительного контроля над тем, какие записи журнала передаются от регистратора к обработчику.

По умолчанию обрабатывается любое сообщение журнала, соответствующее требованиям уровня журнала. Однако, установив фильтр, вы можете добавить дополнительные критерии к процессу ведения журнала. Например, вы можете установить фильтр, который разрешает ERRORотправку сообщений только из определенного источника.

Фильтры также можно использовать для изменения записи журнала перед отправкой. Например, вы можете написать фильтр, который понижает рейтинг ERRORзаписей журнала до WARNINGзаписей, если выполняется определенный набор критериев.

Фильтры могут быть установлены на регистраторах или на обработчиках; несколько фильтров можно использовать в цепочке для выполнения нескольких действий фильтрации.

Форматировщики

В конечном итоге запись журнала должна быть отображена в виде текста. Средства форматирования описывают точный формат этого текста. Средство форматирования обычно состоит из строки форматирования Python, содержащей атрибуты LogRecord ; однако вы также можете написать собственные средства форматирования для реализации определенного поведения форматирования.

Использование журнала

После того, как вы настроили свои регистраторы, обработчики, фильтры и средства форматирования, вам необходимо поместить вызовы регистрации в свой код. Использование фреймворка ведения журнала работает следующим образом:

# import the logging library
import logging

# Get an instance of a logger
logger = logging.getLogger(__name__)

def my_view(request, arg1, arg):
    ...
    if bad_mojo:
        # Log an error message
        logger.error('Something went wrong!')

Вот и все! Каждый раз, когда bad_mojoусловие активируется, будет записываться запись в журнал ошибок.

Именование логгеров

Вызов для logging.getLogger()получения (создания, если необходимо) экземпляра регистратора. Экземпляр регистратора идентифицируется по имени. Это имя используется для идентификации регистратора в целях настройки.

По соглашению, имя регистратора обычно __name__является именем модуля Python, который содержит регистратор. Это позволяет фильтровать и обрабатывать вызовы журналирования для каждого модуля. Однако, если у вас есть другой способ организации сообщений журнала, вы можете указать любое имя, разделенное точками, для идентификации вашего регистратора:

# Get an instance of a specific named logger
logger = logging.getLogger('project.interesting.stuff')

Пунктирные пути имен регистраторов определяют иерархию. project.interestingРегистратор считается родителем project.interesting.stuffрегистратора; projectрегистратор является родителем project.interestingрегистратора.

Почему важна иерархия? Ну, потому что регистраторы могут быть настроены на передачу своих вызовов регистрации своим родителям. Таким образом, вы можете определить единый набор обработчиков в корне дерева регистраторов и захватывать все вызовы регистрации в поддереве регистраторов. Регистратор определен в projectпространстве имен будет перехватывать все сообщения протоколирования , выданные на project.interestingи project.interesting.stuffлесорубов.

Это распространение можно контролировать для каждого регистратора. Если вы не хотите, чтобы конкретный регистратор передавался своим родителям, вы можете отключить это поведение.

Выполнение журнала вызовов

Экземпляр регистратора содержит метод записи для каждого из уровней журнала по умолчанию:

  • logger.debug()
  • logger.info()
  • logger.warning()
  • logger.error()
  • logger.critical()

Доступны два других вызова журнала:

  • logger.log(): Вручную генерирует сообщение журнала с определенным уровнем журнала.
  • logger.exception(): Создает ERRORсообщение регистрации уровня, охватывающее текущий фрейм стека исключений.

Настройка логирования

Недостаточно просто поместить в код вызовы логирования. Вам также необходимо настроить средства ведения журнала, обработчики, фильтры и средства форматирования, чтобы обеспечить возможность использования вывода журнала.

Библиотека ведения журнала Python предоставляет несколько методов настройки ведения журнала, от программного интерфейса до файлов конфигурации. По умолчанию Django использует формат dictConfig .

Чтобы настроить ведение журнала, вы используете LOGGINGсловарь настроек ведения журнала. Эти параметры описывают средства ведения журнала, обработчики, фильтры и средства форматирования, которые вы хотите использовать в настройках ведения журнала, а также уровни журналов и другие свойства, которые должны иметь эти компоненты.

По умолчанию этот LOGGINGпараметр объединяется с конфигурацией ведения журнала Django по умолчанию, используя следующую схему.

Если для disable_existing_loggersключа в LOGGINGdictConfig задано значение True(что является dictConfigзначением по умолчанию, если ключ отсутствует), то все регистраторы из конфигурации по умолчанию будут отключены. Отключенные регистраторы - это не то же самое, что удаленные; регистратор по-прежнему будет существовать, но молча отбрасывает все, что было зарегистрировано в нем, даже не передавая записи в родительский регистратор. Таким образом, вы должны быть очень осторожны при использовании ; вероятно, это не то, что вы хотите. Вместо этого, вы можете установить , чтобы и переопределить некоторые или все регистраторы по умолчанию; или вы можете установить , чтобы и ручка каротаж конфиг себя .'disable_existing_loggers': Truedisable_existing_loggersFalseLOGGING_CONFIGNone

Ведение журнала настраивается как часть общей setup()функции Django . Таким образом, вы можете быть уверены, что регистраторы всегда готовы к использованию в коде вашего проекта.

Примеры

Полная документация по формату dictConfig - лучший источник информации о словарях конфигурации журналирования. Однако, чтобы дать вам представление о том, что возможно, вот несколько примеров.

Для начала вот небольшая конфигурация, которая позволит вам выводить все сообщения журнала на консоль:

settings.py
import os

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'root': {
        'handlers': ['console'],
        'level': 'WARNING',
    },
}

Это настраивает родительский rootрегистратор для отправки сообщений с WARNINGуровнем и выше обработчику консоли. Установив уровень на INFOили, DEBUGвы можете отображать больше сообщений. Это может быть полезно во время разработки.

Затем мы можем добавить более детальное ведение журнала. Вот пример того, как заставить систему журналирования печатать больше сообщений только из django с именем logger:

settings.py
import os

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'root': {
        'handlers': ['console'],
        'level': 'WARNING',
    },
    'loggers': {
        'django': {
            'handlers': ['console'],
            'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
            'propagate': False,
        },
    },
}

По умолчанию эта конфигурация отправляет сообщения от djangoрегистратора уровня INFOили выше на консоль. Это тот же уровень, что и конфигурация ведения журнала по умолчанию в Django, за исключением того, что конфигурация по умолчанию отображает записи журнала только тогда, когда DEBUG=True. Django не регистрирует много INFOсообщений такого уровня. Однако с помощью этой конфигурации вы также можете установить переменную среды DJANGO_LOG_LEVEL=DEBUGдля просмотра всех журналов отладки Django, которые очень подробны, поскольку включают все запросы к базе данных.

Вам не нужно входить в консоль. Вот конфигурация, которая записывает все журналы из django с именем logger в локальный файл:

settings.py
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': '/path/to/django/debug.log',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

Если вы используете этот пример, обязательно измените 'filename'путь на место, доступное для записи пользователю, запускающему приложение Django.

Наконец, вот пример довольно сложной настройки ведения журнала:

settings.py
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
            'style': '{',
        },
        'simple': {
            'format': '{levelname} {message}',
            'style': '{',
        },
    },
    'filters': {
        'special': {
            '()': 'project.logging.SpecialFilter',
            'foo': 'bar',
        },
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'mail_admins': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
            'filters': ['special']
        }
    },
    'loggers': {
        'django': {
            'handlers': ['console'],
            'propagate': True,
        },
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': False,
        },
        'myproject.custom': {
            'handlers': ['console', 'mail_admins'],
            'level': 'INFO',
            'filters': ['special']
        }
    }
}

Эта конфигурация ведения журнала выполняет следующие функции:

  • Определяет конфигурацию как имеющуюся в формате «dictConfig версии 1». В настоящее время это единственная версия формата dictConfig.

  • Определяет два средства форматирования:

    • simple, который выводит имя уровня журнала (например, DEBUG) и сообщение журнала.

      formatСтрока является нормальным Python форматирования строки описания деталей , которые будут выводиться на каждой лесозаготовительной линии. Полный список деталей, которые можно вывести, можно найти в Объектах средства форматирования .

    • verbose, который выводит имя уровня журнала, сообщение журнала, а также время, процесс, поток и модуль, которые генерируют сообщение журнала.

  • Определяет два фильтра:

    • project.logging.SpecialFilter, используя псевдоним special. Если для этого фильтра требуются дополнительные аргументы, их можно указать в качестве дополнительных ключей в словаре конфигурации фильтра. В этом случае при fooсоздании barэкземпляра аргументу будет присвоено значение SpecialFilter.
    • django.utils.log.RequireDebugTrue, который передает записи, когда DEBUGесть True.
  • Определяет два обработчика:

    • console, a StreamHandler, который печатает любое INFO (или большее) сообщение в sys.stderr. Этот обработчик использует simple выходной формат.
    • mail_admins, an AdminEmailHandler, который отправляет на сайт любое ERROR (или более высокое) сообщение ADMINS. Этот обработчик использует specialфильтр.
  • Настраивает три регистратора:

    • django, который передает все сообщения consoleобработчику.
    • django.request, который передает все ERRORсообщения mail_adminsобработчику. Кроме того, этот регистратор помечен, чтобы не распространять сообщения. Это означает, что сообщения журнала, записанные в django.request, не будут обрабатываться djangoрегистратором.
    • myproject.custom, который передает все сообщения на уровне INFO или выше, которые также передают specialфильтр двум обработчикам - consoleи mail_admins. Это означает, что INFOсообщения всех уровней (или более высоких) будут выводиться на консоль; ERRORи CRITICAL сообщения также будут выводиться через электронную почту.

Пользовательская конфигурация ведения журнала

Если вы не хотите использовать формат Python dictConfig для настройки вашего регистратора, вы можете указать свою собственную схему конфигурации.

Этот LOGGING_CONFIGпараметр определяет вызываемый объект, который будет использоваться для настройки регистраторов Django. По умолчанию он указывает на logging.config.dictConfig()функцию Python . Однако, если вы хотите использовать другой процесс настройки, вы можете использовать любой другой вызываемый объект, который принимает единственный аргумент. Содержимое LOGGINGбудет предоставлено как значение этого аргумента при настройке ведения журнала.

Отключение конфигурации ведения журнала

Если вы вообще не хотите настраивать ведение журнала (или хотите настроить ведение журнала вручную, используя собственный подход), вы можете установить LOGGING_CONFIGзначение None. Это отключит процесс настройки журнала Django по умолчанию .

Установка LOGGING_CONFIGдля Noneтолько означает , что автоматический процесс конфигурации отключен, не войдя себя. Если вы отключите процесс настройки, Django по-прежнему будет выполнять вызовы журналирования, возвращаясь к любому определенному поведению журналирования по умолчанию.

Вот пример, который отключает конфигурацию ведения журнала Django, а затем вручную настраивает ведение журнала:

settings.py
LOGGING_CONFIG = None

import logging.config
logging.config.dictConfig(...)

Обратите внимание, что процесс конфигурации по умолчанию вызывается только LOGGING_CONFIGпосле полной загрузки параметров. Напротив, ручная настройка ведения журнала в файле настроек немедленно загрузит конфигурацию ведения журнала. Таким образом, ваша конфигурация ведения журнала должна отображаться после любых настроек, от которых она зависит.

Расширения журналирования Django

Django предоставляет ряд утилит для удовлетворения уникальных требований ведения журнала в среде веб-сервера.

Логгеры

Django предоставляет несколько встроенных регистраторов.

django

Регистратор всех сообщений в djangoиерархии. Никакие сообщения не публикуются с этим именем, а вместо этого используются один из указанных ниже регистраторов.

django.request

Журнал сообщений, связанных с обработкой запросов. Ответы 5XX выдаются как ERRORсообщения; Ответы 4XX выдаются как WARNING сообщения. Запросы, которые регистрируются в django.securityрегистраторе, не регистрируются django.request.

Сообщения в этот регистратор имеют следующий дополнительный контекст:

  • status_code: Код ответа HTTP, связанный с запросом.
  • request: Объект запроса, создавший сообщение журнала.

django.server

Журнал сообщений, связанных с обработкой запросов, полученных сервером, вызванным runserverкомандой. Ответы HTTP 5XX регистрируются как ERROR сообщения, ответы 4XX регистрируются как WARNINGсообщения, а все остальное регистрируется как INFO.

Сообщения в этот регистратор имеют следующий дополнительный контекст:

  • status_code: Код ответа HTTP, связанный с запросом.
  • request: Объект запроса, создавший сообщение журнала.

django.template

Журнал сообщений, связанных с отображением шаблонов.

  • Отсутствующие переменные контекста регистрируются как DEBUGсообщения.

django.db.backends

Сообщения, относящиеся к взаимодействию кода с базой данных. Например, каждый оператор SQL уровня приложения, выполняемый запросом, регистрируется на DEBUGуровне этого регистратора.

Сообщения в этот регистратор имеют следующий дополнительный контекст:

  • duration: Время, затраченное на выполнение оператора SQL.
  • sql: Выполняемый оператор SQL.
  • params: Параметры, которые использовались в вызове SQL.

По соображениям производительности ведение журнала SQL включается, только если для settings.DEBUGнего установлено значение True, независимо от уровня ведения журнала или установленных обработчиков.

Эта регистрация не включает в себя инициализацию рамки уровня (например ) или запросы управления транзакциями (например , , и ). Включите ведение журнала запросов в своей базе данных, если вы хотите просмотреть все запросы к базе данных.SET TIMEZONEBEGINCOMMITROLLBACK

django.security.*

Регистраторы безопасности будут получать сообщения о любых SuspiciousOperationошибках, связанных с безопасностью. Для каждого подтипа ошибки безопасности, включая все ошибки, есть подзаголовок SuspiciousOperation. Уровень события журнала зависит от того, где обрабатывается исключение. Большинство событий регистрируется как предупреждение, тогда как любое сообщение SuspiciousOperation, достигнутое обработчиком WSGI, регистрируется как ошибка. Например, когда HTTP- Hostзаголовок включен в запрос от клиента, который не соответствует ALLOWED_HOSTS, Django вернет ответ 400, а сообщение об ошибке будет записано в django.security.DisallowedHostрегистратор.

Эти события djangoжурнала по умолчанию будут поступать в средство ведения журнала, которое присылает сообщения об ошибках администраторам DEBUG=False. Запросы, приводящие к ответу 400 из-за a SuspiciousOperation, не будут регистрироваться в django.request регистраторе, а только в django.securityрегистраторе.

Чтобы отключить определенный тип SuspiciousOperation, вы можете переопределить этот конкретный регистратор, следуя этому примеру:

'handlers': {
    'null': {
        'class': 'logging.NullHandler',
    },
},
'loggers': {
    'django.security.DisallowedHost': {
        'handlers': ['null'],
        'propagate': False,
    },
},

Другие django.securityрегистраторы, не основанные на SuspiciousOperation:

django.db.backends.schema

Регистрирует SQL-запросы, которые выполняются во время изменений схемы в базе данных платформой миграции . Обратите внимание, что он не будет регистрировать запросы, выполняемые RunPython. Сообщения в этот регистратор имеют paramsи sqlв дополнительном контексте (но в отличие от django.db.backendsпродолжительности). Значения имеют то же значение, что описано в django.db.backends .

Обработчики

Django предоставляет один обработчик журналов в дополнение к тем, которые предоставляются модулем ведения журналов Python.

classAdminEmailHandler ( include_html = False , email_backend = None , reporter_class = None )

Этот обработчик отправляет электронное письмо на сайт ADMINSдля каждого полученного сообщения журнала.

Если запись журнала содержит requestатрибут, полная информация о запросе будет включена в электронное письмо. Тема электронного письма будет включать фразу «внутренний IP-адрес», если в INTERNAL_IPSнастройках указан IP-адрес клиента ; в противном случае он будет включать «ВНЕШНИЙ IP-адрес».

Если запись журнала содержит информацию о трассировке стека, эта трассировка стека будет включена в электронное письмо.

include_htmlАргумент AdminEmailHandlerиспользуется для управления , включает ли отслеживающий электронной почты вложения HTML , содержащий полное содержимое веб - страницы отладки , который был бы выработан , если бы DEBUGбыли True. Чтобы установить это значение в вашей конфигурации, включите его в определение обработчика django.utils.log.AdminEmailHandler, например:

'handlers': {
    'mail_admins': {
        'level': 'ERROR',
        'class': 'django.utils.log.AdminEmailHandler',
        'include_html': True,
    }
},

Обратите внимание, что эта HTML-версия электронного письма содержит полную трассировку с именами и значениями локальных переменных на каждом уровне стека, а также значениями ваших настроек Django. Эта информация потенциально очень конфиденциальна, и вы можете не захотеть пересылать ее по электронной почте. Подумайте об использовании чего-то вроде Sentry, чтобы получить лучшее из обоих миров - богатую информацию о полных трассировках плюс безопасность, чтобы не отправлять информацию по электронной почте. Вы также можете явно указать определенную конфиденциальную информацию, которая будет отфильтрована из отчетов об ошибках - подробнее о фильтрации отчетов об ошибках .

Установив email_backendаргумент AdminEmailHandler, сервер электронной почты , который используется обработчиком, может быть переопределен, например:

'handlers': {
    'mail_admins': {
        'level': 'ERROR',
        'class': 'django.utils.log.AdminEmailHandler',
        'email_backend': 'django.core.mail.backends.filebased.EmailBackend',
    }
},

По умолчанию будет использоваться экземпляр серверной части электронной почты, указанный в EMAIL_BACKEND.

reporter_classАргумент AdminEmailHandlerпозволяет обеспечивая django.views.debug.ExceptionReporterподкласс , чтобы настроить текст обратного прослеживания , переданный в теле сообщения электронной почты. Вы указываете путь импорта строки к классу, который хотите использовать, например:

'handlers': {
    'mail_admins': {
        'level': 'ERROR',
        'class': 'django.utils.log.AdminEmailHandler',
        'include_html': True,
        'reporter_class': 'somepackage.error_reporter.CustomErrorReporter'
    }
},
send_mail( тема , сообщение , * аргументы , ** kwargs )

Отправляет электронные письма администраторам. Чтобы настроить это поведение, вы можете создать подкласс AdminEmailHandlerкласса и переопределить этот метод.

Фильтры

Django предоставляет некоторые фильтры журналов в дополнение к тем, которые предоставляются модулем ведения журналов Python.

классCallbackFilter ( обратный вызов )

Этот фильтр принимает функцию обратного вызова (которая должна принимать единственный аргумент - запись, которая должна быть записана в журнал) и вызывает ее для каждой записи, проходящей через фильтр. Обработка этой записи не будет продолжена, если обратный вызов вернет False.

Например, чтобы отфильтровать UnreadablePostError (вызывается, когда пользователь отменяет загрузку) из электронных писем администратора, вы должны создать функцию фильтра:

from django.http import UnreadablePostError

def skip_unreadable_post(record):
    if record.exc_info:
        exc_type, exc_value = record.exc_info[:2]
        if isinstance(exc_value, UnreadablePostError):
            return False
    return True

а затем добавьте его в конфигурацию ведения журнала:

'filters': {
    'skip_unreadable_posts': {
        '()': 'django.utils.log.CallbackFilter',
        'callback': skip_unreadable_post,
    }
},
'handlers': {
    'mail_admins': {
        'level': 'ERROR',
        'filters': ['skip_unreadable_posts'],
        'class': 'django.utils.log.AdminEmailHandler'
    }
},
класс RequireDebugFalse

Этот фильтр будет передавать записи, только если settings.DEBUG имеет значение False.

Этот фильтр используется в LOGGING конфигурации по умолчанию следующим образом, чтобы гарантировать, что AdminEmailHandlerсообщения об ошибках будут отправляться администраторам только DEBUGв следующих случаях False:

'filters': {
    'require_debug_false': {
        '()': 'django.utils.log.RequireDebugFalse',
    }
},
'handlers': {
    'mail_admins': {
        'level': 'ERROR',
        'filters': ['require_debug_false'],
        'class': 'django.utils.log.AdminEmailHandler'
    }
},
класс RequireDebugTrue

Этот фильтр похож на RequireDebugFalse, за исключением того, что записи передаются только тогда, когда DEBUGесть True.

Конфигурация журналирования по умолчанию в Django

По умолчанию Django настраивает следующие журналы:

Когда DEBUGэто True:

  • djangoРегистратор отправляет сообщения в djangoиерархии ( за исключением django.server) на INFOуровне или выше на консоль.

Когда DEBUGэто False:

  • djangoРегистратор отправляет сообщения в djangoиерархии (кроме django.server) с ERRORили CRITICALуровня до AdminEmailHandler.

Независимо от стоимости DEBUG:

  • Django.server регистратор отправляет сообщения на INFOуровне или выше на консоль.

Все регистраторы, кроме django.server, распространяют ведение журнала своим родителям, вплоть до корневого djangoрегистратора. consoleИ mail_admins обработчики прикреплены к корневой регистратор , чтобы обеспечить поведение , описанное выше.

Смотрите также Настройка входа , чтобы узнать , как вы можете дополнить или заменить эту конфигурацию регистрации по умолчанию , определенной в Джанго / Utils / log.py .

Copyright ©2021 All rights reserved