[PROF-15616] Add JFR support and java_cpu_jfr scenario - #156
Conversation
|
@jbachorik do you prefer converting in the framework ? Or in the test scenario ? |
|
@r1viollet If we are ok with maintaining the go parser of JFR and are sure it won't hamper the correctness check, in-framework is a better fit. |
I agree that there is a question of ownership. I'm fine helping with the design of prof-correctness, but I won't be checking results. It has been quite low overhead to maintain the framework while we don't make big evolutions to the format. |
|
Let's push for this, if things break, we'll just remove them |
94f3446 to
738696f
Compare
738696f to
42fd00f
Compare
Add the ability to parse Java Flight Recorder (.jfr) files as part of the correctness analysis pipeline. analysis/jfr.go: - parseJFR(): converts raw JFR bytes to a map of metric name → *profile.Profile, using github.com/grafana/jfr-parser/parser directly (no pyroscope/api dependency). - convertJFRFiles(): called at the start of AnalyzeResults; walks the output directory for *.jfr files and writes per-metric pprof files (e.g. profile.jfr → profile_cpu.pprof, profile_lock.pprof, …). Existing pprof analysis code then picks these up via the normal filename-regex matching. Supported JFR event types: jdk.ExecutionSample (cpu/wall), jdk.ObjectAllocationInNewTLAB, jdk.ObjectAllocationOutsideTLAB, jdk.JavaMonitorEnter, and the Datadog WallClockSample extension. scenarios/java_cpu_jfr: - Simple Fibonacci CPU burner recorded with built-in JDK JFR (eclipse-temurin:21-jdk, settings=profile, dumponexit=true). - Asserts ≥80% of CPU samples contain DummyApp.fibonacci. - EXECUTION_TIME_SEC env var honoured (default 30 s).
d88eeac to
cf77dde
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cf77dde98d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
cf77dde to
96c4983
Compare
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
| github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= | ||
| github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
| github.com/r1viollet/pyroscope-jfr-parser v0.0.0-20260803080954-eddc025c5c4e h1:qOsPPgSArMHlR10zugkK6l5pCZp+8fK99pIcwxpYJ7M= |
There was a problem hiding this comment.
for now, upstream jfr parser handles a subset of events
|
@jbachorik this is starting to make sense |
| } | ||
|
|
||
| switch event.Type.Name { | ||
| case "jdk.ExecutionSample", "datadog.ExecutionSample": |
There was a problem hiding this comment.
I did not handle everything here, this is mainly to have an example
What
Add Java Flight Recorder (JFR) support to the analyzer as a first-class input format via the neutral
ProfileSetmodel.The analyzer now follows the same shape for all supported profile formats:
pprof->FromPprof->ProfileSetOTLP->FromOTLP->ProfileSetJFR->FromJFR->ProfileSetThe JFR path no longer converts recordings to synthetic pprof files. It reads raw JFR events and maps supported event types directly to semantic profile samples.
Currently supported JFR CPU events:
jdk.ExecutionSampledatadog.ExecutionSampleHow
analysis/jfr.gowith direct JFR-to-ProfileSetparsing..jfrfiles throughLoadProfileSetalongside pprof and OTLP..jfrfiles to generated*_cpu.pproffiles inAnalyzeResults.jfr-parserfork exposing raw JFR events and decoded raw fields so prof-correctness owns producer-specific semantic mapping without carrying JFR wire-decoding code.localRootSpanIdas the neutrallocal root span idlabel.Scenario
Add
scenarios/java_cpu_jfr, which runs the Datadog Java profiler throughdd-java-agentand captures a local JFR through the tracer's built-in debug dump path.The scenario:
dd-java-agent.jardd.profiling.debug.dump_path=/app/data/dumpsdd-profiler-debug-*.jfrfile by regexDummyApp.fibonacciThis intentionally validates Datadog profiler JFR output, not HotSpot's built-in
-XX:StartFlightRecordingoutput.The profile-upload/intake path is not modeled in this PR. A fake Datadog profile intake would be useful as shared test-harness infrastructure, but should be implemented generically in Go and reused across languages rather than embedded in this Java JFR scenario.
Testing
GOPRIVATE=github.com/r1viollet/pyroscope-jfr-parser \ GONOSUMDB=github.com/r1viollet/pyroscope-jfr-parser \ GOPROXY=direct \ go test ./analysis ./cmd/prof-analyzeGOPRIVATE=github.com/r1viollet/pyroscope-jfr-parser \ GONOSUMDB=github.com/r1viollet/pyroscope-jfr-parser \ GOPROXY=direct \ TEST_SCENARIOS=java_cpu_jfr TEST_RUN_SECS=40 \ go test -run TestScenarios -count=1Both pass locally.
Notes
This currently depends on a temporary parser fork:
Parser fork PR for review/upstreaming:
Before merging, this should move to a Datadog fork or an upstream
jfr-parserchange exposing raw events/fields.