Async-native debug toolbar for Python ASGI frameworks with first-class Litestar support.
Documentation: https://jacobcoffee.github.io/debug-toolbar
Source Code: https://github.com/JacobCoffee/debug-toolbar
- Async-Native: Built from the ground up for async/await patterns
- Framework-Agnostic Core: Core package works with any ASGI framework
- Litestar Integration: First-class plugin support for Litestar applications
- Pluggable Panels: Easy to add, remove, or customize debug panels
- Minimal Overhead: Negligible performance impact when disabled
- Type-Safe: Full type annotations with strict type checking
- Dark/Light Themes: Toggle between dark and light themes
- Flexible Positioning: Place toolbar on any edge (left, right, top, bottom)
- SQL Query Analysis: EXPLAIN query plans for PostgreSQL, SQLite, MySQL, MariaDB
- N+1 Detection: Automatic detection of N+1 query patterns with fix suggestions
- Flame Graphs: Interactive profiling visualization in speedscope format
- Memory Profiling: Multi-backend support (tracemalloc, memray)
- Proactive Alerts: Automatic detection of security, performance, and database issues
- MCP Integration: AI assistant integration for automated debugging with Claude Code
- WebSocket Debugging: Real-time connection tracking with live updates and message inspection
# Core package only
pip install debug-toolbar
# With Litestar integration
pip install debug-toolbar[litestar]
# With Advanced-Alchemy SQLAlchemy panel
pip install debug-toolbar[advanced-alchemy]
# All extras
pip install debug-toolbar[all]Or with uv:
uv add debug-toolbar[litestar]from litestar import Litestar, get
from debug_toolbar.litestar import DebugToolbarPlugin, LitestarDebugToolbarConfig
@get("/")
async def index() -> dict[str, str]:
return {"message": "Hello, World!"}
config = LitestarDebugToolbarConfig(enabled=True)
app = Litestar(
route_handlers=[index],
plugins=[DebugToolbarPlugin(config)],
)from litestar import Litestar
from advanced_alchemy.extensions.litestar import SQLAlchemyPlugin, SQLAlchemyAsyncConfig
from debug_toolbar.litestar import DebugToolbarPlugin, LitestarDebugToolbarConfig
db_config = SQLAlchemyAsyncConfig(connection_string="sqlite+aiosqlite:///app.db")
toolbar_config = LitestarDebugToolbarConfig(
enabled=True,
extra_panels=["debug_toolbar.extras.advanced_alchemy.SQLAlchemyPanel"],
)
app = Litestar(
plugins=[
SQLAlchemyPlugin(config=db_config),
DebugToolbarPlugin(toolbar_config),
],
)from debug_toolbar import DebugToolbar, DebugToolbarConfig
config = DebugToolbarConfig(enabled=True)
toolbar = DebugToolbar(config)
# Wrap your ASGI app
app = toolbar.wrap(your_asgi_app)| Panel | Description |
|---|---|
| Timer | Request timing and CPU time |
| Request | HTTP method, path, headers, cookies |
| Response | Status code, response headers |
| Logging | Log records captured during request |
| Versions | Python and package versions |
| Headers | Categorized headers with security analysis |
| Settings | Application configuration viewer |
| Templates | Jinja2/Mako render tracking |
| Profiling | cProfile/pyinstrument with flame graphs |
| Alerts | Proactive security/performance issue detection |
| Memory | Memory profiling (tracemalloc/memray) |
| Cache | Redis/memcached operation tracking |
| Routes | Application routes (Litestar-specific) |
| Events | Lifecycle hooks and exception handlers (Litestar-specific) |
| WebSocket | Real-time connection tracking, message inspection, live updates |
| SQLAlchemy | Query tracking with N+1 detection (requires advanced-alchemy extra) |
from debug_toolbar.litestar import LitestarDebugToolbarConfig
config = LitestarDebugToolbarConfig(
enabled=True,
exclude_paths=["/_debug_toolbar", "/static", "/health"],
max_request_history=50,
intercept_redirects=False,
show_toolbar_callback=lambda request: request.app.debug,
extra_panels=["myapp.panels.CustomPanel"],
exclude_panels=["VersionsPanel"],
)from typing import Any, ClassVar
from debug_toolbar.core import Panel, RequestContext
class MyCustomPanel(Panel):
panel_id: ClassVar[str] = "MyCustomPanel"
title: ClassVar[str] = "My Panel"
template: ClassVar[str] = "panels/my_panel.html"
has_content: ClassVar[bool] = True
async def generate_stats(self, context: RequestContext) -> dict[str, Any]:
return {"custom_data": "Your debug information here"}# Clone the repository
git clone https://github.com/JacobCoffee/debug-toolbar.git
cd debug-toolbar
# Install dependencies
make dev
# Run tests
make test
# Run all CI checks
make cidebug_toolbar/
├── core/ # Framework-agnostic core
│ ├── panels/ # Built-in panels
│ │ ├── timer.py, request.py, response.py # Default panels
│ │ ├── headers.py, settings.py # Optional panels
│ │ ├── profiling.py, memory/, alerts.py # Advanced panels
│ │ ├── templates.py, cache.py # Integration panels
│ │ └── websocket.py # WebSocket debugging
│ ├── config.py # DebugToolbarConfig
│ ├── context.py # RequestContext (contextvars-based)
│ ├── panel.py # Panel base class
│ ├── storage.py # LRU request history storage
│ └── toolbar.py # DebugToolbar manager
├── litestar/ # Litestar integration
│ ├── panels/ # Litestar-specific panels (routes, events)
│ ├── config.py # LitestarDebugToolbarConfig
│ ├── middleware.py
│ └── plugin.py # DebugToolbarPlugin
└── extras/ # Optional integrations
└── advanced_alchemy/ # SQLAlchemy panel with N+1 detection
This project uses Semantic Versioning.
- Major versions introduce breaking changes
- Major versions support currently supported Litestar versions
- See the Litestar Versioning Policy for details
Contributions are welcome! Please see CONTRIBUTING.rst for guidelines.
MIT License - see LICENSE for details.
Inspired by:













