Ведение журнала по умолчанию для настройки Django

94

Кажется, я не могу понять, как настроить регистратор "по умолчанию" для моей установки Django. Я хотел бы использовать новую LOGGINGнастройку Django 1.3 в settings.py.

Я просмотрел пример Django Logging Doc , но мне кажется, что они только настраивают обработчики, которые будут вести журнал для определенных регистраторов. В случае их примера они устанавливают обработчик для регистраторов с именами «django», «django.request» и «myproject.custom».

Все, что я хочу сделать, это установить значение по умолчанию, logging.handlers.RotatingFileHandlerкоторое по умолчанию будет обрабатывать все регистраторы. то есть, если я создаю новый модуль где-нибудь в моем проекте, и это обозначается чем-то вроде:, my_app_name.my_new_moduleя должен иметь возможность сделать это, и все журналы будут переходить в журналы смены файлов.

# In file './my_app_name/my_new_module.py'
import logging
logger = logging.getLogger('my_app_name.my_new_module')
logger.debug('Hello logs!') # <-- This should get logged to my RotatingFileHandler that I setup in `settings.py`!
Крис В.
источник

Ответы:

154

Догадаться...

Вы можете установить «все» логгер с помощью ссылки его с пустой строкой: ''.

В качестве примера, в следующей настройке у меня сохраняются все события журнала logs/mylog.log, за исключением django.requestсобытий журнала, которые будут сохранены в logs/django_request.log. Потому что 'propagate'установлено на Falseмой django.requestрегистратор, то журнал события никогда не достигнут в «всех» журналирования.

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': {
        'default': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/mylog.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },  
        'request_handler': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/django_request.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },
    },
    'loggers': {
        '': {
            'handlers': ['default'],
            'level': 'DEBUG',
            'propagate': True
        },
        'django.request': {
            'handlers': ['request_handler'],
            'level': 'DEBUG',
            'propagate': False
        },
    }
}
Крис В.
источник
2
Крис, документы Django по этому поводу не сбивают с толку. Спасибо за это.
5
Небольшое исправление: комментарий подразумевает, что на ведение журнала sql повлияет регистратор django.request. Чтобы перенаправить ведение журнала sql, вы должны определить регистратор для 'django.db'. Регистратор django.request обрабатывает HTTP-ответы 5xx и 4xx.
rych
В этом помогают другие нубы вроде меня: регистратор создаст файлы журнала, но logs/сначала вам нужно создать папку :-). В противном случае вы получите ошибку при запуске ./manange.py runserver. @Chris W. Спасибо за ваш пример настроек ведения журнала. Это мне очень помогло!
hobbes3
3
@arindamroychowdhury При вышеуказанной конфигурации , если вы делаете logger = logging.getLogger('foo'); logger.warn('bar');то defaultобработчик будет ловить , что протоколирование и что - то вроде <time> WARN: foo: barбудет в конечном итоге вlogs/mylog.log
Chris W.
8
Спасибо, похоже, что это '' означает корневой регистратор. Эта полезная информация не была найдена в документации Django.
Eino Mäkitalo
25

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

Однако я думаю, что предполагаемый способ - определить специальный регистратор под rootключом словаря конфигурации регистрации. Я нашел это в документации Python :

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

Вот конфигурация из вашего ответа, измененная для использования rootключа:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': {
        'default': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/mylog.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },  
        'request_handler': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': 'logs/django_request.log',
            'maxBytes': 1024*1024*5, # 5 MB
            'backupCount': 5,
            'formatter':'standard',
        },
    },
    'root': {
        'handlers': ['default'],
        'level': 'DEBUG'
    },
    'loggers': {
        'django.request': {
            'handlers': ['request_handler'],
            'level': 'DEBUG',
            'propagate': False
        },
    }
}

Честно говоря, я не вижу никакой разницы в поведении между двумя конфигурациями. Похоже, что определение регистратора с ключом пустой строки изменит корневой регистратор, потому logging.getLogger('')что вернет корневой регистратор.

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

Дон Киркби
источник
Да, верно, извините за ошибку! Хотя использование '' вместо 'root' в некоторой степени логично, я все же считаю немного непоследовательным с их стороны перенос rootзаписи в корень dict в процессе плавного перехода с логики 2.6 fileConfig на 2.7 dictConfig.
Энтони Хэтчкинс
2
import logging
logger = logging.getLogger(__name__)

после добавления:

logging.basicConfig(
    level = logging.DEBUG,
    format = '%(name)s %(levelname)s %(message)s',
)

мы можем изменить формат на:

format = '"%(levelname)s:%(name)s:%(message)s"  ',

или

format = '%(name)s %(asctime)s %(levelname)s %(message)s',
Сержио
источник
0

Я сделал быстрый образец, чтобы проверить, какая конфигурация используется, когда в config dict есть ссылка на rootключ и пустой ''регистратор.

import logging.config

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'fmt1': {
            'format': '[FMT1] %(asctime)-15s %(message)s',
        },
        'fmt2': {
            'format': '[FMT2] %(asctime)-15s %(message)s',
        }
    },
    'handlers': {
        'console1': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'fmt1',
        },
        'console2': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'fmt2',
        },
    },
    # First config for root logger: console1 -> fmt1
    'root': {
        'handlers': ['console1'],
        'level': 'DEBUG',
        'propagate': True,
    },
    'loggers': {
        # Second config for root logger: console2 -> fmt2
        '': {
            'handlers': ['console2'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

logging.config.dictConfig(LOGGING)

l1 = logging.getLogger()
l2 = logging.getLogger('')
root = logging.root

l1.info("l1")
l2.info("l2")
root.info("root logger")

Выводит следующий результат:

[FMT1] 2018-12-18 17:24:47,691 l1
[FMT1] 2018-12-18 17:24:47,691 l2
[FMT1] 2018-12-18 17:24:47,691 root logger

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

[FMT2] 2018-12-18 17:25:43,757 l1
[FMT2] 2018-12-18 17:25:43,757 l2
[FMT2] 2018-12-18 17:25:43,757 root logger

В обоих случаях я смог отладить и определить, что все три регистратора ( l1, l2и root) ссылаются на один и тот же экземпляр регистратора, корневой регистратор.

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

Antwane
источник