stratis
stratis

Reputation: 8042

Logging django.request to file instead of console

I am trying to configure my django settings.py to properly use the python logging facility but I've stumbled upon a rather strange problem:

Even after reading the docs, I simply can't find out how to redirect the console printed debug request lines from Django to a file I've specified; Below is part of my logging configuration.

LOGGING = {
    'version': 1,
    'formatters': {
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    }
    'handlers': {
        'file_http': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': r'C:\mysystem-http.log',
            'formatter': 'verbose'
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['file_http'],
            'level': 'DEBUG',
            'propagate': False
        }
    }
}

I keep seeing my console print line of the following format:

[19/Dec/2014 11:48:03] "POST /api/v1/ HTTP/1.1" 200 10

How may I redirect these to a file using the logging facility?

Thanks in advance

Upvotes: 6

Views: 3028

Answers (3)

bitoffdev
bitoffdev

Reputation: 3384

@dikamilo's answer is correct.

Prior to Django 1.10, manage.py runserver ran Django's own WSGIServer implementation, which logged to sys.stderr.

Adding the following code to settings.py will monkey patch the WSGIRequestHandler used by runserver so that all requests are logged via the logging module with the name django.server in order to roughly mimic the behaviour of Django 1.10+.

###############################################################################
# SUPER-JANK PATCH FOR DJANGO RUNSERVER LOGGING PRIOR TO VERSION 1.10
###############################################################################
#
# Add this to settings.py
#
import logging
from django.core.servers.basehttp import WSGIRequestHandler
logger = logging.getLogger('django.server')
def log_message(self, format, *args):
    # Don't bother logging requests for admin images or the favicon.
    if self.path.startswith(self.admin_static_prefix) or self.path == '/favicon.ico':
        return
    msg = format % args
    if args[1][0] in ['1', '4', '5']:
        logger.warn(msg)
    else:
        logger.info(msg)

WSGIRequestHandler.log_message = log_message

It replaces the log_message method, which is responsible for actually writing to stderr.

After adding this patch, you can configure logging as you normally would via LOGGING in settings.py.

Upvotes: 0

dikamilo
dikamilo

Reputation: 667

manage.py runserver is not using logging system for messages like [19/Dec/2014 11:48:03] "POST /api/v1/ HTTP/1.1" 200 10. Instead of this, runserver uses sys.stderr (and sys.stdout for others messages). If you really need to redirect this to file you can override sys.stderr settings.py. Example - logging sys.stderr to file and console:

import sys

class Logger(object):
    def __init__(self):
        self.console = sys.stderr
        self.file = open("runserver.log", "a", 0)

    def write(self, msg):
        self.console.write(msg)
        self.file.write(msg)

sys.stderr = Logger()

In write method you can use logging system to handle this by LOGGING settings as well.

Update:

In Django 1.10, runserver output goes through logging: https://docs.djangoproject.com/en/dev/releases/1.10/#runserver-output-goes-through-logging

Upvotes: 6

Benjamin Toueg
Benjamin Toueg

Reputation: 10867

These outputs are handled by your HTTP server (WSGIServer from the standard library if running in dev mode).

The configuration of your settings.py has nothing to do with it.

Upvotes: 3

Related Questions