|
| 1 | +--- |
| 2 | +title: Monitoring and memory triage |
| 3 | +description: Collect Prometheus metrics, use Grafana dashboards, and investigate Codex Pooler production memory spikes without exposing request content. |
| 4 | +--- |
| 5 | + |
| 6 | +Codex Pooler exposes Prometheus metrics at `/metrics`. Metrics auth is managed from `/admin/system`; if a bearer token is configured, Prometheus must scrape with the matching Kubernetes Secret reference instead of putting the raw token in Helm values. |
| 7 | + |
| 8 | +Use monitoring for runtime evidence only. Dashboards, alerts, logs, tickets, and copied queries must not include prompts, response bodies, uploaded files, websocket frames, cookies, bearer tokens, upstream secrets, or raw Pool API keys. |
| 9 | + |
| 10 | +## Collector path |
| 11 | + |
| 12 | +The Helm chart can render a Prometheus Operator `ServiceMonitor` for the app service: |
| 13 | + |
| 14 | +```yaml |
| 15 | +monitoring: |
| 16 | + serviceMonitor: |
| 17 | + enabled: true |
| 18 | + labels: |
| 19 | + release: kube-prometheus-stack |
| 20 | + interval: 10s |
| 21 | + scrapeTimeout: 5s |
| 22 | +``` |
| 23 | +
|
| 24 | +The `release` label and scrape interval should match your own Prometheus Operator selectors and scrape budget. For fast OOM investigations, prefer a short interval for the app ServiceMonitor and keep broader Kubernetes collectors at their normal cadence. |
| 25 | + |
| 26 | +## Memory dashboard |
| 27 | + |
| 28 | +Build your Grafana or Prometheus dashboard around the signals needed to correlate a fast memory spike: |
| 29 | + |
| 30 | +1. Kubernetes cgroup working set versus pod memory limit |
| 31 | +2. BEAM memory total, processes, binary, ETS, code, and atom memory by pod |
| 32 | +3. BEAM process count, port count, and run queue |
| 33 | +4. app restarts, OOM events, and last terminated reason |
| 34 | +5. request rate and p95 endpoint/router latency |
| 35 | +6. stream-buffer oversized and truncated events |
| 36 | + |
| 37 | +Read the dashboard as a correlation view. If cgroup memory climbs while BEAM total stays flat, look outside normal BEAM heap attribution. If `vm_memory_binary_bytes` climbs with cgroup memory, inspect streaming response retention, file bodies, and upstream transport buffering. If process count, ports, or run queue climb, inspect stuck request processes, websocket ownership, and overloaded route classes. |
| 38 | + |
| 39 | +## Useful PromQL |
| 40 | + |
| 41 | +```text |
| 42 | +max by (pod) ( |
| 43 | + container_memory_working_set_bytes{namespace="codex-pooler", container="app", image!=""} |
| 44 | +) |
| 45 | +``` |
| 46 | + |
| 47 | +```text |
| 48 | +vm_memory_total_bytes{namespace="codex-pooler", job="codex-pooler-app"} |
| 49 | +vm_memory_binary_bytes{namespace="codex-pooler", job="codex-pooler-app"} |
| 50 | +vm_memory_processes_bytes{namespace="codex-pooler", job="codex-pooler-app"} |
| 51 | +vm_memory_ets_bytes{namespace="codex-pooler", job="codex-pooler-app"} |
| 52 | +``` |
| 53 | + |
| 54 | +```text |
| 55 | +increase(kube_pod_container_status_restarts_total{ |
| 56 | + namespace="codex-pooler", |
| 57 | + exported_container="app" |
| 58 | +}[15m]) |
| 59 | +``` |
| 60 | + |
| 61 | +```text |
| 62 | +rate(codex_pooler_gateway_stream_buffer_oversized_count_total[5m]) |
| 63 | +rate(codex_pooler_gateway_stream_buffer_truncated_count_total[5m]) |
| 64 | +``` |
| 65 | + |
| 66 | +## Memory sampler logs |
| 67 | + |
| 68 | +The in-process memory sampler is enabled by default. When BEAM total memory or cgroup usage crosses the configured threshold, it logs a sanitized snapshot with memory categories, process and port counts, top processes by memory, and top processes by message queue length. |
| 69 | + |
| 70 | +Emergency tuning environment variables: |
| 71 | + |
| 72 | +```bash |
| 73 | +CODEX_POOLER_MEMORY_SAMPLER_ENABLED=true |
| 74 | +CODEX_POOLER_MEMORY_SAMPLER_THRESHOLD_RATIO=0.70 |
| 75 | +CODEX_POOLER_MEMORY_SAMPLER_MIN_INTERVAL_MS=60000 |
| 76 | +CODEX_POOLER_MEMORY_SAMPLER_TOP_PROCESSES=20 |
| 77 | +CODEX_POOLER_MEMORY_SAMPLER_LIMIT_BYTES=1073741824 |
| 78 | +``` |
| 79 | + |
| 80 | +Use a lower threshold or shorter interval only during active investigation, because logs are the only signal likely to capture a spike that reaches OOM before the next Prometheus scrape. |
0 commit comments