7.18 The One-Page Quick Reference
You now have a toolkit. But in the heat of debugging, you won't remember which tool to reach for. This section is your decision support systemβthe cheat sheet you print out and tape to your wall.
Decision tree: Which tool for which scenario?
Let's walk through the decision process. You have a problem. Here's how you choose your tool:
Question 1: Is this in production or development?
-
Production: Never use debuggers. Options are: APM tools (DataDog, New Relic),
py-spyin attach mode, structured log analysis, or replicate in development -
Development: Continue to Question 2
Question 2: Do you know roughly where the problem is?
-
Yes, I know the file/function: Set a debugger breakpoint at that location β Step through execution
-
No idea where to start: Continue to Question 3
Question 3: What are you trying to understand?
-
"What code runs when I do X?": Framework DevTools first (Django Debug Toolbar, React DevTools). Look at request/render timeline
-
"Why is this slow?": Profiler.
py-spyfor Python, Chrome Performance tab for JavaScript -
"What's calling this function?": Debugger with call stack inspection, or
console.trace()for JavaScript -
"How does this feature work across files?": Debugger with step-through, following execution across boundaries
-
"What changed between versions?":
git bisectto find the breaking commit
Question 4: Can you reproduce the issue?
-
Yes, consistently: Debugger is your primary tool. Set breakpoint, reproduce, step through
-
No, it's intermittent: Logging with correlation IDs. Add structured logs at key points, trigger the bug, search logs by request ID
-
Only under load: Profiler in sampling mode, or APM tool
Here's the decision tree in visual form you can reference:
Problem in production?
ββ Yes β APM tools / py-spy attach / structured logs
ββ No (development) β Know where the issue is?
ββ Yes β Debugger at that location
ββ No β What are you trying to understand?
ββ What runs? β Framework DevTools
ββ Why slow? β Profiler
ββ What calls this? β Debugger call stack / console.trace()
ββ How does feature work? β Debugger step-through
ββ What changed? β git bisect
Common debugger commands across languages
When you're in a debugger, these commands work similarly across languages, though the exact syntax varies. Memorizing this mapping lets you context-switch between languages:
| Action | Python pdb | Node.js inspector | Chrome DevTools | GDB/LLDB |
| -------------------------- | ------------------- | -------------------------- | ------------------- | ----------------- |
| Continue execution | c | c or cont | F8 | c |
| Step over (next line) | n | n or next | F10 | n |
| Step into (enter function) | s | s or step | F11 | s |
| Step out (exit function) | r | o or out | Shift+F11 | finish |
| Print variable | p var | exec var | hover or console | p var |
| Show location | l | list | automatic | l |
| Call stack | w | bt or backtrace | visible in pane | bt |
| Move up stack | u | up | click in stack pane | up |
| Move down stack | d | down | click in stack pane | down |
| List breakpoints | b | breakpoints | visible in pane | info break |
| Set breakpoint | b filename:line | sb('file', line) | click gutter | b filename:line |
| Conditional breakpoint | b line, condition | sb('file', line, 'cond') | right-click gutter | b line if cond |
| Quit debugger | q | .exit or Ctrl+C | close tab | q |
Notice the pattern: n for next/step-over is universal. s for step-into is universal. c for continue is universal. If you remember these three, you can debug in any language.
The key insight: Most debugging involves only five commands: continue, step-over, step-into, print, and examining the call stack. Everything else is situational. Master these five and you're 90% effective.
Framework-specific tool URLs and installation
When you need to set up tracing tools in a new project, you shouldn't have to google "how to install django debug toolbar" for the tenth time. Here's your reference:
Python/Django:
# Django Debug Toolbar
pip install django-debug-toolbar
# Add to settings.py INSTALLED_APPS:
# 'debug_toolbar'
# Add to settings.py MIDDLEWARE (near top):
# 'debug_toolbar.middleware.DebugToolbarMiddleware'
# Add to settings.py:
# INTERNAL_IPS = ['127.0.0.1']
# Docs: https://django-debug-toolbar.readthedocs.io/
Python/Flask:
# Flask-DebugToolbar
pip install flask-debugtoolbar
# In your app.py:
# from flask_debugtoolbar import DebugToolbarExtension
# app.config['SECRET_KEY'] = 'dev'
# toolbar = DebugToolbarExtension(app)
# Docs: https://flask-debugtoolbar.readthedocs.io/
Python Profiling:
# py-spy (global install recommended)
pip install py-spy
# Or: cargo install py-spy
# Usage:
# py-spy top --pid <pid>
# py-spy record -o profile.svg --pid <pid>
# Docs: https://github.com/benfred/py-spy
JavaScript/React:
# React DevTools (browser extension)
# Chrome: https://chrome.google.com/webstore
# Search "React Developer Tools"
# Firefox: https://addons.mozilla.org/en-US/firefox/
# Search "React Developer Tools"
# After install, look for βοΈ tabs in DevTools
JavaScript/Vue:
# Vue DevTools
# Chrome: https://chrome.google.com/webstore
# Search "Vue.js devtools"
# Firefox: https://addons.mozilla.org/en-US/firefox/
# Search "Vue.js devtools"
# Standalone app for non-browser debugging:
# npm install -g @vue/devtools
# vue-devtools
JavaScript/Node.js:
# Built-in inspector (no installation needed)
node --inspect your-script.js
# Then open chrome://inspect in Chrome
# Or use VS Code debugger:
# Create .vscode/launch.json with:
# {
# "type": "node",
# "request": "launch",
# "name": "Debug",
# "program": "${workspaceFolder}/index.js"
# }
General Profiling:
# Python cProfile (built-in)
python -m cProfile -o output.prof script.py
python -m pstats output.prof
# Visualization
pip install snakeviz
snakeviz output.prof
# Node.js profiling (built-in)
node --prof script.js
node --prof-process isolate-*-v8.log > processed.txt
The pattern to notice: Most frameworks in mature ecosystems have official or community-standard debugging tools. Always search "[framework name] debugging tools" before building your own instrumentation. These tools are maintained, documented, and encode community best practices.
Performance profiling command templates
Copy-paste these commands when you need to profile. They're configured with sensible defaults you can modify:
Python Application Profiling:
# Basic profiling with cProfile
python -m cProfile -s cumtime script.py | head -30
# Save profile for later analysis
python -m cProfile -o profile.stats script.py
# Analyze saved profile
python -m pstats profile.stats
# In pstats shell:
# sort cumtime
# stats 20
# Visual analysis with SnakeViz
pip install snakeviz
python -m cProfile -o profile.stats script.py
snakeviz profile.stats
Django Request Profiling:
# Profile a specific view
python -m cProfile -o profile.stats manage.py runserver --noreload
# Then make requests and analyze profile.stats
# Note: --noreload prevents Django from spawning worker process
# Alternative: Use django-silk for per-request profiling
pip install django-silk
# Add 'silk' to INSTALLED_APPS
# Add silk middleware
# Visit /silk/ to see per-request profiles
Python Production-Safe Profiling:
# Attach py-spy to running process
py-spy top --pid <pid>
# Record for 30 seconds, then analyze
py-spy record -o profile.svg --duration 30 --pid <pid>
# Profile a script from start
py-spy record -o profile.svg -- python script.py
# Sample at higher rate for more detail (default is 100Hz)
py-spy record --rate 500 -o profile.svg --pid <pid>
Node.js Application Profiling:
# Built-in profiler
node --prof app.js
# Run your workload, then Ctrl+C
node --prof-process isolate-*-v8.log > profile.txt
less profile.txt
# Chrome DevTools profiling
node --inspect app.js
# Open chrome://inspect
# Click "inspect", go to Profiler tab
# Record while running workload
# Or with inspect-brk to pause at start
node --inspect-brk app.js
JavaScript Browser Profiling:
# Chrome DevTools Performance profiling:
# 1. Open DevTools (F12)
# 2. Go to Performance tab
# 3. Click record (Ctrl+E)
# 4. Perform action
# 5. Stop recording
# 6. Analyze flame chart
# React-specific profiling:
# 1. Open React DevTools
# 2. Go to Profiler tab
# 3. Click record
# 4. Interact with app
# 5. Stop recording
# 6. Analyze component render times
Memory Profiling (Python):
# Install memory_profiler
pip install memory_profiler
# Add @profile decorator to functions
# Then run:
python -m memory_profiler script.py
# Or for line-by-line:
kernprof -l -v script.py
Memory Profiling (Node.js):
# Heap snapshot in Chrome DevTools
node --inspect app.js
# Open chrome://inspect
# Click "inspect", go to Memory tab
# Take heap snapshot before and after action
# Compare snapshots to find leaks
# Or use clinic.js
npm install -g clinic
clinic doctor -- node app.js
# Generates detailed performance report
Database Query Profiling:
# Django: Use Debug Toolbar in development
# Shows all queries, execution time, and duplicates
# Or enable query logging:
# In settings.py:
# LOGGING = {
# 'handlers': {
# 'console': {
# 'class': 'logging.StreamHandler',
# },
# },
# 'loggers': {
# 'django.db.backends': {
# 'handlers': ['console'],
# 'level': 'DEBUG',
# },
# },
# }
# PostgreSQL query timing:
# In psql:
# \timing on
# Then run queries
# MySQL slow query log:
# Add to my.cnf:
# slow_query_log = 1
# long_query_time = 0.1 # Log queries over 100ms
# slow_query_log_file = /var/log/mysql/slow.log
The pattern to notice: All these commands follow a similar structure: tool β output format β target. Profilers generate data, then you visualize it. The two-step process (capture then analyze) lets you profile in one environment and analyze in another.
Checkpoint: Are you actually ready?
Before moving on, let's test your toolkit readiness. Can you answer "yes" to all of these?
-
You could set up a debugger in a new Python or JavaScript project in under 5 minutes
-
You know which tool to reach for when code is slow vs. when you don't understand what code runs
-
You have at least one structured logging or profiling command saved somewhere for quick access
-
You've actually used (not just read about) at least 3 tools from your language's checklist
If you answered "no" to any of these, stop here. Go back and actually practice with the tools. Read through the toolkit checklist again, but this time, actually install and test each tool. Set a breakpoint. Profile something. Trace a function call.
This is the key insight: The toolkit isn't the knowledge of what tools exist. The toolkit is the muscle memory of reaching for the right tool without thinking. You build that through practice, not reading.
The difference between a developer who knows these tools exist and a developer who has them in their toolkit is about 30 minutes of hands-on practice per tool. That's it. Not days. Not weeks. Thirty minutes of "let me actually try this on my current project."
Do that now, before you read further. Your future self, debugging at midnight, will thank you.