Django Logging: Your Appβs Secret Diary π
Imagine you have a magical diary that writes itself. Every time something happens in your roomβa toy falls, a friend visits, or you find a lost sockβthe diary automatically records it. Thatβs exactly what logging does for your Django app!
The Story of the Helpful Diary
Once upon a time, there was a busy toy store (your Django app). The store owner needed to know everything happening insideβwhen customers arrived, when toys broke, or when something went wrong. So they hired four special helpers:
- The Logging Configuration - The diaryβs rulebook
- Loggers and Handlers - The writers and delivery people
- Log Levels and Formatting - The importance labels and handwriting style
- Built-in Loggers - Djangoβs own team of diarists
Letβs meet each one!
1. Logging Configuration π§
What Is It?
The logging configuration is like setting up rules for your diary. It answers questions like:
- Where should messages go? (A file? The screen?)
- How detailed should they be?
- What format should they follow?
The Magic Spell (settings.py)
# settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'root': {
'handlers': ['console'],
'level': 'DEBUG',
},
}
What does this mean?
| Part | Meaning |
|---|---|
version: 1 |
Always use 1 (itβs the only version!) |
disable_existing_loggers |
Keep Djangoβs own loggers working |
handlers |
Where to send messages |
root |
The main logger settings |
Real-World Example
# A complete, beginner-friendly setup
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'simple': {
'format': '{levelname} {message}',
'style': '{',
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'simple',
},
},
'loggers': {
'myapp': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
2. Loggers and Handlers π
The Story
Think of Loggers as writers who write messages. Handlers are delivery people who decide where those messages go.
graph TD A["Your Code"] --> B["Logger"] B --> C["Handler 1: Console"] B --> D["Handler 2: File"] B --> E["Handler 3: Email"] C --> F["Your Screen"] D --> G["log.txt"] E --> H["Your Inbox"]
Creating a Logger
import logging
# Create your personal writer
logger = logging.getLogger('myapp')
# Now write messages!
logger.info('A customer arrived!')
logger.warning('Running low on toys!')
logger.error('A toy broke!')
Common Handlers
| Handler | What It Does | Example |
|---|---|---|
StreamHandler |
Prints to screen | See errors while coding |
FileHandler |
Writes to a file | Keep a permanent record |
RotatingFileHandler |
Creates new files when full | Avoid giant log files |
SMTPHandler |
Sends emails | Alert for critical errors |
Example: File Handler Setup
'handlers': {
'file': {
'class': 'logging.FileHandler',
'filename': 'debug.log',
'formatter': 'simple',
},
},
3. Log Levels and Formatting β
The Importance Ladder
Not all messages are equally important. Log levels are like shouting volumes:
graph TD A["DEBUG π"] --> B["INFO βΉοΈ"] B --> C["WARNING β οΈ"] C --> D["ERROR β"] D --> E["CRITICAL π¨"] style E fill:#ff6b6b style D fill:#ffa94d style C fill:#ffd43b style B fill:#69db7c style A fill:#748ffc
| Level | Number | When to Use |
|---|---|---|
| DEBUG | 10 | Tiny details (for detectives) |
| INFO | 20 | Normal events (βUser logged inβ) |
| WARNING | 30 | Something odd (βLow disk spaceβ) |
| ERROR | 40 | Something broke |
| CRITICAL | 50 | EMERGENCY! App might crash |
Using Levels in Code
import logging
logger = logging.getLogger('myapp')
logger.debug('Checking inventory...')
logger.info('New order placed!')
logger.warning('Only 5 toys left!')
logger.error('Payment failed!')
logger.critical('Database down!')
Formatting: Making Messages Pretty
Formatters decide how messages look. Think of it as choosing a handwriting style.
'formatters': {
'detailed': {
'format': '{asctime} {levelname} {name} {message}',
'style': '{',
},
},
Output:
2024-01-15 10:30:45 INFO myapp New order placed!
Format Variables
| Variable | Shows |
|---|---|
{asctime} |
Date and time |
{levelname} |
DEBUG, INFO, etc. |
{name} |
Logger name |
{message} |
Your message |
{filename} |
Which file |
{lineno} |
Which line number |
4. Django Built-in Loggers π
Django comes with its own team of writers, already watching different parts of your app!
The Built-in Team
graph TD A["Django Built-in Loggers"] A --> B["django"] A --> C["django.request"] A --> D["django.server"] A --> E["django.template"] A --> F["django.db.backends"] A --> G["django.security"]
What Each Logger Watches
| Logger | What It Records |
|---|---|
django |
The parent of all Django loggers |
django.request |
Every web request (404s, 500s) |
django.server |
Development server messages |
django.template |
Template errors |
django.db.backends |
Database queries |
django.security |
Security issues |
Example: Capture Database Queries
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
Now youβll see every database query!
Example: Catch 404 and 500 Errors
'loggers': {
'django.request': {
'handlers': ['file'],
'level': 'WARNING',
},
},
Putting It All Together π
Hereβs a complete, production-ready setup:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '{asctime} {levelname} {name}: {message}',
'style': '{',
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'standard',
},
'file': {
'class': 'logging.FileHandler',
'filename': 'app.log',
'formatter': 'standard',
},
},
'loggers': {
'myapp': {
'handlers': ['console', 'file'],
'level': 'DEBUG',
},
'django.request': {
'handlers': ['file'],
'level': 'WARNING',
},
},
}
Quick Reference Card π
βββββββββββββββββββββββββββββββββββββββ
β LOGGING = { β
β 'version': 1, β
β 'formatters': {...}, β
β 'handlers': {...}, β
β 'loggers': {...}, β
β } β
βββββββββββββββββββββββββββββββββββββββ
logger = logging.getLogger('name')
logger.debug() β Tiny details
logger.info() β Normal events
logger.warning() β Odd things
logger.error() β Broken things
logger.critical() β EMERGENCY!
You Did It! π
You now understand Django logging like a pro:
β Configuration - Setting up the rules β Loggers - The message writers β Handlers - Where messages go β Levels - How important each message is β Formatting - How messages look β Built-in Loggers - Djangoβs own helpers
Your Django app now has a magical self-writing diary. Every bug, every visitor, every problemβall recorded automatically. Happy logging! π
