Phase 3 + Phase 6 of the Stack Activity audit (PR 2 of 2):
- StackActivityMetricsService: in-process counters and ring-buffered
latency histogram (1000 samples per nodeId/op pair). Mirrors the
FileExplorerMetricsService pattern shipped in #1216. No external
export. Records (nodeId, op) where op is read or write, with
success/error counts and p50/p95 latency on demand.
- Admin endpoint GET /api/stack-activity-metrics returns the snapshot.
Admin-only via requireAdmin, mounted next to the file-explorer
metrics route. An operator debugging "why is the activity tab slow
on this node?" can pull per-(nodeId, op) counts and latencies
without scrolling logs.
- Diagnostic logs: route handler emits a structured [StackActivity:diag]
read entry per request (stackName, nodeId, limit, before, beforeId,
returned, elapsedMs); dispatchAlert emits a [StackActivity:diag] write
entry per persisted notification (category, stackName, nodeId, actor,
messageLen). Both gated on developer_mode via isDebugEnabled. Same
namespace so a single grep covers reads and writes on the timeline
path. Per-request and per-event, never inside a poll loop.
- Metric record points: the route's try/finally records a read metric
with the outcome of the DB call; dispatchAlert records a write metric
on both the success path and (before re-throwing) the failure path,
so error rates from the insert path stay visible.
- docs/features/stack-activity.mdx: refreshed to reflect PR 1's
retention behavior (30 days plus per-(node, stack) 500-row cap, 1000
per-node unattached), composite (timestamp, id) cursor, error-vs-
empty UI distinction, and "by username" vs "via Subsystem" actor
rendering. Adds Troubleshooting entries for "Activity unavailable"
(node disconnect or fetch failure), "expected event missing"
(retention windows), and "same restart shows twice" (manual click
vs Auto-Heal redeploy are distinct events).
No tier, role, or capability gate touched. The admin metrics endpoint
inherits the standard requireAdmin gate already used by /api/file-
explorer-metrics and /api/stack-metrics.