开发者

Where to call logging.setLoggerClass() in Django

开发者 https://www.devze.com 2023-03-13 09:12 出处:网络
I\'m using Django 1.3 with the standard Python logging. I\'ve configured it to log errors to a file: \'loggers\': {

I'm using Django 1.3 with the standard Python logging. I've configured it to log errors to a file:

'loggers': {
    'django': {
        'handlers': ['logfile'],
        'level': 'ERROR',
        'propagate': False,
  开发者_JAVA技巧  },

I also want the username of the currently logged in Django user to be logged. For that I've defined my own formatter with a format that includes "%(username)s" and created my own logging class (named RequestLogger) which populates the extra username attribute. The only thing left to do is to call:

logging.setLoggerClass(RequestLogger)

The question is: where should I call this? I've tried putting it into __init__.py (at project level) and into settings.py. Both of those work fine with the Django dev server, but when running in Apache using WSGI I get errors like this in the Apache error log:

[error] Traceback (most recent call last):
[error]   File "/usr/lib/python2.7/logging/__init__.py", line 842, in emit
[error]     msg = self.format(record)
[error]   File "/usr/lib/python2.7/logging/__init__.py", line 719, in format
[error]     return fmt.format(record)
[error]   File "/usr/lib/python2.7/logging/__init__.py", line 467, in format
[error]     s = self._fmt % record.__dict__
[error] KeyError: 'username'
[error] Logged from file base.py, line 209

This seems to imply that in WSGI the Django logger gets initialised before my logging.setLoggerClass() call. (It's definitely getting called, because my own logging works and includes the username).


Rather than use a custom logging class, you can use a Filter on your handlers to do this. See this post, and this part of the docs.


Vinay Sajip's solution of using a filter avoids this problem entirely, so I'm accepting his answer. The documentation on how to configure a filter using a dictionary is a bit lacking, so I'll put an example here:

LOGGING = {
    ...
    'filters': {
        'add_django_request': {
            '()': 'logger.AddDjangoRequestFilter',
        },
    },
    'handlers': {
        'myhandler': {
            ...
            'filters': ['add_django_request'],
        },
    },

In case anyone is wondering, it does work with a custom Logger class if you call setLoggerClass inside the .wsgi file, before the import django.core.handlers.wsgi line (for Apache) and also inside manage.py (for the Django dev server). The filter solution is better, though.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号