Skip to content

Commit 2a7b7cf

Browse files
committed
add minimum repro case
1 parent 4739945 commit 2a7b7cf

File tree

6 files changed

+3312
-2055
lines changed

6 files changed

+3312
-2055
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# FastAPI Exception Capture Usage
2+
3+
Minimal reproduction of PostHog exception capture issue.
4+
5+
## Quick Start
6+
7+
```bash
8+
cd posthog-python/playgrounds/fastapi-exception-capture
9+
export POSTHOG_API_KEY="your_key"
10+
uv sync
11+
uv run python app.py
12+
```
13+
14+
## Test
15+
16+
```bash
17+
curl http://localhost:8000/test-exception
18+
```
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/usr/bin/env python3
2+
3+
import logging
4+
import os
5+
6+
from fastapi import FastAPI
7+
from fastapi.responses import JSONResponse
8+
from posthog import Posthog
9+
10+
logging.basicConfig(level=logging.INFO)
11+
logger = logging.getLogger(__name__)
12+
13+
app = FastAPI()
14+
15+
POSTHOG_API_KEY = os.getenv("POSTHOG_API_KEY", "phc_PLACEHOLDER_KEY")
16+
POSTHOG_HOST = os.getenv("POSTHOG_HOST", "https://us.i.posthog.com")
17+
18+
19+
@app.exception_handler(Exception)
20+
async def global_exception_handler(request, exception):
21+
client = Posthog(
22+
POSTHOG_API_KEY,
23+
host=POSTHOG_HOST,
24+
log_captured_exceptions=True,
25+
debug=True,
26+
)
27+
28+
user_id = "anonymous"
29+
properties = {"url": str(request.url)}
30+
31+
capture_id = client.capture_exception(
32+
exception,
33+
distinct_id=user_id,
34+
properties=properties,
35+
)
36+
37+
logger.info(
38+
f"Captured exception: {exception.__class__.__name__} ({str(exception)[:100]}), id: {capture_id}"
39+
)
40+
41+
return JSONResponse(
42+
status_code=500,
43+
content={
44+
"error": "Internal server error",
45+
"capture_id": capture_id,
46+
},
47+
)
48+
49+
50+
@app.get("/")
51+
async def root():
52+
return {"message": "PostHog Exception Capture Playground"}
53+
54+
55+
@app.get("/test-exception")
56+
async def test_exception():
57+
raise Exception("TEST BACKEND EXCEPTION")
58+
59+
60+
if __name__ == "__main__":
61+
import uvicorn
62+
63+
print("Starting server...")
64+
print(f"PostHog Host: {POSTHOG_HOST}")
65+
print("\nTest: curl http://localhost:8000/test-exception")
66+
uvicorn.run(app, host="127.0.0.1", port=8000, log_level="info")
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[project]
2+
name = "fastapi-exception-capture-playground"
3+
version = "0.1.0"
4+
requires-python = ">=3.9"
5+
dependencies = ["fastapi>=0.104.0", "uvicorn[standard]>=0.24.0", "posthog"]
6+
7+
[tool.uv.sources]
8+
posthog = { path = "../..", editable = true }

0 commit comments

Comments
 (0)