Skip to content

observability: record audit trace spans for classroom requests - #38

Merged
nycomp merged 2 commits into
mainfrom
feat/37-audit-tracing
Oct 5, 2026
Merged

nycomp merged 2 commits into
mainfrom
feat/37-audit-tracing

Conversation

@nycomp

@nycomp nycomp commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Parent: nyjc-computing/campus#816 (item 2 — client apps as trace producers). Refs #37.

What

Make classroom a campus audit trace producer: when AUDIT_TRACING_ENABLED=1, the app factory wires campus.audit.middleware.init_app into the Flask app, so every classroom request is recorded as a span in the audit service.

Combined with SDK trace propagation (nyjc-computing/campus-api-python#93), campus SDK calls made while handling a classroom request carry X-Request-ID/X-Parent-Span-ID and land as child spans — the audit waterfall then answers which classroom route fired each campus call, in what order (the duplicate GET /auth/v1/sessions/... question in campus#816).

Decisions (the open questions in #37)

  • Dependency shape: resolved — no extraction needed. classroom already depends on campus-suite (pyproject, branch weekly) and the middleware ships in it, so wiring is imports + config only. Flagged on campus#816; extraction into a shared package stays a non-goal unless the contract grows (W3C traceparent).
  • Config surface: opt-in (AUDIT_TRACING_ENABLED=1 + AUDIT_API_KEY=<producer key>), default off — a client app shouldn't ingest spans without an explicit key. Read once at app creation: flipping the flag is a redeploy, not a runtime change (same semantics as the campus services' gate). Dev deployment only for now; staging/prod get it when they exist.
  • Volume: span ingestion is one async worker per service, fail-safe (missing/broken key only loses spans, never requests) — fine at classroom's scale.

Verification

  • Local: middleware registers start_span/end_span with the flag set; X-Request-ID echoed on responses; flag unset → no hooks (kill-switch path); cross-repo contract check — the middleware's flask.g stash read by the new campus_python.tracing produces both headers.
  • E2E (post-merge, on the dev deployment): classroom login should produce classroom root spans with auth calls as child spans; kill switch re-verified live with AUDIT_TRACING_ENABLED=0.

Notes

  • poetry.lock bump for the SDK propagation commit lands as a follow-up commit on this branch once campus-api-python#93 merges (git dep pinned by lock).
  • Pre-existing ruff findings in the touched file (I001/E722/E501) are unchanged by this PR.
  • Follow-up (not this PR): classroom spans could carry the signed-in user (flask.g.user → span user_id) — needs a small stash in flask_campus.OAuthLoginManager (campus repo).

Make classroom a campus audit trace producer (campus#816 item 2, #37):
with AUDIT_TRACING_ENABLED=1 and AUDIT_API_KEY set, classroom requests
are recorded as spans in the audit service, and campus SDK calls made
while handling a request carry trace context and land as child spans —
the audit waterfall then shows which classroom route fired each campus
call.

- Opt-in via AUDIT_TRACING_ENABLED (default off; read once at app
  creation, flip = redeploy). Producer key recipe: campus
  docs/audit-tracing.md. Ingestion is async and fail-safe.
- Dependency shape (the open decision in #37): resolved — no extraction
  needed; classroom already depends on campus-suite and the middleware
  ships in it. Documented on campus#816.

SDK call propagation itself lands with campus-api-python#93; classroom
picks it up via the campus-api-python lock bump once that PR merges.
- campus-api-python -> dd84fc7: SDK trace-context propagation (#93) —
  SDK calls made while handling a traced classroom request carry
  X-Request-ID / X-Parent-Span-ID and land as child audit spans.
- campus-suite -> de7ec3c (weekly 2026-10-05): current middleware with
  producer-side span secret redaction (#805) and journey tagging (#803)
  — required before classroom starts ingesting spans.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants