Skip to content

Commit 237849d

Browse files
authored
fix: psycopg2 register_default_jsonb TypeError with InstrumentedConnection + stack tests (#52)
1 parent 735730d commit 237849d

41 files changed

Lines changed: 2189 additions & 92 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/e2e.yml

Lines changed: 94 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,43 @@ on:
1515

1616
jobs:
1717
discover:
18-
name: Discover E2E Tests
18+
name: Discover Tests
1919
runs-on: ubuntu-latest
2020
outputs:
21-
matrix: ${{ steps.set-matrix.outputs.matrix }}
21+
e2e_matrix: ${{ steps.set-matrix.outputs.e2e_matrix }}
22+
stack_matrix: ${{ steps.set-matrix.outputs.stack_matrix }}
2223
steps:
2324
- name: Checkout
2425
uses: actions/checkout@v4
2526

26-
- name: Find all e2e-tests directories
27+
- name: Find all test directories
2728
id: set-matrix
2829
run: |
29-
# Find all directories with e2e-tests and convert to JSON array
30-
LIBRARIES=$(find drift/instrumentation -type d -name "e2e-tests" \
30+
# Find all e2e-tests directories (single instrumentation)
31+
E2E_TESTS=$(find drift/instrumentation -type d -name "e2e-tests" \
3132
| sed 's|drift/instrumentation/||' | sed 's|/e2e-tests||' | sort \
3233
| jq -R -s -c 'split("\n") | map(select(length > 0))')
3334
34-
echo "Found libraries with e2e-tests: $LIBRARIES"
35-
echo "matrix=$LIBRARIES" >> $GITHUB_OUTPUT
35+
# Find all stack-tests directories (multi-instrumentation)
36+
STACK_TESTS=$(find drift/stack-tests -mindepth 1 -maxdepth 1 -type d 2>/dev/null \
37+
| xargs -I {} basename {} | sort \
38+
| jq -R -s -c 'split("\n") | map(select(length > 0))') || echo "[]"
39+
40+
echo "Found e2e-tests: $E2E_TESTS"
41+
echo "Found stack-tests: $STACK_TESTS"
42+
echo "e2e_matrix=$E2E_TESTS" >> $GITHUB_OUTPUT
43+
echo "stack_matrix=$STACK_TESTS" >> $GITHUB_OUTPUT
3644
3745
e2e:
38-
name: E2E Tests - ${{ matrix.library }}
46+
name: E2E - ${{ matrix.library }}
3947
needs: discover
4048
runs-on: ubuntu-latest
4149
timeout-minutes: 30
4250
strategy:
4351
fail-fast: false
4452
max-parallel: 6
4553
matrix:
46-
library: ${{ fromJSON(needs.discover.outputs.matrix) }}
54+
library: ${{ fromJSON(needs.discover.outputs.e2e_matrix) }}
4755
steps:
4856
- name: Checkout
4957
uses: actions/checkout@v4
@@ -109,3 +117,80 @@ jobs:
109117
docker volume prune -f || true
110118
# Clean up networks
111119
docker network prune -f || true
120+
121+
stack:
122+
name: Stack - ${{ matrix.test }}
123+
needs: discover
124+
if: ${{ needs.discover.outputs.stack_matrix != '[]' && needs.discover.outputs.stack_matrix != '' }}
125+
runs-on: ubuntu-latest
126+
timeout-minutes: 30
127+
strategy:
128+
fail-fast: false
129+
max-parallel: 3
130+
matrix:
131+
test: ${{ fromJSON(needs.discover.outputs.stack_matrix) }}
132+
steps:
133+
- name: Checkout
134+
uses: actions/checkout@v4
135+
136+
- name: Install uv
137+
uses: astral-sh/setup-uv@v4
138+
with:
139+
version: "latest"
140+
141+
- name: Setup Python
142+
run: uv python install 3.9
143+
144+
- name: Setup Docker Buildx
145+
uses: docker/setup-buildx-action@v3
146+
with:
147+
driver: docker
148+
149+
- name: Install SDK dependencies
150+
run: uv sync --all-extras
151+
152+
- name: Build SDK
153+
run: uv build
154+
155+
- name: Verify SDK build
156+
run: |
157+
ls -la dist/ || (echo "dist folder not found!" && exit 1)
158+
test -f dist/*.whl || (echo "SDK build incomplete!" && exit 1)
159+
160+
- name: Get latest Tusk CLI version
161+
id: tusk-version
162+
run: |
163+
VERSION=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
164+
"https://api.github.com/repos/Use-Tusk/tusk-drift-cli/releases/latest" \
165+
| grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
166+
echo "version=$VERSION" >> $GITHUB_OUTPUT
167+
echo "Latest Tusk CLI version: $VERSION"
168+
169+
- name: Build base image
170+
env:
171+
DOCKER_DEFAULT_PLATFORM: linux/amd64
172+
run: |
173+
docker build \
174+
--build-arg TUSK_CLI_VERSION=${{ steps.tusk-version.outputs.version }} \
175+
-t python-e2e-base:latest \
176+
-f drift/instrumentation/e2e_common/Dockerfile.base \
177+
.
178+
179+
- name: Run stack tests for ${{ matrix.test }}
180+
env:
181+
DOCKER_DEFAULT_PLATFORM: linux/amd64
182+
TUSK_CLI_VERSION: ${{ steps.tusk-version.outputs.version }}
183+
run: |
184+
chmod +x ./drift/stack-tests/${{ matrix.test }}/run.sh
185+
cd ./drift/stack-tests/${{ matrix.test }} && ./run.sh 8000
186+
187+
- name: Cleanup Docker resources
188+
if: always()
189+
run: |
190+
# Stop all running containers
191+
docker ps -aq | xargs -r docker stop || true
192+
docker ps -aq | xargs -r docker rm || true
193+
# Clean up volumes
194+
docker volume prune -f || true
195+
# Clean up networks
196+
docker network prune -f || true

CONTRIBUTING.md

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,14 @@ E2E tests validate full instrumentation workflows using Docker containers. They
6868

6969
#### Running E2E Tests
7070

71-
Run all e2e tests:
71+
Run all tests (e2e + stack):
7272

7373
```bash
74-
./run-all-e2e-tests.sh # Sequential (default)
75-
./run-all-e2e-tests.sh 2 # 2 tests in parallel
76-
./run-all-e2e-tests.sh 0 # All tests in parallel
74+
./run-all-e2e-tests.sh # Run all tests sequentially
75+
./run-all-e2e-tests.sh -c 2 # Run 2 tests concurrently
76+
./run-all-e2e-tests.sh -c 0 # Run all tests in parallel
77+
./run-all-e2e-tests.sh --instrumentation-only # Run only e2e tests
78+
./run-all-e2e-tests.sh --stack-only # Run only stack tests
7779
```
7880

7981
Run a single instrumentation's e2e test:
@@ -143,12 +145,28 @@ python src/test_requests.py
143145
144146
For more details, see `drift/instrumentation/README-e2e-tests.md`.
145147
148+
### Stack Tests
149+
150+
Stack tests validate multiple instrumentations working together in realistic application architectures (e.g., Django + PostgreSQL, FastAPI + Redis). They catch bugs at integration points that don't surface in isolated e2e testing.
151+
152+
```bash
153+
# Run a specific stack test
154+
cd drift/stack-tests/django-postgres
155+
./run.sh
156+
157+
# Or run all tests (including stack tests) from the root
158+
./run-all-e2e-tests.sh
159+
```
160+
161+
For available tests and details, see `drift/stack-tests/README.md`.
162+
146163
## Documentation
147164

148165
| Document | Description |
149166
|----------|-------------|
150167
| `docs/context-propagation.md` | Context propagation behavior, edge cases, and patterns |
151168
| `drift/instrumentation/README-e2e-tests.md` | E2E test architecture and debugging |
169+
| `drift/stack-tests/README.md` | Stack tests for multi-instrumentation scenarios |
152170

153171
## For Maintainers
154172

E2E_TESTING_GUIDE.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,16 @@ To run all E2E tests across all instrumentations:
294294
./run-all-e2e-tests.sh
295295
296296
# 2 tests in parallel
297-
./run-all-e2e-tests.sh 2
297+
./run-all-e2e-tests.sh -c 2
298298
299299
# All tests in parallel (unlimited)
300-
./run-all-e2e-tests.sh 0
300+
./run-all-e2e-tests.sh -c 0
301+
302+
# Run only single-instrumentation e2e tests
303+
./run-all-e2e-tests.sh --instrumentation-only
304+
305+
# Run only stack tests
306+
./run-all-e2e-tests.sh --stack-only
301307
```
302308

303309
## Quick Reference Commands

drift/instrumentation/README-e2e-tests.md

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ cd drift/instrumentation/flask/e2e-tests
5959
./run.sh
6060
```
6161

62-
---
63-
6462
### 2. fastapi
6563

6664
**Purpose:** Test FastAPI ASGI instrumentation
@@ -81,8 +79,6 @@ cd drift/instrumentation/fastapi/e2e-tests
8179
./run.sh
8280
```
8381

84-
---
85-
8682
### 3. django
8783

8884
**Purpose:** Test Django middleware instrumentation
@@ -103,8 +99,6 @@ cd drift/instrumentation/django/e2e-tests
10399
./run.sh
104100
```
105101

106-
---
107-
108102
### 4. redis
109103

110104
**Purpose:** Test Redis instrumentation
@@ -124,8 +118,6 @@ cd drift/instrumentation/redis/e2e-tests
124118
./run.sh
125119
```
126120

127-
---
128-
129121
### 5. psycopg
130122

131123
**Purpose:** Test Psycopg (v3) PostgreSQL instrumentation
@@ -146,8 +138,6 @@ cd drift/instrumentation/psycopg/e2e-tests
146138
./run.sh
147139
```
148140

149-
---
150-
151141
### 6. psycopg2
152142

153143
**Purpose:** Test Psycopg2 (legacy) PostgreSQL instrumentation
@@ -166,8 +156,6 @@ cd drift/instrumentation/psycopg2/e2e-tests
166156
./run.sh
167157
```
168158

169-
---
170-
171159
## How E2E Tests Work
172160

173161
### Architecture
@@ -225,8 +213,6 @@ The e2e tests follow a **Docker entrypoint-driven architecture** where the Pytho
225213
- Python uses Docker entrypoint for orchestration
226214
- Both approaches work, but Python approach is more maintainable
227215

228-
---
229-
230216
## Prerequisites
231217

232218
### 1. Build Base Image
@@ -247,8 +233,6 @@ This image contains:
247233

248234
All tests require Docker and Docker Compose.
249235

250-
---
251-
252236
## Running Tests
253237

254238
### Single Test
@@ -272,10 +256,16 @@ cd drift/instrumentation/flask/e2e-tests
272256
./run-all-e2e-tests.sh
273257

274258
# 2 tests in parallel
275-
./run-all-e2e-tests.sh 2
259+
./run-all-e2e-tests.sh -c 2
276260

277261
# All tests in parallel (unlimited)
278-
./run-all-e2e-tests.sh 0
262+
./run-all-e2e-tests.sh -c 0
263+
264+
# Run only single-instrumentation e2e tests
265+
./run-all-e2e-tests.sh --instrumentation-only
266+
267+
# Run only stack tests
268+
./run-all-e2e-tests.sh --stack-only
279269
```
280270

281271
### All Tests (Manual Parallel)
@@ -289,8 +279,6 @@ wait
289279

290280
Each test uses a unique Docker Compose project name based on the port, so they don't conflict.
291281

292-
---
293-
294282
## Understanding Test Output
295283

296284
### Successful Test
@@ -341,8 +329,6 @@ If the test fails, you'll see:
341329

342330
Traces are preserved in `.tusk/traces/` for inspection.
343331

344-
---
345-
346332
## Debugging Tests
347333

348334
### View Traces
@@ -389,8 +375,6 @@ docker compose build
389375
docker compose run --rm app /bin/bash
390376
```
391377

392-
---
393-
394378
## CI Integration
395379

396380
### GitHub Actions Example
@@ -436,8 +420,6 @@ jobs:
436420
path: drift/instrumentation/${{ matrix.test }}/e2e-tests/.tusk/traces/
437421
```
438422
439-
---
440-
441423
## Adding New Tests
442424
443425
To add a new e2e test:
@@ -464,8 +446,6 @@ To add a new e2e test:
464446

465447
5. **Add to CI**: Update GitHub Actions workflow
466448

467-
---
468-
469449
## Troubleshooting
470450

471451
### "python-e2e-base:latest not found"
@@ -565,8 +545,6 @@ The e2e test runner checks for these warnings after running tests. If found, the
565545

566546
This is equivalent to the Node.js SDK's `check_tcp_instrumentation_warning` check.
567547

568-
---
569-
570548
## Comparison with Node.js E2E Tests
571549

572550
| Aspect | Node.js | Python |
@@ -581,17 +559,13 @@ This is equivalent to the Node.js SDK's `check_tcp_instrumentation_warning` chec
581559

582560
Both approaches achieve the same goal, but Python's entrypoint-driven design is simpler and more maintainable.
583561

584-
---
585-
586562
## Related Documentation
587563

588564
- [Base Dockerfile](./e2e_common/Dockerfile.base) - Python e2e base Docker image
589565
- [Base Runner](./e2e_common/base_runner.py) - Shared e2e test runner class
590566
- [Python SDK README](../../README.md) - Main Python SDK documentation
591567
- [CONTRIBUTING.md](../../CONTRIBUTING.md) - Contribution guidelines with e2e test instructions
592568

593-
---
594-
595569
## Maintaining These Tests
596570

597571
### Updating Tusk CLI Version
@@ -623,8 +597,6 @@ Update `requirements.txt` in specific test directory:
623597
Flask>=3.2.0 # Update version
624598
```
625599

626-
---
627-
628600
## Success Criteria
629601

630602
All tests should:

0 commit comments

Comments
 (0)