🏠

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?

Question 2: Do you know roughly where the problem is?

Question 3: What are you trying to understand?

Question 4: Can you reproduce the issue?

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?

  1. You could set up a debugger in a new Python or JavaScript project in under 5 minutes

  2. You know which tool to reach for when code is slow vs. when you don't understand what code runs

  3. You have at least one structured logging or profiling command saved somewhere for quick access

  4. 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.