Django 设置默认日志记录

100

我似乎无法弄清如何为我的Django安装设置“默认”记录器。 我想在settings.py中使用Django 1.3的新LOGGING设置。

我查看了Django Logging Doc's example,但在我看来,它们只设置了处理程序,这些处理程序将为特定记录器进行记录。 在他们的示例中,他们为名为'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`!
4个回答

164

问题解决了...

你可以通过使用空字符串引用来设置“catch all”记录器:''

例如,在下面的设置中,我将所有日志事件保存到logs/mylog.log中,除了django.request日志事件,它将保存到logs/django_request.log中。因为我django.request记录器的'propagate'被设置为False,所以日志事件永远不会到达“catch all”记录器。

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
Chris,Django文档并不令人困惑。感谢您。 - user290043
5
微调一下:该评论暗示了django.request日志记录器会影响SQL日志记录。如果要重定向SQL日志记录,您需要为“django.db”定义一个日志记录器。django.request日志记录器处理5xx和4xx的HTTP响应。 - rych
1
这对像我一样的新手很有帮助:记录器将创建日志文件,但您必须首先创建“logs/”文件夹 :-)。否则,在运行./manange.py runserver时会出现错误。@Chris W.感谢您提供的示例日志设置。它对我帮助很大! - hobbes3
3
如果你按照上述配置执行logger = logging.getLogger('foo'); logger.warn('bar');,那么default处理程序将捕获该日志记录,并且类似于 <time> WARN: foo: bar 的内容将出现在 logs/mylog.log 中。 - Chris W.
11
谢谢,看起来这个“''”表示根日志记录器。这个有用的信息在 Django 文档中没有找到。 - Eino Mäkitalo
显示剩余3条评论

28

正如你在回答中所说,Chris,定义默认日志记录器的选项之一是将空字符串用作其键。

但是,我认为旨在定义特殊记录器的正确方式是在日志配置字典的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' 在某种程度上是合理的,但我仍然觉得他们将 root 条目移动到字典的根部在从2.6 fileConfig逻辑平稳过渡到2.7 dictConfig时有点不一致。 - Antony Hatchkins

3
我制作了一个快速示例,以检查在配置字典中引用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

在这两种情况下,我都能够调试并确定所有三个记录器(l1l2root)都引用了相同的记录器实例,即根记录器。

希望这能帮助其他像我一样被两种不同配置根记录器的方式所困惑的人。


3
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',

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接