Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving the request object in a custom Django logging handler

I have a custom Logging handler that I want to handle all logging message levels (INFO, WARN, DEBUG, ERROR, etc.) and send that to a data analytics server. For each message, the data will include fields on the record and on the original request object.

The problem is that I have not seen the request object attached to any of the records. I found on the official documentation that only django.request messages have the request object attached to the record, but no mention of what specifically django.request messages are. (https://docs.djangoproject.com/en/1.9/topics/logging/#django-request).

What are django.request messages? How/When are they fired? How can I reroute every logging message to have the request object on it so that my handler can attach that data that will be sent to a proxy server?

----handler----

class LogHandler(logging.Handler):
    request = None

    def __init__(self, request=None):
        logging.Handler.__init__(self)

    def parse_record_to_json(self, record):
        import json

        created = datetime.datetime.fromtimestamp(record.created)
        return {
            'timestamp': created.strftime('%m/%d/%Y %H:%M:%S'),
            'method': record.funcName,
            'level': record.levelname,
            'line': record.lineno,
            'module': record.module,
            'message': record.getMessage(),
            'path': record.pathname,
        }

    def emit(self, record):
        user_id = None
        try:
            self.request = record.request
            if self.request.user.is_authenticated():
                user_id = self.request.user.id
        except:
            print "this must not be a django.request message"
            self.request = None

        from .event import SendEvent
        json_record = self.parse_record_to_json(record)
        level = json_record.pop('level', None)

        SendEvent(key="server_log",
                    name=level,
                    request=self.request,
                    obj=json_record,
                    user=user_id)

-----settings.py-----

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': '%(levelname)s  %(name)s  %(asctime)s %(filename)s:%(lineno)s] %(message)s',
        },
    },
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'standard',
        },
        'null': {
            'level': 'DEBUG',
            'class': 'django.utils.log.NullHandler',
        },
        'splunk':{
            'class':'proj.common.handlers.LogHandler',

        }
    },
    # 'root': {
    #     'handlers': ['console', 'loghandler',],
    #     'level': 'INFO',
    #     'formatter':'standard',
    # },
    'loggers': {
        'django':{
            'handlers':['console'],
            'level':'INFO',
            'formatter':'standard',
        },
        'py.warnings':{
            'handlers': ['null',],
            'propagate': False,
        },
        'django.request':{
            'handlers':['console','loghandler'],
            'propogate':False,
        },
    }
}
like image 989
user3516853 Avatar asked Jan 19 '16 20:01

user3516853


People also ask

What is request object in Django?

Django uses request and response objects to pass state through the system. When a page is requested, Django creates an HttpRequest object that contains metadata about the request. Then Django loads the appropriate view, passing the HttpRequest as the first argument to the view function.

Where are Django logs stored?

The Django One-Click application employs Gunicorn and Upstart. Application level logging can be found in /var/log/upstart/gunicorn. log By default, Gunicorn logs to stderr and Upstart will collect output to stderr/stdout in /var/log/upstart/$JOB_NAME.

How do you disable verbose error handling and logging in Django?

If you don't want to configure logging at all (or you want to manually configure logging using your own approach), you can set LOGGING_CONFIG to None . This will disable the configuration process for Django's default logging.

How does Django logging work?

A logger is the entry point into the logging system. Each logger is a named bucket to which messages can be written for processing. A logger is configured to have a log level. This log level describes the severity of the messages that the logger will handle.


1 Answers

To answer the “what is a django.request message”: The django.request logger is one of the Python loggers provided with Django. So, a django.request message is a log message sent to the django.request logger. As you've found, the Django documentation says:

Messages to this logger have the following extra context:

  • status_code: The HTTP response code associated with the request.
  • request: The request object that generated the logging message.

What may not be obvious is that “extra context” is provided with the logging message, and those items become attributes on the LogRecord instance.

So yes, in the LogHandler.emit method you defined, the record parameter is the LogRecord. The record.request attribute will be the HTTP request object, if the record was created on the django.request logger.

Your LogHandler will only receive messages if you direct them there, for example via the Django setting LOGGING['loggers']['django.request']['handlers'].

like image 107
bignose Avatar answered Sep 29 '22 23:09

bignose