stemtrace 0.2.2__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.2.2 → stemtrace-0.3.1}/.bumpversion.toml +1 -1
- {stemtrace-0.2.2 → stemtrace-0.3.1}/.github/workflows/e2e.yml +48 -10
- {stemtrace-0.2.2 → stemtrace-0.3.1}/CHANGELOG.md +39 -1
- {stemtrace-0.2.2 → stemtrace-0.3.1}/Makefile +31 -1
- {stemtrace-0.2.2 → stemtrace-0.3.1}/PKG-INFO +110 -10
- {stemtrace-0.2.2 → stemtrace-0.3.1}/README.md +109 -9
- stemtrace-0.3.1/docker-compose.e2e.rabbitmq.yml +88 -0
- stemtrace-0.3.1/docker-compose.rabbitmq.yml +44 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/docker-compose.yml +1 -1
- {stemtrace-0.2.2 → stemtrace-0.3.1}/examples/celery_app.py +35 -5
- {stemtrace-0.2.2 → stemtrace-0.3.1}/examples/fastapi_integration.py +7 -11
- {stemtrace-0.2.2 → stemtrace-0.3.1}/examples/with_auth.py +2 -3
- stemtrace-0.3.1/examples/with_login.py +43 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/pyproject.toml +10 -1
- stemtrace-0.3.1/scripts/wait_for_http.py +41 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/__init__.py +112 -2
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/core/exceptions.py +1 -1
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/library/transports/__init__.py +5 -0
- stemtrace-0.3.1/src/stemtrace/library/transports/rabbitmq.py +250 -0
- stemtrace-0.3.1/src/stemtrace/server/__main__.py +250 -0
- {stemtrace-0.2.2 → 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.2.2 → 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.2.2 → stemtrace-0.3.1}/src/stemtrace/server/fastapi/router.py +3 -1
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/package.json +1 -1
- stemtrace-0.3.1/src/stemtrace/server/ui/static.py +261 -0
- stemtrace-0.3.1/src/stemtrace/server/ui/templates/login.html +153 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/e2e/tasks.py +3 -2
- stemtrace-0.3.1/tests/e2e/test_workers_e2e.py +197 -0
- stemtrace-0.3.1/tests/integration/test_rabbitmq_transport.py +139 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/integration/test_static_ui.py +51 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/integration/test_workers_refresh.py +1 -1
- {stemtrace-0.2.2 → 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.2.2 → 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.1/tests/unit/test_transports.py +1033 -0
- stemtrace-0.3.1/tests/unit/test_ui_static_prefix.py +74 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/uv.lock +1 -1
- stemtrace-0.2.2/src/stemtrace/server/__main__.py +0 -136
- stemtrace-0.2.2/src/stemtrace/server/api/websocket.py +0 -28
- stemtrace-0.2.2/src/stemtrace/server/ui/static.py +0 -122
- stemtrace-0.2.2/tests/e2e/test_workers_e2e.py +0 -117
- stemtrace-0.2.2/tests/unit/test_routes.py +0 -575
- stemtrace-0.2.2/tests/unit/test_transports.py +0 -543
- {stemtrace-0.2.2 → stemtrace-0.3.1}/.dockerignore +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/.github/dependabot.yml +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/.github/workflows/ci.yml +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/.github/workflows/release.yml +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/.gitignore +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/.pre-commit-config.yaml +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/.python-version +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/CONTRIBUTING.md +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/Dockerfile +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/Dockerfile.e2e +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/LICENSE +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/build_ui.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/docker-compose.e2e.yml +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/docs/screenshots/task_details.png +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/docs/screenshots/unregistered.png +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/docs/screenshots/workflow.png +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/progress.md +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/core/__init__.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/core/events.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/core/graph.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/core/ports.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/library/__init__.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/library/bootsteps.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/library/config.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/library/scrubbing.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/library/signals.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/library/transports/memory.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/library/transports/redis.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/py.typed +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/__init__.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/api/__init__.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/api/schemas.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/consumer.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/fastapi/__init__.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/fastapi/auth.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/store.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/__init__.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/biome.json +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/index.html +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/package-lock.json +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/playwright.config.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/postcss.config.js +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/api/client.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/api/queries.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/DateRangePicker.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/Filters.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/TaskGraph.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/TaskList.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/TaskStateBadge.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/TaskTimeline.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/TimelineBar.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/components/Tooltip.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/hooks/WebSocketContext.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/hooks/useInfiniteScroll.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/index.css +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/main.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/__root.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/graph.$rootId.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/graphs.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/index.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/registry.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/tasks.$taskId.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/routes/workers.tsx +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/utils/format.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/src/vite-env.d.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/fixtures/mock-api.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/fixtures/mock-data.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/graphs.spec.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/registry.spec.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/task-detail.spec.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/tasks.spec.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tests/workers.spec.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tsconfig.json +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/tsconfig.tsbuildinfo +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/ui/frontend/vite.config.ts +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/src/stemtrace/server/websocket.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/__init__.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/conftest.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/e2e/__init__.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/e2e/conftest.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/e2e/test_api_e2e.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/integration/__init__.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/integration/test_embedded_static.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/integration/test_fastapi_integration.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/integration/test_redis_transport.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/unit/__init__.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/unit/test_auth.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/unit/test_bootsteps.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/unit/test_config.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/unit/test_consumer.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/unit/test_events.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/unit/test_exceptions.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/unit/test_graph.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/unit/test_scrubbing.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/unit/test_signals.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/unit/test_store.py +0 -0
- {stemtrace-0.2.2 → stemtrace-0.3.1}/tests/unit/test_websocket.py +0 -0
|
@@ -13,6 +13,12 @@ jobs:
|
|
|
13
13
|
name: API E2E Tests
|
|
14
14
|
runs-on: ubuntu-latest
|
|
15
15
|
timeout-minutes: 15
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
broker:
|
|
20
|
+
- redis
|
|
21
|
+
- rabbitmq
|
|
16
22
|
|
|
17
23
|
steps:
|
|
18
24
|
- uses: actions/checkout@v6
|
|
@@ -20,13 +26,25 @@ jobs:
|
|
|
20
26
|
- name: Set up Docker Buildx
|
|
21
27
|
uses: docker/setup-buildx-action@v3
|
|
22
28
|
|
|
29
|
+
- name: Select compose file and Celery env
|
|
30
|
+
run: |
|
|
31
|
+
if [ "${{ matrix.broker }}" = "rabbitmq" ]; then
|
|
32
|
+
echo "COMPOSE_FILE=docker-compose.e2e.rabbitmq.yml" >> "$GITHUB_ENV"
|
|
33
|
+
echo "CELERY_BROKER_URL=amqp://guest:guest@localhost:5672//" >> "$GITHUB_ENV"
|
|
34
|
+
echo "CELERY_RESULT_BACKEND=redis://localhost:16380/1" >> "$GITHUB_ENV"
|
|
35
|
+
else
|
|
36
|
+
echo "COMPOSE_FILE=docker-compose.e2e.yml" >> "$GITHUB_ENV"
|
|
37
|
+
echo "CELERY_BROKER_URL=redis://localhost:16379/0" >> "$GITHUB_ENV"
|
|
38
|
+
echo "CELERY_RESULT_BACKEND=redis://localhost:16379/1" >> "$GITHUB_ENV"
|
|
39
|
+
fi
|
|
40
|
+
|
|
23
41
|
- name: Build images
|
|
24
42
|
run: |
|
|
25
|
-
docker compose -f
|
|
43
|
+
docker compose -f "$COMPOSE_FILE" build
|
|
26
44
|
|
|
27
45
|
- name: Start services
|
|
28
46
|
run: |
|
|
29
|
-
docker compose -f
|
|
47
|
+
docker compose -f "$COMPOSE_FILE" up -d
|
|
30
48
|
# Wait for services to be healthy
|
|
31
49
|
echo "Waiting for services..."
|
|
32
50
|
timeout 120 bash -c 'until curl -sf http://localhost:8000/stemtrace/api/health -o /dev/null; do sleep 2; done'
|
|
@@ -51,16 +69,23 @@ jobs:
|
|
|
51
69
|
- name: Show logs on failure
|
|
52
70
|
if: failure()
|
|
53
71
|
run: |
|
|
54
|
-
docker compose -f
|
|
72
|
+
docker compose -f "$COMPOSE_FILE" logs
|
|
55
73
|
|
|
56
74
|
- name: Stop services
|
|
57
75
|
if: always()
|
|
58
|
-
run:
|
|
76
|
+
run: |
|
|
77
|
+
docker compose -f "$COMPOSE_FILE" down -v
|
|
59
78
|
|
|
60
79
|
playwright:
|
|
61
80
|
name: Playwright E2E Tests
|
|
62
81
|
runs-on: ubuntu-latest
|
|
63
82
|
timeout-minutes: 20
|
|
83
|
+
strategy:
|
|
84
|
+
fail-fast: false
|
|
85
|
+
matrix:
|
|
86
|
+
broker:
|
|
87
|
+
- redis
|
|
88
|
+
- rabbitmq
|
|
64
89
|
|
|
65
90
|
steps:
|
|
66
91
|
- uses: actions/checkout@v6
|
|
@@ -68,13 +93,25 @@ jobs:
|
|
|
68
93
|
- name: Set up Docker Buildx
|
|
69
94
|
uses: docker/setup-buildx-action@v3
|
|
70
95
|
|
|
96
|
+
- name: Select compose file and Celery env
|
|
97
|
+
run: |
|
|
98
|
+
if [ "${{ matrix.broker }}" = "rabbitmq" ]; then
|
|
99
|
+
echo "COMPOSE_FILE=docker-compose.e2e.rabbitmq.yml" >> "$GITHUB_ENV"
|
|
100
|
+
echo "CELERY_BROKER_URL=amqp://guest:guest@localhost:5672//" >> "$GITHUB_ENV"
|
|
101
|
+
echo "CELERY_RESULT_BACKEND=redis://localhost:16380/1" >> "$GITHUB_ENV"
|
|
102
|
+
else
|
|
103
|
+
echo "COMPOSE_FILE=docker-compose.e2e.yml" >> "$GITHUB_ENV"
|
|
104
|
+
echo "CELERY_BROKER_URL=redis://localhost:16379/0" >> "$GITHUB_ENV"
|
|
105
|
+
echo "CELERY_RESULT_BACKEND=redis://localhost:16379/1" >> "$GITHUB_ENV"
|
|
106
|
+
fi
|
|
107
|
+
|
|
71
108
|
- name: Build images
|
|
72
109
|
run: |
|
|
73
|
-
docker compose -f
|
|
110
|
+
docker compose -f "$COMPOSE_FILE" build
|
|
74
111
|
|
|
75
112
|
- name: Start services
|
|
76
113
|
run: |
|
|
77
|
-
docker compose -f
|
|
114
|
+
docker compose -f "$COMPOSE_FILE" up -d
|
|
78
115
|
echo "Waiting for services..."
|
|
79
116
|
timeout 120 bash -c 'until curl -sf http://localhost:8000/stemtrace/api/health -o /dev/null; do sleep 2; done'
|
|
80
117
|
echo "Services ready!"
|
|
@@ -133,7 +170,7 @@ jobs:
|
|
|
133
170
|
uses: actions/upload-artifact@v6
|
|
134
171
|
if: always()
|
|
135
172
|
with:
|
|
136
|
-
name: playwright-report
|
|
173
|
+
name: playwright-report-${{ matrix.broker }}
|
|
137
174
|
path: src/stemtrace/server/ui/frontend/playwright-report/
|
|
138
175
|
retention-days: 7
|
|
139
176
|
|
|
@@ -141,15 +178,16 @@ jobs:
|
|
|
141
178
|
uses: actions/upload-artifact@v6
|
|
142
179
|
if: failure()
|
|
143
180
|
with:
|
|
144
|
-
name: playwright-test-results
|
|
181
|
+
name: playwright-test-results-${{ matrix.broker }}
|
|
145
182
|
path: src/stemtrace/server/ui/frontend/test-results/
|
|
146
183
|
retention-days: 7
|
|
147
184
|
|
|
148
185
|
- name: Show logs on failure
|
|
149
186
|
if: failure()
|
|
150
187
|
run: |
|
|
151
|
-
docker compose -f
|
|
188
|
+
docker compose -f "$COMPOSE_FILE" logs
|
|
152
189
|
|
|
153
190
|
- name: Stop services
|
|
154
191
|
if: always()
|
|
155
|
-
run:
|
|
192
|
+
run: |
|
|
193
|
+
docker compose -f "$COMPOSE_FILE" down -v
|
|
@@ -7,8 +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
|
+
|
|
23
|
+
## [0.3.0] - 2026-01-04
|
|
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
|
+
|
|
10
35
|
## [0.2.2] - 2026-01-03
|
|
11
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
|
+
|
|
12
48
|
## [0.2.1] - 2026-01-03
|
|
13
49
|
|
|
14
50
|
### Added
|
|
@@ -61,7 +97,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
61
97
|
- **E2E test suite**: Docker API tests + Playwright browser tests
|
|
62
98
|
- **Comprehensive test suite**: 350+ Python tests, 90%+ coverage
|
|
63
99
|
|
|
64
|
-
[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
|
|
65
103
|
[0.2.1]: https://github.com/iansokolskyi/stemtrace/compare/v0.2.0...v0.2.1
|
|
66
104
|
[0.2.0]: https://github.com/iansokolskyi/stemtrace/compare/v0.1.1...v0.2.0
|
|
67
105
|
[0.1.1]: https://github.com/iansokolskyi/stemtrace/compare/v0.1.0...v0.1.1
|
|
@@ -168,9 +168,10 @@ e2e-mock:
|
|
|
168
168
|
|
|
169
169
|
# Start E2E test environment (Docker)
|
|
170
170
|
e2e-up:
|
|
171
|
+
docker compose -f docker-compose.e2e.yml build
|
|
171
172
|
docker compose -f docker-compose.e2e.yml up -d --wait
|
|
172
173
|
@echo "Waiting for services..."
|
|
173
|
-
@
|
|
174
|
+
@uv run python scripts/wait_for_http.py http://localhost:8000/stemtrace/api/health --timeout 60
|
|
174
175
|
@echo "✅ E2E environment ready at http://localhost:8000"
|
|
175
176
|
|
|
176
177
|
# Stop E2E test environment
|
|
@@ -193,5 +194,34 @@ e2e:
|
|
|
193
194
|
$(MAKE) e2e-down; \
|
|
194
195
|
exit $$status
|
|
195
196
|
|
|
197
|
+
# =============================================================================
|
|
198
|
+
# E2E Testing (RabbitMQ broker)
|
|
199
|
+
# =============================================================================
|
|
200
|
+
|
|
201
|
+
e2e-up-rabbitmq:
|
|
202
|
+
docker compose -f docker-compose.e2e.rabbitmq.yml build
|
|
203
|
+
docker compose -f docker-compose.e2e.rabbitmq.yml up -d --wait
|
|
204
|
+
@echo "Waiting for services..."
|
|
205
|
+
@uv run python scripts/wait_for_http.py http://localhost:8000/stemtrace/api/health --timeout 60
|
|
206
|
+
@echo "✅ RabbitMQ E2E environment ready at http://localhost:8000"
|
|
207
|
+
|
|
208
|
+
e2e-down-rabbitmq:
|
|
209
|
+
docker compose -f docker-compose.e2e.rabbitmq.yml down -v
|
|
210
|
+
|
|
211
|
+
e2e-api-rabbitmq:
|
|
212
|
+
CELERY_BROKER_URL=amqp://guest:guest@localhost:5672// \
|
|
213
|
+
CELERY_RESULT_BACKEND=redis://localhost:16380/1 \
|
|
214
|
+
uv run pytest tests/e2e/ -m e2e -v
|
|
215
|
+
|
|
216
|
+
e2e-playwright-real-rabbitmq:
|
|
217
|
+
cd $(FRONTEND_DIR) && E2E_MODE=real PLAYWRIGHT_BASE_URL=http://localhost:8000 npm test
|
|
218
|
+
|
|
219
|
+
e2e-rabbitmq:
|
|
220
|
+
$(MAKE) e2e-up-rabbitmq
|
|
221
|
+
$(MAKE) e2e-api-rabbitmq && $(MAKE) e2e-playwright-real-rabbitmq; \
|
|
222
|
+
status=$$?; \
|
|
223
|
+
$(MAKE) e2e-down-rabbitmq; \
|
|
224
|
+
exit $$status
|
|
225
|
+
|
|
196
226
|
# Quick E2E alias (mock mode, no Docker)
|
|
197
227
|
e2e-quick: e2e-mock
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: stemtrace
|
|
3
|
-
Version: 0.
|
|
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)
|
|
@@ -72,7 +72,7 @@ Ever stared at a failed Celery task wondering "what called this?" or "why did it
|
|
|
72
72
|
|
|
73
73
|
Stemtrace captures your task executions as a graph — visualize parent→child flows, see retry chains, track groups and chords, all without adding any new infrastructure.
|
|
74
74
|
|
|
75
|
-
**
|
|
75
|
+
**stemtrace supports Redis and RabbitMQ** for event transport.
|
|
76
76
|
|
|
77
77
|
## ✨ Features
|
|
78
78
|
|
|
@@ -91,7 +91,7 @@ Stemtrace captures your task executions as a graph — visualize parent→child
|
|
|
91
91
|
- **Registry status badges** — Quickly spot tasks that are active, never run, or not registered by any current worker
|
|
92
92
|
|
|
93
93
|
**Production Ready**
|
|
94
|
-
- **Zero Infrastructure** — Uses your existing Redis
|
|
94
|
+
- **Zero Infrastructure** — Uses your existing broker (Redis or RabbitMQ), no database needed
|
|
95
95
|
- **Sensitive Data Scrubbing** — Passwords and API keys filtered automatically
|
|
96
96
|
- **Read-Only** — Safe for production; never modifies your task queue
|
|
97
97
|
- **FastAPI Integration** — Mount into your existing app with one line
|
|
@@ -162,6 +162,14 @@ stemtrace server
|
|
|
162
162
|
|
|
163
163
|
Open [http://localhost:8000](http://localhost:8000).
|
|
164
164
|
|
|
165
|
+
Tip: make sure the server is pointed at the same broker as your workers:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
stemtrace server --broker-url redis://localhost:6379/0
|
|
169
|
+
# or:
|
|
170
|
+
stemtrace server --broker-url amqp://guest:guest@localhost:5672//
|
|
171
|
+
```
|
|
172
|
+
|
|
165
173
|
**Option B: Embed in your FastAPI app** (no extra container)
|
|
166
174
|
|
|
167
175
|
```python
|
|
@@ -175,7 +183,7 @@ stemtrace.init_app(app, broker_url="redis://localhost:6379/0")
|
|
|
175
183
|
|
|
176
184
|
Access at `/stemtrace/` in your existing app — no new services to deploy.
|
|
177
185
|
|
|
178
|
-
See [Deployment Options](
|
|
186
|
+
See [Deployment Options](#deployment-options) for auth, scaling, and more.
|
|
179
187
|
|
|
180
188
|
## 📦 Architecture
|
|
181
189
|
|
|
@@ -294,18 +302,58 @@ batch_processor
|
|
|
294
302
|
- **Timing** — Each node displays start time and duration directly in the graph
|
|
295
303
|
- **Aggregate state** — Container shows running/success/failure based on member states
|
|
296
304
|
|
|
297
|
-
### 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
|
+
```
|
|
298
327
|
|
|
299
328
|
| Variable | Description | Default |
|
|
300
329
|
|----------|-------------|---------|
|
|
301
|
-
| `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`. |
|
|
302
332
|
|
|
303
333
|
### Supported Brokers
|
|
304
334
|
|
|
305
335
|
| Broker | URL Scheme | Status |
|
|
306
336
|
|--------|------------|--------|
|
|
307
337
|
| Redis | `redis://`, `rediss://` | ✅ Supported |
|
|
308
|
-
| RabbitMQ | `amqp://`, `amqps://` |
|
|
338
|
+
| RabbitMQ | `amqp://`, `amqps://`, `pyamqp://` | ✅ Supported |
|
|
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).
|
|
309
357
|
|
|
310
358
|
## 🐳 Docker
|
|
311
359
|
|
|
@@ -315,6 +363,23 @@ docker run -p 8000:8000 \
|
|
|
315
363
|
ghcr.io/iansokolskyi/stemtrace
|
|
316
364
|
```
|
|
317
365
|
|
|
366
|
+
RabbitMQ example:
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
docker run -p 8000:8000 \
|
|
370
|
+
-e STEMTRACE_BROKER_URL=amqp://guest:guest@host.docker.internal:5672// \
|
|
371
|
+
ghcr.io/iansokolskyi/stemtrace
|
|
372
|
+
```
|
|
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
|
+
|
|
318
383
|
Or with Docker Compose:
|
|
319
384
|
|
|
320
385
|
```yaml
|
|
@@ -327,6 +392,8 @@ services:
|
|
|
327
392
|
- STEMTRACE_BROKER_URL=redis://redis:6379/0
|
|
328
393
|
```
|
|
329
394
|
|
|
395
|
+
For a local RabbitMQ setup, see [`docker-compose.rabbitmq.yml`](docker-compose.rabbitmq.yml).
|
|
396
|
+
|
|
330
397
|
## 🖥️ Deployment Options
|
|
331
398
|
|
|
332
399
|
`stemtrace` offers two deployment modes depending on your needs:
|
|
@@ -353,11 +420,22 @@ Open [http://localhost:8000](http://localhost:8000) to view the dashboard.
|
|
|
353
420
|
```bash
|
|
354
421
|
stemtrace server \
|
|
355
422
|
--broker-url redis://myredis:6379/0 \
|
|
423
|
+
--transport-url redis://myredis:6379/0 \
|
|
356
424
|
--host 0.0.0.0 \
|
|
357
425
|
--port 8000 \
|
|
358
426
|
--reload # For development
|
|
359
427
|
```
|
|
360
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
|
+
|
|
361
439
|
#### High-Scale Production Setup
|
|
362
440
|
|
|
363
441
|
Note: `stemtrace server` includes an embedded consumer today (single-process). A multi-process deployment mode is planned.
|
|
@@ -379,6 +457,8 @@ That's it. `init_app()` automatically:
|
|
|
379
457
|
- Mounts the dashboard at `/stemtrace/`
|
|
380
458
|
- Starts the event consumer
|
|
381
459
|
|
|
460
|
+
Tip: you can also set `transport_url` if you want stemtrace events stored separately from your Celery broker.
|
|
461
|
+
|
|
382
462
|
#### Configuration Options
|
|
383
463
|
|
|
384
464
|
```python
|
|
@@ -388,6 +468,7 @@ import stemtrace
|
|
|
388
468
|
extension = stemtrace.init_app(
|
|
389
469
|
app,
|
|
390
470
|
broker_url="redis://localhost:6379/0",
|
|
471
|
+
transport_url=None, # Defaults to broker_url
|
|
391
472
|
prefix="/stemtrace", # Mount path AND event stream prefix (normalized)
|
|
392
473
|
ttl=86400, # Event TTL in seconds
|
|
393
474
|
max_nodes=10000, # Max nodes in memory
|
|
@@ -407,7 +488,26 @@ from your_app.auth import require_admin
|
|
|
407
488
|
stemtrace.init_app(app, broker_url="redis://localhost:6379/0", auth_dependency=Depends(require_admin))
|
|
408
489
|
```
|
|
409
490
|
|
|
410
|
-
|
|
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)
|
|
411
511
|
|
|
412
512
|
```python
|
|
413
513
|
import stemtrace
|
|
@@ -437,12 +537,12 @@ stemtrace.init_app(
|
|
|
437
537
|
- ✅ **Sensitive data scrubbing** — Passwords and API keys filtered automatically
|
|
438
538
|
- ✅ **Real-time updates** — WebSocket-powered live dashboard
|
|
439
539
|
- ✅ **FastAPI integration** — Mount into your existing app
|
|
540
|
+
- ✅ **RabbitMQ support** — Use your existing RabbitMQ broker (`amqp://`, `amqps://`, `pyamqp://`)
|
|
440
541
|
- ✅ **Workers page** — Monitor online/offline workers and their registered tasks
|
|
441
542
|
- ✅ **Task registry** — Browse discovered + registered tasks with clear status badges
|
|
442
543
|
|
|
443
544
|
### Coming Soon
|
|
444
545
|
|
|
445
|
-
- 🔜 **RabbitMQ support** — Use your existing RabbitMQ broker
|
|
446
546
|
- 🔜 **Anomaly detection** — Spot stuck, orphaned, or failed tasks
|
|
447
547
|
- 🔜 **Dashboard with stats** — Success rates, durations, failure trends
|
|
448
548
|
- 🔜 **OpenTelemetry export** — Send traces to Jaeger, Tempo, Datadog
|