Skip to content

jinooos/observabilitypoc

Repository files navigation

Observability POC Testbed

A minimal FastAPI notes app with 4 deliberately seeded issues, sitting behind an nginx reverse proxy that injects an OpenReplay tracker snippet. Use this to validate an observability setup before rebuilding it into the real app.

Directory structure

observability_poc/
├── app/
│   ├── main.py              # FastAPI backend (CRUD + 1 seeded slow endpoint)
│   ├── static/
│   │   ├── index.html       # UI incl. 1 seeded dead-click button
│   │   ├── app.js           # incl. 1 seeded broken API call, 1 seeded JS error
│   │   └── style.css
├── tests/
│   └── test_api.py          # pytest, core CRUD only (written before app code)
├── proxy/
│   └── nginx.conf           # reverse proxy, injects tracker snippet
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── README.md

Run it

docker compose up --build

This starts two containers:

  • app — FastAPI backend on port 8000, not published to the host
  • proxy — nginx on port 8080, the only entry point

Access the app through the proxy, not directly: http://localhost:8080

Run tests

python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
pytest tests/ -v

All 10 tests cover core CRUD (create/list/get/delete notes) and pass against the real implementation — none were weakened to pass.

OpenReplay tracker snippet

Lives in proxy/nginx.conf. The proxy uses sub_filter to rewrite the HTML response from the app, inserting the tracker immediately before </head> on every page load.

The project's snippet was given in npm/ESM form (import { tracker } from '@openreplay/tracker'), and this app is plain static HTML/JS with no bundler, so it's loaded as a native ES module via a jsdelivr +esm CDN re-export of the package instead:

sub_filter '</head>' '<script type="module">
import { tracker } from "https://cdn.jsdelivr.net/npm/@openreplay/tracker@latest/+esm";
tracker.configure({
  projectKey: "Xg0cg4l4qtBpkAcQGwCM",
  ingestPoint: "https://analyticspoc.ap.openreplay.cloud/ingest",
});
tracker.start();
</script>
</head>';
sub_filter_once on;

To change the project key/ingest point, edit those values directly in proxy/nginx.conf and restart the proxy container (docker compose restart proxy) — no app rebuild needed.

Seeded issues (each tagged # SEEDED-ISSUE: <type> or <!-- SEEDED-ISSUE: <type> --> in code)

# Type Where What happens
a broken-api-call app/static/app.js, "Export Notes" button Calls GET /api/notes/export-csv, which doesn't exist on the backend → 404
b unhandled-js-error app/static/app.js, "View Note Stats" button Sets .innerHTML on a DOM element (#note-stats-panel) that's never rendered → uncaught TypeError
c dead-click app/static/index.html, "Settings" button Rendered as a normal button, no event listener ever attached to it
d slow-response app/main.py, GET /api/notes/{id}/archive time.sleep(6) before responding — triggered by the "Archive" button on any note

To exercise (c) and (b), add a note first via the form, then click "View Note Stats" / "Archive" / "Export Notes" / "Settings" from the UI at http://localhost:8080.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors