Continuous Java Flight Recorder (JFR)
Continuous JFR runbook for Pinot with dynamic cluster-level on/off control
This page is the runbook for running continuous Java Flight Recorder (JFR) in Pinot.
Pinot supports cluster-level runtime control through ContinuousJfrStarter, so operators can turn recording on/off or adjust settings without restarting Pinot processes.
What is Java Flight Recorder (JFR)?
Java Flight Recorder (JFR) is a profiling and diagnostics framework built into the JDK. It records events from the JVM and application (for example CPU, memory, allocation, GC, thread, and lock events) into .jfr files with low production overhead.
In Java 8, JFR was a commercial feature and older documentation may mention -XX:+UnlockCommercialFeatures -XX:+FlightRecorder. Since Java 11, JFR is part of OpenJDK and does not require commercial flags.
Official deployment model
Run one long-lived recording in each Pinot JVM process (Controller, Broker, Server, Minion) and control it with pinot.jfr.* cluster config.
Configure with cluster config
pinot.jfr.enabled
false
Enables/disables continuous recording.
pinot.jfr.configuration
default
JFR settings profile (default, profile, or custom JFR config).
pinot.jfr.name
pinot-continuous
Recording name.
pinot.jfr.dumpOnExit
false
Dumps recording on JVM exit. Set to true for on-exit dumps; note that this may trigger repository cleanup even if preserveRepository=true.
pinot.jfr.toDisk
true
Stores recording repository on disk.
pinot.jfr.maxSize
2GB
Max recording size when toDisk=true; supports human-readable values (for example 512MB, 2GB) or raw bytes.
pinot.jfr.maxAge
P7D
Max event age (ISO-8601 duration) when toDisk=true.
pinot.jfr.directory
system temp directory
JFR repository directory path. Applied via the DiagnosticCommand MBean as repositorypath.
pinot.jfr.dumpPath
unset
Default JFR dump directory path. Applied via the DiagnosticCommand MBean as dumppath.
pinot.jfr.preserveRepository
true
Preserves the JFR repository directory after JVM exit. By default, JFR deletes the repository on exit; set this to prevent that (useful for post-mortem analysis). Applied via the DiagnosticCommand MBean as preserve-repository.
pinot.jfr.repositoryMaxTotalSize
20GB
Maximum total size for all repositories under the configured repository directory. When exceeded, older repositories are removed first. The currently active repository is always retained.
Example:
Notes:
configuration=defaultis low-overhead and production-safe.Use
configuration=profileonly during active investigations.maxAgeandmaxSizecap footprint and history.Configuration changes are applied dynamically; Pinot restarts the active recording in-process.
preserveRepositoryis useful for post-mortem analysis of in-flight chunks when the repository directory is shared across processes.repositoryMaxTotalSizeautomatically removes older repositories to maintain total size, but the active repository is always kept.
Behavior of ContinuousJfrStarter
Starts/stops one recording per Pinot JVM based on
pinot.jfr.enabled.Reacts to
pinot.jfr.*config updates at runtime.Manages JFR repository and dump paths via the DiagnosticCommand MBean (
JFR.configure repositorypath=...andJFR.configure dumppath=...).Manages recording lifecycle via the DiagnosticCommand MBean (
JFR.startandJFR.stop).If the DiagnosticCommand MBean is unavailable, Pinot logs a warning and skips JFR operations instead of failing startup.
Automatically manages repository cleanup by removing older repositories when total size exceeds
repositoryMaxTotalSize, while preserving the active repository.Uses standard JFR lifecycle controls (same model as JVM-native JFR), with Pinot cluster config as the control plane.
Operational checks
List JVMs:
Inspect recordings:
Incident workflow
Capture a point-in-time dump without restarting the process:
Take additional dumps as needed during the incident timeline.
Alternative startup via JVM options
If you prefer static startup-only configuration, you can configure JFR in JAVA_OPTS:
Use this only when dynamic cluster-level toggling is not required.
Handling large recordings
When a recording is too large to transfer or inspect as one file, split it:
Share only relevant chunks for triage.
Retention and tuning
Start with
configuration=default.Increase
maxAgefor longer timeline retention.Increase
maxSizefor high event-volume workloads.Configure
repositoryMaxTotalSizeandpreserveRepositoryto manage disk usage and support post-mortem analysis.Keep host-level cleanup policies for operator-created dump files.
Use explicit timestamped names for ad hoc dump files.
Common pitfalls
Assuming Pinot automatically rotates JFR dump files.
Running without disk budget guardrails (
maxAgeandmaxSize).Leaving
configuration=profileenabled permanently.Not configuring
dumpPathwhen frequent dumps are needed (requires manual directory management).
Minimal operator checklist
Related
Monitoring — Metrics, Prometheus, and Grafana.
Configuration Reference / Monitoring Metrics — Pinot metrics reference.
Opening and analyzing JFR files
jfr summary <file.jfr>for high-level stats.jfr view <file.jfr>for aggregated views.jfr print <file.jfr>for detailed events (--jsonand--xmlsupported).Java Mission Control (JMC) for interactive analysis.
jdk.jfr.consumer.RecordingFilefor programmatic analysis.
Quick sanity check:
External references
Package jdk.jfr (Java SE 21) — Overview of the JFR API: defining events, controlling Flight Recorder, and the
jdk.jfrpackage.The
jfrcommand — Command-line tool to view, print, and summarize.jfrfiles (JDK 21+).Using JDK Flight Recorder with Java Mission Control — Recording and inspecting flights with the JMC GUI; includes an overview of JFR and how to analyze recordings.
JDK Mission Control (JMC) — Download — Standalone JMC build for opening and analyzing
.jfrrecordings.RecordingFile (jdk.jfr.consumer) — API for reading and parsing
.jfrfiles programmatically.
Last updated
Was this helpful?

