How can I add additional metadata into the django.server logs?

Hi,

What I am trying to do is as given below,

  • The current logs for the server requests look like the following.
[29/Nov/2023 02:33:50] "GET /api/health/ HTTP/1.1" 200 31
  • The new format I need is as following.
[29/Nov/2023 02:33:50] "GET /api/health/ HTTP/1.1" 200 31 user-id:<user_id>

I tried to add a logs filter.

"django.server": {
             "()": "django.utils.log.ServerFormatter",
            "format": "[%(asctime)s] %(levelname)s %(module)s %(message)s user_id:%(user_id)s  ",
        }

The following is my filter.

class UserIdFilter(logging.Filter):
    def filter(self, record):
        user_id = None
        if hasattr(record, "request"):
            try:
                user_id = record.request.user.id
            except Exception as exp:
                user_id = "anon"
        if not user_id:
           user_id = "unknown"
        record.user_id = user_id
        return True

The problem is the record object above is a socket.socket object and does not have any request http payload metadata.

What could I do differently to find and append the request user_id to the logs?

What log are you looking at there?

What server and wsgi container are you using for your application?

Hi Ken,

The logs that I need to modify are the default django.server logs that are created for every API call. The project is using django 2.2.28. The application is hosted in an AWS lambda with zappa. So by default the logs go into the Cloudwatch.

Ok, but this implies to me that you might be using runserver for your application, which is an exceedingly bad idea.

(The only place where Django defines a logger “django.server” is in the basehttp.py. At the very top of the file in the comments you’ll see:

CSP is not intended as a first line of defense against content injection vulnerabilities. Instead, CSP is best used as defense-in-depth. It reduces the harm that a malicious injection can cause, but it is not a replacement for careful input validation and output encoding.

Also, quoting directly from the runserver docs:

DO NOT USE THIS SERVER IN A PRODUCTION SETTING. It has not gone through security audits or performance tests. (And that’s how it’s gonna stay. …

The bottom line is you’re taking a fundamentally flawed approach here.

For a reliable and stable deployment, at a minimum you will want to something like gunicorn.

Now, to address your logging question, this is the wrong place in the stack to try and get that information. If you want to log URLs (and possibly POST data as well) associated with a user, you’ll want to use custom middleware to log those requests after the request has been associated with the User object making the request. (We use django-request-logging for this. It works well for us.)