Supercharge Your Django Logging: Custom Filters for the Win
The Problem
Default Django logs are okay, but they lack juicy details like IP addresses, browsers, and user info. Wouldn't it be cool to have all that at your fingertips?
Enter Custom Logging Filters
Django lets us create custom filters to add extra info to our logs. Here's how:
- First, set up your logging config in settings.py. It'll look something like this:
LOGGING = {
# ... other config ...
"filters": {
"custom_request_filter": {
"()": "path.to.your.CustomRequestFilter",
},
},
# ... more config ...
}
- Now, let's create our custom filter:
import logging
from django.core.exceptions import ObjectDoesNotExist
class CustomRequestFilter(logging.Filter):
def filter(self, record):
if hasattr(record, "request"):
request = record.request # type: ignore
try:
record.ip_address = request.META.get("REMOTE_ADDR", "-")
record.device_type = request.META.get("HTTP_SEC_CH_UA_PLATFORM")
# ex string - "Brave";v="129", "Not=A?Brand";v="8", "Chromium";v="129"
record.browser = request.META.get("HTTP_SEC_CH_UA").split(";")[0]
except AttributeError:
record.browser = "-"
record.device_type = "-"
record.ip_address = "-"
try:
record.user = request.user.username if request.user.is_authenticated else "unauthenticated"
except (ObjectDoesNotExist, AttributeError):
record.user = "unauthenticated"
record.http_status = getattr(record, "status_code", "-")
else:
record.ip_address = "-"
record.user = "-"
record.device_type = "-"
record.browser = "-"
record.http_status = "-"
return True
- Apply the filter to your handlers:
"handlers": {
"file": {
# ... other config ...
"filters": ["custom_request_filter"],
},
},
- Update your formatter to use the new attributes:
"formatters": {
"verbose": {
"format": "{asctime} {ip_address} {user} {message}",
"style": "{",
},
},
Bonus: Logging in WebSocket Consumers
Don't forget about your WebSocket consumers! They need love too. Here's a quick tip:
class FocusSessionConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.request = self._generate_request_metadata()
# ... other connect logic ...
logger.info(f"{self.user.username} connected", extra={"request": self.request})
def _generate_request_metadata(self):
request = HttpRequest()
# Populate request.META with relevant info
return request
Here are some code snippets from how i use it in django channels context
consumer.py
class FocusSessionConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.user = self.scope["user"]
self.username = self.scope["url_route"]["kwargs"]["username"]
self.request = self._generate_request_metadata()
await self.channel_layer.group_add(self.session_group_name, self.channel_name) # type: ignore
await self.accept()
# othe code related to project
logger.info(f"{self.user.username} connected to session '{self.session_id}'", extra={"request": self.request})
await self.update_session_followers_list_to_all_clients()
def _generate_request_metadata(self):
request = HttpRequest()
user_agent = str(self.scope["headers"][4][1].strip())
try:
ip_add = self.scope["client"][0]
except Exception:
ip_add = "-"
try:
user_os = user_agent.rsplit("(")[1].split(";")[0]
except Exception:
user_os = "-"
request.META = {
"REMOTE_ADDR": ip_add,
"HTTP_SEC_CH_UA_PLATFORM": user_os,
}
request.user = self.user
return request
Wrapping Up
With these custom filters, your logs will be bursting with useful info. Happy debugging, folks!
Remember, logging is like a good curry - it should be rich, flavorful, and help you find the source of the problem. Now go forth and log like a pro! 🚀📝
p.s - i am still learning so there could be some mistakes in this blog. please test your code after implementing.
Subscribe to my newsletter
Read articles from Saurav Sharma directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Saurav Sharma
Saurav Sharma
I am a Self Taught Backend developer With 3 Years of Experience. Currently, I am working at a tech Startup based in The Bahamas. Here are my skills so far - 💪Expert at - 🔹Python 🔹Django 🔹Django REST framework 🔹Celery ( for distributed tasks ) 🔹ORM ( Know how to write fast queries & design models ) 🔹Django 3rd party packages along with postgresQL and mysql as Databases. 🔹Cache using Redis & Memcache 🔹Numpy + OpenCV for Image Processing 🔹ElasticSearch + HayStack 🔹Linux ( Debian ) 😎 Working Knowledge - Html, CSS, JavaScript, Ajax, Jquery, Git ( GitHub & BitBucket ), Basic React & React Native, Linux ( Arch ), MongoDB, VPS 🤠 Currently Learning - 🔹More Deep Dive into Django 🔹Docker 🔹Making APIs more Robust 🔹NeoVim 🔹System Design ☺️ Will Be Learn in upcoming months - 🔹GraphQL 🔹 Rust language Other than above, there is not a single technology ever exists that i can't master if needed.