Skip to content

Add web-pod observability: memory/OOM watchdog, in-flight-request logging, concurrency counters #115

Description

@grossir

Problem

PR #114 (part of #113) captures the stack of a timed-out worker and logs per-request durations. That closes the hang attribution gap, but three diagnostic blind spots remain — all observability concerns that were deliberately scoped out of #114 to keep it low-risk and reviewable.

Gaps to close

1. OOM / SIGKILL is a black box (highest value)

scanning-web workers are SIGKILL'd (SCANNING-1W, "perhaps out of memory"), and SIGKILL is uncatchable — the only way to get evidence is to log before the kill. There is currently no in-process memory signal at all. Proposed:

  • A lightweight background thread logging worker RSS every N seconds (a memory-over-time trace in pod logs, line up against the kill timestamp).
  • A pre-OOM watchdog: when RSS crosses a soft threshold (e.g. 85% of the pod limit), dump all-thread stacks + RSS to stderr/Sentry. The only in-process route to "what was the worker doing when it ran out of memory."

2. No "which request + params" attribution

faulthandler names the view function, but not the request context (which scan.pk, user, URL params). And gunicorn's access log writes a line on response completion, so a request that hangs until the worker is killed never logs — the access log shows everything except the culprit. Proposed:

  • An in-flight-request logger: middleware records (thread, url, scan_pk, user, start_time) on entry into a shared dict; a background thread logs any entry older than N seconds (with elapsed + context) while it's still hung, and clears it on completion. Names the frozen endpoint with its params, before the kill.

3. Threadpool / concurrency saturation is invisible

A leading hypothesis is asgiref-threadpool exhaustion / GIL starvation, but nothing logs it. Proposed:

  • Periodically log in-flight request count and threading.active_count() (pairs naturally with #2's shared state).

Optional

  • send_default_pii=True in Sentry init to attach user/request details to error events (privacy tradeoff).
  • Structured/JSON logs for searchability in the EKS log aggregator.

Definition of done

  • Worker RSS is visible over time in logs; a pre-OOM threshold dump exists, letting SCANNING-1W be classified (pod OOM vs node pressure).
  • A hung request is logged with its endpoint + params (scan_pk, user) while still in flight.
  • In-flight/active-thread counts are logged, enough to confirm or rule out threadpool saturation.

Notes

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Status
Scanning backlog

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions