stemtrace 0.3.0__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {stemtrace-0.3.0 → stemtrace-0.3.1}/.bumpversion.toml +1 -1
- {stemtrace-0.3.0 → stemtrace-0.3.1}/CHANGELOG.md +37 -1
- {stemtrace-0.3.0 → stemtrace-0.3.1}/PKG-INFO +87 -5
- {stemtrace-0.3.0 → stemtrace-0.3.1}/README.md +86 -4
- {stemtrace-0.3.0 → stemtrace-0.3.1}/docker-compose.yml +1 -1
- {stemtrace-0.3.0 → stemtrace-0.3.1}/examples/celery_app.py +35 -5
- {stemtrace-0.3.0 → stemtrace-0.3.1}/examples/fastapi_integration.py +7 -11
- {stemtrace-0.3.0 → stemtrace-0.3.1}/examples/with_auth.py +2 -3
- stemtrace-0.3.1/examples/with_login.py +43 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/pyproject.toml +2 -1
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/__init__.py +112 -2
- stemtrace-0.3.1/src/stemtrace/server/__main__.py +250 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/api/routes.py +195 -29
- stemtrace-0.3.1/src/stemtrace/server/api/websocket.py +49 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/fastapi/extension.py +33 -3
- stemtrace-0.3.1/src/stemtrace/server/fastapi/form_auth.py +157 -0
- stemtrace-0.3.1/src/stemtrace/server/fastapi/login_routes.py +157 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/fastapi/router.py +3 -1
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/package.json +1 -1
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/static.py +115 -15
- stemtrace-0.3.1/src/stemtrace/server/ui/templates/login.html +153 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/integration/test_workers_refresh.py +1 -1
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_examples.py +50 -2
- stemtrace-0.3.1/tests/unit/test_form_auth.py +135 -0
- stemtrace-0.3.1/tests/unit/test_form_login.py +169 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_init.py +94 -0
- stemtrace-0.3.1/tests/unit/test_routes.py +1186 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_ui_static_prefix.py +13 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/uv.lock +1 -1
- stemtrace-0.3.0/src/stemtrace/server/__main__.py +0 -136
- stemtrace-0.3.0/src/stemtrace/server/api/websocket.py +0 -28
- stemtrace-0.3.0/tests/unit/test_routes.py +0 -575
- {stemtrace-0.3.0 → stemtrace-0.3.1}/.dockerignore +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/.github/dependabot.yml +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/.github/workflows/ci.yml +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/.github/workflows/e2e.yml +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/.github/workflows/release.yml +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/.gitignore +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/.pre-commit-config.yaml +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/.python-version +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/CONTRIBUTING.md +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/Dockerfile +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/Dockerfile.e2e +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/LICENSE +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/Makefile +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/build_ui.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/docker-compose.e2e.rabbitmq.yml +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/docker-compose.e2e.yml +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/docker-compose.rabbitmq.yml +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/docs/screenshots/task_details.png +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/docs/screenshots/unregistered.png +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/docs/screenshots/workflow.png +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/progress.md +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/scripts/wait_for_http.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/core/__init__.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/core/events.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/core/exceptions.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/core/graph.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/core/ports.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/library/__init__.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/library/bootsteps.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/library/config.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/library/scrubbing.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/library/signals.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/library/transports/__init__.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/library/transports/memory.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/library/transports/rabbitmq.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/library/transports/redis.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/py.typed +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/__init__.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/api/__init__.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/api/schemas.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/consumer.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/fastapi/__init__.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/fastapi/auth.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/store.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/__init__.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/biome.json +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/index.html +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/package-lock.json +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/playwright.config.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/postcss.config.js +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/api/client.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/api/queries.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/DateRangePicker.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/Filters.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/TaskGraph.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/TaskList.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/TaskStateBadge.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/TaskTimeline.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/TimelineBar.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/Tooltip.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/hooks/WebSocketContext.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/hooks/useInfiniteScroll.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/index.css +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/main.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/__root.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/graph.$rootId.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/graphs.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/index.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/registry.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/tasks.$taskId.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/workers.tsx +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/utils/format.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/vite-env.d.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/fixtures/mock-api.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/fixtures/mock-data.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/graphs.spec.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/registry.spec.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/task-detail.spec.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/tasks.spec.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/workers.spec.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tsconfig.json +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tsconfig.tsbuildinfo +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/vite.config.ts +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/src/stemtrace/server/websocket.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/__init__.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/conftest.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/e2e/__init__.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/e2e/conftest.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/e2e/tasks.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/e2e/test_api_e2e.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/e2e/test_workers_e2e.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/integration/__init__.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/integration/test_embedded_static.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/integration/test_fastapi_integration.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/integration/test_rabbitmq_transport.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/integration/test_redis_transport.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/integration/test_static_ui.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/__init__.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_auth.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_bootsteps.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_config.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_consumer.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_events.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_exceptions.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_graph.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_scrubbing.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_signals.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_store.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_transports.py +0 -0
- {stemtrace-0.3.0 → stemtrace-0.3.1}/tests/unit/test_websocket.py +0 -0
|
@@ -7,10 +7,44 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.1] - 2026-01-04
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- UI: optional built-in form login flow for protecting the stemtrace UI
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Config: split server broker URL from worker event transport URL (`broker_url` vs `transport_url`)
|
|
17
|
+
- API: avoid blocking worker/registry refresh operations
|
|
18
|
+
- Docs: clarify optional configuration and retention behavior
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- Workers/Registry: refresh via Celery inspect to reduce stale worker/task registry data
|
|
22
|
+
|
|
10
23
|
## [0.3.0] - 2026-01-04
|
|
11
24
|
|
|
25
|
+
### Added
|
|
26
|
+
- RabbitMQ event transport
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
- Tests: improved RabbitMQ transport coverage and reduced duplication
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
- UI: harden derived prefix sanitization
|
|
33
|
+
- CI/E2E: avoid artifact name conflicts
|
|
34
|
+
|
|
12
35
|
## [0.2.2] - 2026-01-03
|
|
13
36
|
|
|
37
|
+
### Added
|
|
38
|
+
- README: add release version badge
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
- Packaging/docs: simplify badges and metadata
|
|
42
|
+
- README: pin PyPI badge to release version
|
|
43
|
+
- Tests: make version assertion dynamic
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
- Version bump: sync fix
|
|
47
|
+
|
|
14
48
|
## [0.2.1] - 2026-01-03
|
|
15
49
|
|
|
16
50
|
### Added
|
|
@@ -63,7 +97,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
63
97
|
- **E2E test suite**: Docker API tests + Playwright browser tests
|
|
64
98
|
- **Comprehensive test suite**: 350+ Python tests, 90%+ coverage
|
|
65
99
|
|
|
66
|
-
[unreleased]: https://github.com/iansokolskyi/stemtrace/compare/v0.
|
|
100
|
+
[unreleased]: https://github.com/iansokolskyi/stemtrace/compare/v0.3.0...HEAD
|
|
101
|
+
[0.3.0]: https://github.com/iansokolskyi/stemtrace/compare/v0.2.2...v0.3.0
|
|
102
|
+
[0.2.2]: https://github.com/iansokolskyi/stemtrace/compare/v0.2.1...v0.2.2
|
|
67
103
|
[0.2.1]: https://github.com/iansokolskyi/stemtrace/compare/v0.2.0...v0.2.1
|
|
68
104
|
[0.2.0]: https://github.com/iansokolskyi/stemtrace/compare/v0.1.1...v0.2.0
|
|
69
105
|
[0.1.1]: https://github.com/iansokolskyi/stemtrace/compare/v0.1.0...v0.1.1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stemtrace
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: A lightweight Celery task flow visualizer
|
|
5
5
|
Project-URL: Homepage, https://github.com/iansokolskyi/stemtrace
|
|
6
6
|
Project-URL: Documentation, https://github.com/iansokolskyi/stemtrace#readme
|
|
@@ -56,7 +56,7 @@ Description-Content-Type: text/markdown
|
|
|
56
56
|
|
|
57
57
|
**Zero-infrastructure Celery task flow visualizer**
|
|
58
58
|
|
|
59
|
-
[](https://pypi.org/project/stemtrace)
|
|
60
60
|
[](https://pypi.org/project/stemtrace/)
|
|
61
61
|
[](https://github.com/iansokolskyi/stemtrace/actions/workflows/ci.yml)
|
|
62
62
|
[](https://codecov.io/gh/iansokolskyi/stemtrace)
|
|
@@ -302,11 +302,33 @@ batch_processor
|
|
|
302
302
|
- **Timing** — Each node displays start time and duration directly in the graph
|
|
303
303
|
- **Aggregate state** — Container shows running/success/failure based on member states
|
|
304
304
|
|
|
305
|
-
### Environment Variables
|
|
305
|
+
### Environment Variables (Optional)
|
|
306
|
+
|
|
307
|
+
You **do not need** these environment variables if you’re using the Python APIs:
|
|
308
|
+
- `stemtrace.init_worker(app, transport_url=..., prefix=..., ttl=...)`
|
|
309
|
+
- `stemtrace.init_app(app, broker_url=..., transport_url=...)`
|
|
310
|
+
|
|
311
|
+
They exist mainly as **convenient defaults** for:
|
|
312
|
+
- `stemtrace server` / `stemtrace consume`
|
|
313
|
+
- container/Docker setups where passing flags is awkward
|
|
314
|
+
|
|
315
|
+
If your app already uses env vars like `BROKER_URL`, `REDIS_URL`, etc., just pass them through:
|
|
316
|
+
|
|
317
|
+
```python
|
|
318
|
+
import os
|
|
319
|
+
import stemtrace
|
|
320
|
+
|
|
321
|
+
stemtrace.init_app(
|
|
322
|
+
app,
|
|
323
|
+
broker_url=os.environ["BROKER_URL"],
|
|
324
|
+
transport_url=os.getenv("STEMTRACE_TRANSPORT_URL") or os.environ["BROKER_URL"],
|
|
325
|
+
)
|
|
326
|
+
```
|
|
306
327
|
|
|
307
328
|
| Variable | Description | Default |
|
|
308
329
|
|----------|-------------|---------|
|
|
309
|
-
| `STEMTRACE_BROKER_URL` |
|
|
330
|
+
| `STEMTRACE_BROKER_URL` | Celery broker URL (used for on-demand worker/registry inspection). Also used as the default for `STEMTRACE_TRANSPORT_URL`. | `redis://localhost:6379/0` |
|
|
331
|
+
| `STEMTRACE_TRANSPORT_URL` | Event transport URL (where stemtrace publishes/consumes events). | Defaults to `STEMTRACE_BROKER_URL`. |
|
|
310
332
|
|
|
311
333
|
### Supported Brokers
|
|
312
334
|
|
|
@@ -315,6 +337,24 @@ batch_processor
|
|
|
315
337
|
| Redis | `redis://`, `rediss://` | ✅ Supported |
|
|
316
338
|
| RabbitMQ | `amqp://`, `amqps://`, `pyamqp://` | ✅ Supported |
|
|
317
339
|
|
|
340
|
+
### Event Retention & Server Restarts (Important)
|
|
341
|
+
|
|
342
|
+
stemtrace builds the UI from **events** and keeps state in an **in-memory** graph store.
|
|
343
|
+
That means a `stemtrace server` restart starts from an empty store and only becomes “full”
|
|
344
|
+
again once events are re-consumed.
|
|
345
|
+
|
|
346
|
+
- **Redis (Streams)**: On restart, the server can rebuild state by replaying events that are
|
|
347
|
+
still retained in the stream (bounded by `ttl` / stream trimming).
|
|
348
|
+
- **RabbitMQ (fanout + per-consumer queue)**:
|
|
349
|
+
- Events already consumed/acked by the server are **gone**.
|
|
350
|
+
- Events published while the server is down are only visible after restart if the server’s
|
|
351
|
+
durable per-consumer queue still exists and the messages are still within TTL.
|
|
352
|
+
- **Workers + Registry tabs**: stemtrace uses **Celery inspect** on demand to populate workers
|
|
353
|
+
and registered tasks, so those pages work even if the server missed `worker_ready` events.
|
|
354
|
+
- **If you need durable history across restarts**: point stemtrace events at Redis even if your
|
|
355
|
+
Celery broker is RabbitMQ (set `transport_url` in `stemtrace.init_worker(...)` and set
|
|
356
|
+
`STEMTRACE_TRANSPORT_URL` for the server / embedded setup).
|
|
357
|
+
|
|
318
358
|
## 🐳 Docker
|
|
319
359
|
|
|
320
360
|
```bash
|
|
@@ -331,6 +371,15 @@ docker run -p 8000:8000 \
|
|
|
331
371
|
ghcr.io/iansokolskyi/stemtrace
|
|
332
372
|
```
|
|
333
373
|
|
|
374
|
+
RabbitMQ broker + Redis event transport (recommended if you want history across server restarts):
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
docker run -p 8000:8000 \
|
|
378
|
+
-e STEMTRACE_BROKER_URL=amqp://guest:guest@host.docker.internal:5672// \
|
|
379
|
+
-e STEMTRACE_TRANSPORT_URL=redis://host.docker.internal:6379/0 \
|
|
380
|
+
ghcr.io/iansokolskyi/stemtrace
|
|
381
|
+
```
|
|
382
|
+
|
|
334
383
|
Or with Docker Compose:
|
|
335
384
|
|
|
336
385
|
```yaml
|
|
@@ -371,11 +420,22 @@ Open [http://localhost:8000](http://localhost:8000) to view the dashboard.
|
|
|
371
420
|
```bash
|
|
372
421
|
stemtrace server \
|
|
373
422
|
--broker-url redis://myredis:6379/0 \
|
|
423
|
+
--transport-url redis://myredis:6379/0 \
|
|
374
424
|
--host 0.0.0.0 \
|
|
375
425
|
--port 8000 \
|
|
376
426
|
--reload # For development
|
|
377
427
|
```
|
|
378
428
|
|
|
429
|
+
#### Protecting the Server (Built-in Login Page)
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
stemtrace server \
|
|
433
|
+
--broker-url redis://myredis:6379/0 \
|
|
434
|
+
--login-username admin \
|
|
435
|
+
--login-password secret \
|
|
436
|
+
--login-secret change-me
|
|
437
|
+
```
|
|
438
|
+
|
|
379
439
|
#### High-Scale Production Setup
|
|
380
440
|
|
|
381
441
|
Note: `stemtrace server` includes an embedded consumer today (single-process). A multi-process deployment mode is planned.
|
|
@@ -397,6 +457,8 @@ That's it. `init_app()` automatically:
|
|
|
397
457
|
- Mounts the dashboard at `/stemtrace/`
|
|
398
458
|
- Starts the event consumer
|
|
399
459
|
|
|
460
|
+
Tip: you can also set `transport_url` if you want stemtrace events stored separately from your Celery broker.
|
|
461
|
+
|
|
400
462
|
#### Configuration Options
|
|
401
463
|
|
|
402
464
|
```python
|
|
@@ -406,6 +468,7 @@ import stemtrace
|
|
|
406
468
|
extension = stemtrace.init_app(
|
|
407
469
|
app,
|
|
408
470
|
broker_url="redis://localhost:6379/0",
|
|
471
|
+
transport_url=None, # Defaults to broker_url
|
|
409
472
|
prefix="/stemtrace", # Mount path AND event stream prefix (normalized)
|
|
410
473
|
ttl=86400, # Event TTL in seconds
|
|
411
474
|
max_nodes=10000, # Max nodes in memory
|
|
@@ -425,7 +488,26 @@ from your_app.auth import require_admin
|
|
|
425
488
|
stemtrace.init_app(app, broker_url="redis://localhost:6379/0", auth_dependency=Depends(require_admin))
|
|
426
489
|
```
|
|
427
490
|
|
|
428
|
-
|
|
491
|
+
#### With Built-in Login Page (Recommended for UI-first)
|
|
492
|
+
|
|
493
|
+
If you primarily use the UI, the easiest way to protect **UI + assets + API + WebSocket**
|
|
494
|
+
is the built-in form login (cookie session):
|
|
495
|
+
|
|
496
|
+
```python
|
|
497
|
+
import stemtrace
|
|
498
|
+
|
|
499
|
+
stemtrace.init_app(
|
|
500
|
+
app,
|
|
501
|
+
broker_url="redis://localhost:6379/0",
|
|
502
|
+
login_username="admin",
|
|
503
|
+
login_password="secret",
|
|
504
|
+
login_secret="change-me", # recommended for production
|
|
505
|
+
)
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
This serves a sign-in page at `/stemtrace/login` and protects everything under `/stemtrace`.
|
|
509
|
+
|
|
510
|
+
#### Built-in Auth Helpers (Basic / API key)
|
|
429
511
|
|
|
430
512
|
```python
|
|
431
513
|
import stemtrace
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Zero-infrastructure Celery task flow visualizer**
|
|
4
4
|
|
|
5
|
-
[](https://pypi.org/project/stemtrace)
|
|
6
6
|
[](https://pypi.org/project/stemtrace/)
|
|
7
7
|
[](https://github.com/iansokolskyi/stemtrace/actions/workflows/ci.yml)
|
|
8
8
|
[](https://codecov.io/gh/iansokolskyi/stemtrace)
|
|
@@ -248,11 +248,33 @@ batch_processor
|
|
|
248
248
|
- **Timing** — Each node displays start time and duration directly in the graph
|
|
249
249
|
- **Aggregate state** — Container shows running/success/failure based on member states
|
|
250
250
|
|
|
251
|
-
### Environment Variables
|
|
251
|
+
### Environment Variables (Optional)
|
|
252
|
+
|
|
253
|
+
You **do not need** these environment variables if you’re using the Python APIs:
|
|
254
|
+
- `stemtrace.init_worker(app, transport_url=..., prefix=..., ttl=...)`
|
|
255
|
+
- `stemtrace.init_app(app, broker_url=..., transport_url=...)`
|
|
256
|
+
|
|
257
|
+
They exist mainly as **convenient defaults** for:
|
|
258
|
+
- `stemtrace server` / `stemtrace consume`
|
|
259
|
+
- container/Docker setups where passing flags is awkward
|
|
260
|
+
|
|
261
|
+
If your app already uses env vars like `BROKER_URL`, `REDIS_URL`, etc., just pass them through:
|
|
262
|
+
|
|
263
|
+
```python
|
|
264
|
+
import os
|
|
265
|
+
import stemtrace
|
|
266
|
+
|
|
267
|
+
stemtrace.init_app(
|
|
268
|
+
app,
|
|
269
|
+
broker_url=os.environ["BROKER_URL"],
|
|
270
|
+
transport_url=os.getenv("STEMTRACE_TRANSPORT_URL") or os.environ["BROKER_URL"],
|
|
271
|
+
)
|
|
272
|
+
```
|
|
252
273
|
|
|
253
274
|
| Variable | Description | Default |
|
|
254
275
|
|----------|-------------|---------|
|
|
255
|
-
| `STEMTRACE_BROKER_URL` |
|
|
276
|
+
| `STEMTRACE_BROKER_URL` | Celery broker URL (used for on-demand worker/registry inspection). Also used as the default for `STEMTRACE_TRANSPORT_URL`. | `redis://localhost:6379/0` |
|
|
277
|
+
| `STEMTRACE_TRANSPORT_URL` | Event transport URL (where stemtrace publishes/consumes events). | Defaults to `STEMTRACE_BROKER_URL`. |
|
|
256
278
|
|
|
257
279
|
### Supported Brokers
|
|
258
280
|
|
|
@@ -261,6 +283,24 @@ batch_processor
|
|
|
261
283
|
| Redis | `redis://`, `rediss://` | ✅ Supported |
|
|
262
284
|
| RabbitMQ | `amqp://`, `amqps://`, `pyamqp://` | ✅ Supported |
|
|
263
285
|
|
|
286
|
+
### Event Retention & Server Restarts (Important)
|
|
287
|
+
|
|
288
|
+
stemtrace builds the UI from **events** and keeps state in an **in-memory** graph store.
|
|
289
|
+
That means a `stemtrace server` restart starts from an empty store and only becomes “full”
|
|
290
|
+
again once events are re-consumed.
|
|
291
|
+
|
|
292
|
+
- **Redis (Streams)**: On restart, the server can rebuild state by replaying events that are
|
|
293
|
+
still retained in the stream (bounded by `ttl` / stream trimming).
|
|
294
|
+
- **RabbitMQ (fanout + per-consumer queue)**:
|
|
295
|
+
- Events already consumed/acked by the server are **gone**.
|
|
296
|
+
- Events published while the server is down are only visible after restart if the server’s
|
|
297
|
+
durable per-consumer queue still exists and the messages are still within TTL.
|
|
298
|
+
- **Workers + Registry tabs**: stemtrace uses **Celery inspect** on demand to populate workers
|
|
299
|
+
and registered tasks, so those pages work even if the server missed `worker_ready` events.
|
|
300
|
+
- **If you need durable history across restarts**: point stemtrace events at Redis even if your
|
|
301
|
+
Celery broker is RabbitMQ (set `transport_url` in `stemtrace.init_worker(...)` and set
|
|
302
|
+
`STEMTRACE_TRANSPORT_URL` for the server / embedded setup).
|
|
303
|
+
|
|
264
304
|
## 🐳 Docker
|
|
265
305
|
|
|
266
306
|
```bash
|
|
@@ -277,6 +317,15 @@ docker run -p 8000:8000 \
|
|
|
277
317
|
ghcr.io/iansokolskyi/stemtrace
|
|
278
318
|
```
|
|
279
319
|
|
|
320
|
+
RabbitMQ broker + Redis event transport (recommended if you want history across server restarts):
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
docker run -p 8000:8000 \
|
|
324
|
+
-e STEMTRACE_BROKER_URL=amqp://guest:guest@host.docker.internal:5672// \
|
|
325
|
+
-e STEMTRACE_TRANSPORT_URL=redis://host.docker.internal:6379/0 \
|
|
326
|
+
ghcr.io/iansokolskyi/stemtrace
|
|
327
|
+
```
|
|
328
|
+
|
|
280
329
|
Or with Docker Compose:
|
|
281
330
|
|
|
282
331
|
```yaml
|
|
@@ -317,11 +366,22 @@ Open [http://localhost:8000](http://localhost:8000) to view the dashboard.
|
|
|
317
366
|
```bash
|
|
318
367
|
stemtrace server \
|
|
319
368
|
--broker-url redis://myredis:6379/0 \
|
|
369
|
+
--transport-url redis://myredis:6379/0 \
|
|
320
370
|
--host 0.0.0.0 \
|
|
321
371
|
--port 8000 \
|
|
322
372
|
--reload # For development
|
|
323
373
|
```
|
|
324
374
|
|
|
375
|
+
#### Protecting the Server (Built-in Login Page)
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
stemtrace server \
|
|
379
|
+
--broker-url redis://myredis:6379/0 \
|
|
380
|
+
--login-username admin \
|
|
381
|
+
--login-password secret \
|
|
382
|
+
--login-secret change-me
|
|
383
|
+
```
|
|
384
|
+
|
|
325
385
|
#### High-Scale Production Setup
|
|
326
386
|
|
|
327
387
|
Note: `stemtrace server` includes an embedded consumer today (single-process). A multi-process deployment mode is planned.
|
|
@@ -343,6 +403,8 @@ That's it. `init_app()` automatically:
|
|
|
343
403
|
- Mounts the dashboard at `/stemtrace/`
|
|
344
404
|
- Starts the event consumer
|
|
345
405
|
|
|
406
|
+
Tip: you can also set `transport_url` if you want stemtrace events stored separately from your Celery broker.
|
|
407
|
+
|
|
346
408
|
#### Configuration Options
|
|
347
409
|
|
|
348
410
|
```python
|
|
@@ -352,6 +414,7 @@ import stemtrace
|
|
|
352
414
|
extension = stemtrace.init_app(
|
|
353
415
|
app,
|
|
354
416
|
broker_url="redis://localhost:6379/0",
|
|
417
|
+
transport_url=None, # Defaults to broker_url
|
|
355
418
|
prefix="/stemtrace", # Mount path AND event stream prefix (normalized)
|
|
356
419
|
ttl=86400, # Event TTL in seconds
|
|
357
420
|
max_nodes=10000, # Max nodes in memory
|
|
@@ -371,7 +434,26 @@ from your_app.auth import require_admin
|
|
|
371
434
|
stemtrace.init_app(app, broker_url="redis://localhost:6379/0", auth_dependency=Depends(require_admin))
|
|
372
435
|
```
|
|
373
436
|
|
|
374
|
-
|
|
437
|
+
#### With Built-in Login Page (Recommended for UI-first)
|
|
438
|
+
|
|
439
|
+
If you primarily use the UI, the easiest way to protect **UI + assets + API + WebSocket**
|
|
440
|
+
is the built-in form login (cookie session):
|
|
441
|
+
|
|
442
|
+
```python
|
|
443
|
+
import stemtrace
|
|
444
|
+
|
|
445
|
+
stemtrace.init_app(
|
|
446
|
+
app,
|
|
447
|
+
broker_url="redis://localhost:6379/0",
|
|
448
|
+
login_username="admin",
|
|
449
|
+
login_password="secret",
|
|
450
|
+
login_secret="change-me", # recommended for production
|
|
451
|
+
)
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
This serves a sign-in page at `/stemtrace/login` and protects everything under `/stemtrace`.
|
|
455
|
+
|
|
456
|
+
#### Built-in Auth Helpers (Basic / API key)
|
|
375
457
|
|
|
376
458
|
```python
|
|
377
459
|
import stemtrace
|
|
@@ -9,18 +9,38 @@ task events for visualization, including:
|
|
|
9
9
|
- Group/chord visualization with synthetic GROUP nodes
|
|
10
10
|
|
|
11
11
|
Usage:
|
|
12
|
-
# Install dependencies
|
|
13
|
-
pip install stemtrace
|
|
12
|
+
# Install dependencies (PyPI)
|
|
13
|
+
pip install stemtrace
|
|
14
|
+
|
|
15
|
+
# Or (from repo)
|
|
16
|
+
uv sync --extra dev
|
|
14
17
|
|
|
15
18
|
# Start Redis
|
|
16
19
|
docker run -d -p 6379:6379 redis:alpine
|
|
17
20
|
|
|
21
|
+
# (Optional) Start RabbitMQ (for RabbitMQ broker tests)
|
|
22
|
+
docker run -d -p 5672:5672 -p 15672:15672 rabbitmq:3-management
|
|
23
|
+
|
|
18
24
|
# Start worker
|
|
19
25
|
celery -A examples.celery_app worker --loglevel=info
|
|
20
26
|
|
|
21
27
|
# Start stemtrace server (in another terminal)
|
|
22
28
|
stemtrace server
|
|
23
29
|
|
|
30
|
+
# Switch between Redis and RabbitMQ using environment variables:
|
|
31
|
+
# - CELERY_BROKER_URL controls where Celery sends tasks (default: Redis)
|
|
32
|
+
# - CELERY_RESULT_BACKEND controls result backend (default: Redis)
|
|
33
|
+
#
|
|
34
|
+
# RabbitMQ note: chord-style workflows require a result backend that supports
|
|
35
|
+
# chords; `redis://` works well.
|
|
36
|
+
#
|
|
37
|
+
# Example (RabbitMQ broker + Redis result backend):
|
|
38
|
+
# export CELERY_BROKER_URL="amqp://guest:guest@localhost:5672//"
|
|
39
|
+
# export CELERY_RESULT_BACKEND="redis://localhost:6379/1"
|
|
40
|
+
#
|
|
41
|
+
# (Optional) override stemtrace's event transport independent of Celery:
|
|
42
|
+
# export STEMTRACE_TRANSPORT_URL="amqp://guest:guest@localhost:5672//"
|
|
43
|
+
|
|
24
44
|
# Run demo tasks
|
|
25
45
|
python examples/celery_app.py workflow # Complex workflow (chain + group)
|
|
26
46
|
python examples/celery_app.py group # Parallel group (synthetic GROUP node)
|
|
@@ -32,6 +52,7 @@ Usage:
|
|
|
32
52
|
|
|
33
53
|
from __future__ import annotations
|
|
34
54
|
|
|
55
|
+
import os
|
|
35
56
|
import random
|
|
36
57
|
import sys
|
|
37
58
|
from typing import Any
|
|
@@ -40,15 +61,24 @@ from celery import Celery, chain, chord, group
|
|
|
40
61
|
|
|
41
62
|
import stemtrace
|
|
42
63
|
|
|
64
|
+
# Defaults (Redis local)
|
|
65
|
+
_DEFAULT_REDIS_BROKER = "redis://localhost:6379/0"
|
|
66
|
+
_DEFAULT_REDIS_BACKEND = "redis://localhost:6379/1"
|
|
67
|
+
|
|
68
|
+
# Allow env-driven configuration so the same example can test Redis or RabbitMQ.
|
|
69
|
+
_CELERY_BROKER_URL = os.getenv("CELERY_BROKER_URL", _DEFAULT_REDIS_BROKER)
|
|
70
|
+
_CELERY_RESULT_BACKEND = os.getenv("CELERY_RESULT_BACKEND", _DEFAULT_REDIS_BACKEND)
|
|
71
|
+
|
|
43
72
|
# Create Celery app
|
|
44
73
|
app = Celery(
|
|
45
74
|
"examples",
|
|
46
|
-
broker=
|
|
47
|
-
backend=
|
|
75
|
+
broker=_CELERY_BROKER_URL,
|
|
76
|
+
backend=_CELERY_RESULT_BACKEND,
|
|
48
77
|
)
|
|
49
78
|
|
|
50
79
|
# Initialize stemtrace tracking
|
|
51
|
-
|
|
80
|
+
_STEMTRACE_TRANSPORT_URL = os.getenv("STEMTRACE_TRANSPORT_URL")
|
|
81
|
+
stemtrace.init_worker(app, transport_url=_STEMTRACE_TRANSPORT_URL)
|
|
52
82
|
|
|
53
83
|
|
|
54
84
|
# =============================================================================
|
|
@@ -5,7 +5,7 @@ This example shows how to mount stemtrace as a router in your existing
|
|
|
5
5
|
FastAPI app, with an embedded consumer for development.
|
|
6
6
|
|
|
7
7
|
Usage:
|
|
8
|
-
pip install stemtrace
|
|
8
|
+
pip install stemtrace
|
|
9
9
|
uvicorn examples.fastapi_integration:app --reload
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -14,19 +14,22 @@ from fastapi import FastAPI
|
|
|
14
14
|
import stemtrace
|
|
15
15
|
|
|
16
16
|
# Configuration
|
|
17
|
+
#
|
|
18
|
+
# `broker_url` is Celery's broker (used for on-demand worker inspection).
|
|
19
|
+
# `transport_url` is where stemtrace consumes events from (defaults to broker_url).
|
|
17
20
|
BROKER_URL = "redis://localhost:6379/0"
|
|
21
|
+
TRANSPORT_URL = None # e.g. "redis://localhost:6379/0"
|
|
18
22
|
|
|
19
23
|
# Create FastAPI app
|
|
20
24
|
app = FastAPI(
|
|
21
25
|
title="My App with stemtrace",
|
|
22
26
|
)
|
|
23
27
|
|
|
24
|
-
# Initialize stemtrace in one line
|
|
28
|
+
# Initialize stemtrace in one line
|
|
25
29
|
stemtrace.init_app(
|
|
26
30
|
app,
|
|
27
31
|
broker_url=BROKER_URL,
|
|
28
|
-
|
|
29
|
-
serve_ui=True, # Serve the React UI
|
|
32
|
+
transport_url=TRANSPORT_URL,
|
|
30
33
|
)
|
|
31
34
|
|
|
32
35
|
|
|
@@ -40,13 +43,6 @@ async def root() -> dict[str, str]:
|
|
|
40
43
|
@app.get("/health")
|
|
41
44
|
async def health() -> dict[str, str]:
|
|
42
45
|
"""Health check endpoint."""
|
|
43
|
-
# Note: With convenience API, you don't have access to the extension instance
|
|
44
|
-
# Use StemtraceExtension directly if you need programmatic access:
|
|
45
|
-
#
|
|
46
|
-
# from stemtrace import StemtraceExtension
|
|
47
|
-
# flow = StemtraceExtension(broker_url=...)
|
|
48
|
-
# flow.init_app(app)
|
|
49
|
-
# return {"status": flow.consumer.is_running}
|
|
50
46
|
#
|
|
51
47
|
return {"status": "ok"}
|
|
52
48
|
|
|
@@ -5,7 +5,7 @@ This example shows how to protect stemtrace endpoints with
|
|
|
5
5
|
basic authentication or API key authentication.
|
|
6
6
|
|
|
7
7
|
Usage:
|
|
8
|
-
pip install stemtrace
|
|
8
|
+
pip install stemtrace
|
|
9
9
|
uvicorn examples.with_auth:app --reload
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -23,11 +23,10 @@ app = FastAPI(
|
|
|
23
23
|
title="stemtrace with Auth",
|
|
24
24
|
)
|
|
25
25
|
|
|
26
|
-
# Initialize stemtrace with authentication
|
|
26
|
+
# Initialize stemtrace with authentication
|
|
27
27
|
stemtrace.init_app(
|
|
28
28
|
app,
|
|
29
29
|
broker_url=BROKER_URL,
|
|
30
|
-
embedded_consumer=True,
|
|
31
30
|
auth_dependency=require_basic_auth(AUTH_USERNAME, AUTH_PASSWORD),
|
|
32
31
|
)
|
|
33
32
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Example: stemtrace with built-in form login.
|
|
3
|
+
|
|
4
|
+
This example shows how to protect the stemtrace UI with a pretty login page.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
pip install stemtrace[server]
|
|
8
|
+
uvicorn examples.with_login:app --reload
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from fastapi import FastAPI
|
|
12
|
+
|
|
13
|
+
import stemtrace
|
|
14
|
+
|
|
15
|
+
# Configuration
|
|
16
|
+
BROKER_URL = "redis://localhost:6379/0"
|
|
17
|
+
LOGIN_USERNAME = "admin"
|
|
18
|
+
LOGIN_PASSWORD = "secret" # NOSONAR - example credential for local demo only
|
|
19
|
+
LOGIN_SECRET = "change-me" # recommended for production
|
|
20
|
+
|
|
21
|
+
app = FastAPI(title="stemtrace with Login")
|
|
22
|
+
|
|
23
|
+
stemtrace.init_app(
|
|
24
|
+
app,
|
|
25
|
+
broker_url=BROKER_URL,
|
|
26
|
+
embedded_consumer=True,
|
|
27
|
+
serve_ui=True,
|
|
28
|
+
login_username=LOGIN_USERNAME,
|
|
29
|
+
login_password=LOGIN_PASSWORD,
|
|
30
|
+
login_secret=LOGIN_SECRET,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@app.get("/")
|
|
35
|
+
async def root() -> dict[str, str]:
|
|
36
|
+
"""Public endpoint."""
|
|
37
|
+
return {"message": "Visit /stemtrace (login required)"}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
if __name__ == "__main__":
|
|
41
|
+
import uvicorn
|
|
42
|
+
|
|
43
|
+
uvicorn.run(app, host="0.0.0.0", port=8000)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "stemtrace"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.1"
|
|
4
4
|
description = "A lightweight Celery task flow visualizer"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "MIT" }
|
|
@@ -76,6 +76,7 @@ build-backend = "hatchling.build"
|
|
|
76
76
|
packages = ["src/stemtrace"]
|
|
77
77
|
artifacts = [
|
|
78
78
|
"src/stemtrace/server/ui/frontend/dist/**",
|
|
79
|
+
"src/stemtrace/server/ui/templates/**",
|
|
79
80
|
]
|
|
80
81
|
|
|
81
82
|
[tool.hatch.build.targets.wheel.hooks.custom]
|