Skip to content

Expose hosted-proxy store size and flush-duration metrics#468

Merged
alistair3149 merged 1 commit into
masterfrom
metrics-proxy-store-gauges
Jul 23, 2026
Merged

Expose hosted-proxy store size and flush-duration metrics#468
alistair3149 merged 1 commit into
masterfrom
metrics-proxy-store-gauges

Conversation

@alistair3149

@alistair3149 alistair3149 commented Jul 23, 2026

Copy link
Copy Markdown
Member

Summary

The hosted OAuth proxy's upstream-token map grows with cumulative sign-ins and is never swept, and every token write flushes the whole store synchronously (serialize + AES-GCM encrypt + write). Today there is no operator signal for either — you cannot tell whether the map's memory or the per-refresh flush cost is becoming a problem. This adds that signal.

What changed

Three Prometheus series on /metrics (when MCP_METRICS=true):

  • mcp_proxy_store_upstream_tokens (gauge) — the unbounded set; grows with cumulative sign-ins.
  • mcp_proxy_store_clients (gauge) — FIFO-capped registered clients.
  • mcp_proxy_store_flush_duration_seconds (histogram) — durable-flush latency, with finer sub-millisecond buckets than the tool-call histogram.

The gauges are read on scrape via a stats provider wired in buildApp, mirroring the existing mcp_active_sessions pattern; backed by a new ProxyStore.stats(). The histogram is observed in the persistence store's flushSync.

Testing

  • Test-driven: unit tests for stats(), the flush histogram, and the lazy-provider gauges (including the zero-default and disabled-recorder no-op paths); an integration test that a durable write records a flush duration end-to-end.
  • Full suite 1548 passing; tsc, oxlint, oxfmt clean.
  • Boot smoke with MCP_METRICS=true: all three series are exposed on /metrics.
  • docs/operations.md "Exposed series" list and a CHANGELOG entry updated.

🤖 Generated with Claude Code

@alistair3149
alistair3149 force-pushed the metrics-proxy-store-gauges branch 2 times, most recently from bc862ba to e54fa31 Compare July 23, 2026 04:55
…rics

The proxy's upstream-token map grows with cumulative sign-ins and is never
swept, and every token write flushes the whole store synchronously (serialize +
encrypt + write). Neither the growth, the per-refresh flush cost, nor a failing
flush had any operator signal.

Add four Prometheus series on /metrics (when MCP_METRICS=true):

- mcp_proxy_store_upstream_tokens (gauge) and mcp_proxy_store_clients (gauge),
  read on scrape via a stats provider wired in buildApp, mirroring the existing
  mcp_active_sessions gauge. Backed by a new ProxyStore.stats().
- mcp_proxy_store_flush_duration_seconds (histogram), observed in the persistence
  store's flushSync with finer sub-millisecond buckets. Successful flushes only.
- mcp_proxy_store_flush_failures_total (counter), incremented in flushSync's catch
  so a slow-and-failing flush is visible to /metrics, not only in the onError log.
  A failed flush leaves the latest sign-in change in memory only, so it is the
  signal an operator alerts on.

These are the gate for deciding whether the token-map eviction sweep and per-row
persistence are worth building; instrument before engineering.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alistair3149
alistair3149 force-pushed the metrics-proxy-store-gauges branch from e54fa31 to 697b46f Compare July 23, 2026 04:57
@alistair3149
alistair3149 marked this pull request as ready for review July 23, 2026 04:58
@alistair3149
alistair3149 merged commit c085091 into master Jul 23, 2026
1 check passed
@alistair3149
alistair3149 deleted the metrics-proxy-store-gauges branch July 23, 2026 04:58
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.

1 participant