https://github.com/peidrao/tracegarden
Request-scoped backend observability toolkit for Django, Flask, and FastAPI: captures SQL/HTTP/Celery/OTel traces with secure redaction, local UI, and zero global singleton coupling.
https://github.com/peidrao/tracegarden
backend debugging developer-tools django fastapi flask observability python
Last synced: 2 months ago
JSON representation
Request-scoped backend observability toolkit for Django, Flask, and FastAPI: captures SQL/HTTP/Celery/OTel traces with secure redaction, local UI, and zero global singleton coupling.
- Host: GitHub
- URL: https://github.com/peidrao/tracegarden
- Owner: peidrao
- License: mit
- Created: 2026-04-09T12:37:12.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-04-13T15:29:53.000Z (2 months ago)
- Last Synced: 2026-04-13T17:37:22.949Z (2 months ago)
- Topics: backend, debugging, developer-tools, django, fastapi, flask, observability, python
- Language: Python
- Homepage: https://pypi.org/project/tracegarden/
- Size: 432 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# TraceGarden
Developer-first visual backend devtools for Django, Flask, and FastAPI.
TraceGarden captures the full request lifecycle — DB queries, outgoing HTTP, OpenTelemetry spans, and **Celery tasks stitched back to the web request that triggered them** — into local SQLite and serves a built-in UI at `/__tracegarden`.
## Why TraceGarden?
**Django Debug Toolbar is great for SQL.** TraceGarden goes further:
| Capability | Django Debug Toolbar | TraceGarden |
|---|---|---|
| SQL queries + N+1 detection | ✅ | ✅ |
| Outgoing HTTP calls inspector | ❌ | ✅ |
| Celery task timeline | ❌ | ✅ |
| **Celery task ↔ parent request stitching** | ❌ | ✅ |
| OpenTelemetry span ingestion | ❌ | ✅ |
| Flask / FastAPI support | ❌ | ✅ |
| Trace bundle export (JSON) | ❌ | ✅ |
The key feature is **Celery stitching**: when a web request enqueues a background task, TraceGarden links the task's full lifecycle (PENDING → STARTED → SUCCESS/FAILURE, with duration and result) back to the originating request in the UI. No external infrastructure required.
## Features
- WSGI + ASGI support (`Django`, `Flask`, `FastAPI`)
- DB query fingerprinting, grouping, duplicate and N+1 detection
- Outgoing HTTP inspector (`requests` / `httpx`)
- Celery stitching (`web request → queued task → worker state`)
- OTel-native span ingestion into local TraceGarden UI
- Trace bundle export (single JSON artifact)
- Redaction by default: auth tokens, passwords, cookies never reach SQLite
- UI token protection
## Installation
```bash
pip install tracegarden
# extras
pip install tracegarden[django]
pip install tracegarden[flask]
pip install tracegarden[fastapi]
pip install tracegarden[celery]
```
## Quick Start
### Flask (two lines)
```python
from flask import Flask
from tracegarden import TraceGarden
app = Flask(__name__)
TraceGarden(app, ui_token="dev-secret")
```
### FastAPI (two lines)
```python
from fastapi import FastAPI
from tracegarden import TraceGarden
app = FastAPI()
TraceGarden(app, ui_token="dev-secret")
```
### Django
```python
# settings.py
INSTALLED_APPS = [
...,
"tracegarden.integrations.django",
]
MIDDLEWARE = [
"tracegarden.integrations.django.middleware.TraceGardenMiddleware",
...,
]
TRACEGARDEN = {
"enabled": True,
"ui_token": "dev-secret",
}
# urls.py
from tracegarden.ui.routes import mount_django_urls
urlpatterns = mount_django_urls() + urlpatterns
```
### Celery stitching
Add one call after your Celery app is created:
```python
# celery.py
from celery import Celery
from tracegarden.integrations.celery.signals import connect_signals
from tracegarden.core.storage import TraceStorage
app = Celery("myproject")
storage = TraceStorage()
connect_signals(storage=storage)
```
TraceGarden will automatically propagate trace IDs through task headers and correlate each task back to the web request that dispatched it — including task duration, result, and failure details.
## UI Access
Default route: `/__tracegarden/`
Pass token using one of:
- header: `X-TraceGarden-Token: dev-secret`
- query param: `?token=dev-secret`
- cookie: `tg_token=dev-secret`
## Screenshots


## OpenTelemetry
```python
from tracegarden.otel.setup import setup_otel
setup_otel(
service_name="my-api",
also_export_to_tracegarden=True,
)
```
## Body capture
Request and response bodies are **not captured by default**. Enable with:
```python
TraceGarden(app, ui_token="dev-secret", capture_request_body=True, capture_response_body=True)
```
Bodies are truncated at `max_body_bytes` (default 64 KB) and redacted before storage.
## What gets recorded
See [docs/WHAT_IT_RECORDS.md](docs/WHAT_IT_RECORDS.md).
## End-to-end examples
See [examples/README.md](examples/README.md).
## License
MIT