Skip to main content

JVM profiling (ign jvm) — the special mode

ign jvm is a special mode, not a routine diagnostic: every intrusive verb ACTIVELY instruments the gateway JVM. Do not run it against a production server casually — it belongs inside an approved change window, with a rollback plan, at the shortest duration that answers the question. The mode exists for the non-production deep-dive (a rig, a UAT gateway, a repro environment) and for the rare, deliberate production incident.

Both mechanisms ride the ALREADY-deployed, secret-gated scriptExec route (the posture above applies in full — an undeployed route refuses exit 6 script_exec_not_configured with zero HTTP):

  • ign jvm sample — a sampling thread profiler: a Jython loop inside the gateway JVM takes ThreadMXBean.dumpAllThreads every --interval-ms for --duration-secs, aggregating server-side into a hot-methods rollup and occurrence-counted stacks. The folded field (and --folded-out PATH sidecar) is flamegraph-ready input. Pure JVM reads — no JVM flags, no agents, no disk. CPU overhead grows with thread count × frequency.
  • ign jvm jfr — Java Flight Recorder over the com.sun.management:type=DiagnosticCommand MBean (the jcmd-over-MBean trick). start is memory-buffered and duration-capped so the recording auto-stops even if you forget; stop dumps to the gateway's temp dir, streams the bytes back base64, and deletes the remote file; status lists recordings verbatim.

The safety contract, in order of enforcement:

  1. A dedicated gate flag, not --yes. The intrusive verbs (sample, jfr start) refuse exit 2 profiling_risk_not_accepted without --i-accept-the-risk — BEFORE any HTTP request. The global --yes/IGNITION_YES deliberately does NOT satisfy this gate: a blanket destructive-ops confirm must never silently cover active JVM instrumentation. (jfr status and jfr stop are ungated — checking and cleaning up must always be cheap to reach; stopping reduces risk and is never refused.)
  2. Hard caps, refused — never clamped. Sample duration ≤ 120 s (default 30), interval 5–1000 ms (default 20); JFR duration ≤ 300 s (default 60) with an auto-stop deadline baked into the recording itself; JFR dumps over 32 MiB are NOT streamed (the recording stops, the file stays on the gateway, and fetched:false + remote_file report it — retrieve and delete it manually). Over-cap asks exit 2 invalid_input BEFORE profile resolution (profile null): you must SEE the boundary, not have it silently moved.
  3. The warning rides everything. Every result — JSON envelope, compact, and human render — leads with the production warning (data.warning first field; a stderr banner in human mode so piping the report never swallows it).

The TUI surface​

The cockpit mirrors the mode as a gated room, not a tab: press J anywhere in ign tui and an interstitial makes you type ACKNOWLEDGE (Enter is inert until the phrase is exact) before the JVM screen opens. The screen carries a persistent red banner, a flight-recorder status pane, and the result of the last action; the keys are s (sample, fixed safe defaults 30 s @ 20 ms), w (live watch — continuous 10 s @ 50 ms windows refreshing the result pane; the status line shouts sampling LIVE while it runs and it stops on toggle, Esc, or a profile switch), f (JFR start, 60 s cap), F (JFR stop + fetch), r (refresh status), Esc (leave the mode). The TUI deliberately exposes NO way to raise durations or intervals — raising them is a CLI-side, still-capped decision. Switching profiles REVOKES the acknowledgment: a new gateway is a new risk decision.

Continuous mode (--follow, w)​

For a live, ongoing view instead of a bounded capture: the CLI's ign jvm sample --follow and the TUI's w watch run bounded sampling windows back-to-back — the per-window caps are unchanged, but the LOOP is open-ended and so is the gateway overhead. Defaults drop to the gentler 10 s @ 50 ms cadence (explicit --duration-secs/--interval-ms still apply, still capped). The CLI streams each window's rollup as it lands (NDJSON envelopes under --json/--compact, human reports otherwise) until Ctrl-C — the same "live, but only while you're watching" posture as logs -f; --folded-out is refused with --follow (a sidecar is one window's stacks). In the TUI the watch stops the moment you leave the mode or switch profiles: continuous instrumentation never outlives the surface showing it.