Skip to content

[PROF-15616] Add JFR support and java_cpu_jfr scenario - #156

Open
r1viollet wants to merge 6 commits into
mainfrom
r1viollet/jfr-support
Open

[PROF-15616] Add JFR support and java_cpu_jfr scenario#156
r1viollet wants to merge 6 commits into
mainfrom
r1viollet/jfr-support

Conversation

@r1viollet

@r1viollet r1viollet commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

What

Add Java Flight Recorder (JFR) support to the analyzer as a first-class input format via the neutral ProfileSet model.

The analyzer now follows the same shape for all supported profile formats:

  • pprof -> FromPprof -> ProfileSet
  • OTLP -> FromOTLP -> ProfileSet
  • JFR -> FromJFR -> ProfileSet

The 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.ExecutionSample
  • datadog.ExecutionSample

How

  • Add analysis/jfr.go with direct JFR-to-ProfileSet parsing.
  • Dispatch .jfr files through LoadProfileSet alongside pprof and OTLP.
  • Stop pre-converting .jfr files to generated *_cpu.pprof files in AnalyzeResults.
  • Use a jfr-parser fork exposing raw JFR events and decoded raw fields so prof-correctness owns producer-specific semantic mapping without carrying JFR wire-decoding code.
  • Keep unsupported JFR event types ignored for now instead of forcing them through a pprof conversion layer.
  • Preserve JFR CPU duration from chunk headers for duration-scaled assertions.
  • Preserve Datadog localRootSpanId as the neutral local root span id label.

Scenario

Add scenarios/java_cpu_jfr, which runs the Datadog Java profiler through dd-java-agent and captures a local JFR through the tracer's built-in debug dump path.

The scenario:

  • installs dd-java-agent.jar
  • enables Datadog profiling / ddprof
  • runs a recursive Fibonacci workload
  • sets dd.profiling.debug.dump_path=/app/data/dumps
  • matches the generated dd-profiler-debug-*.jfr file by regex
  • asserts CPU samples contain DummyApp.fibonacci

This intentionally validates Datadog profiler JFR output, not HotSpot's built-in -XX:StartFlightRecording output.

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-analyze
GOPRIVATE=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=1

Both pass locally.

Notes

This currently depends on a temporary parser fork:

replace github.com/grafana/jfr-parser => github.com/r1viollet/pyroscope-jfr-parser v0.0.0-20260803080954-eddc025c5c4e

Parser fork PR for review/upstreaming:

Before merging, this should move to a Datadog fork or an upstream jfr-parser change exposing raw events/fields.

@r1viollet

Copy link
Copy Markdown
Collaborator Author

@jbachorik do you prefer converting in the framework ? Or in the test scenario ?
This is in the framework

@jbachorik

Copy link
Copy Markdown

@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.
Who would be on the hook to fix the go jfr parser if we encounter any issues? Perhaps it is less of a concerns with agentic coding tools but still we should have someone making sure we don't make correctness tests incorrect or failing...

@r1viollet

Copy link
Copy Markdown
Collaborator Author

... someone making sure we don't make correctness tests incorrect or failing...

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.
I would expect java folks to still enrich the tests and investigate failures.

@r1viollet

Copy link
Copy Markdown
Collaborator Author

Let's push for this, if things break, we'll just remove them

@r1viollet
r1viollet marked this pull request as ready for review July 17, 2026 12:01
@r1viollet
r1viollet requested a review from a team as a code owner July 17, 2026 12:01
Comment thread analysis/jfr.go Outdated
@r1viollet
r1viollet force-pushed the r1viollet/jfr-support branch 2 times, most recently from 94f3446 to 738696f Compare July 28, 2026 09:37
Comment thread scenarios/java_cpu_jfr/Dockerfile Outdated
@r1viollet
r1viollet force-pushed the r1viollet/jfr-support branch from 738696f to 42fd00f Compare July 28, 2026 10:59
@r1viollet
r1viollet changed the base branch from main to r1viollet/analysis-otlp-native July 28, 2026 11:00
@r1viollet
r1viollet marked this pull request as draft July 28, 2026 14:30
Base automatically changed from r1viollet/analysis-otlp-native to main August 3, 2026 07:26
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).
@r1viollet
r1viollet force-pushed the r1viollet/jfr-support branch 3 times, most recently from d88eeac to cf77dde Compare August 3, 2026 08:01
@r1viollet

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread analysis/jfr.go
Comment thread analysis/jfr.go Outdated
@r1viollet
r1viollet force-pushed the r1viollet/jfr-support branch from cf77dde to 96c4983 Compare August 3, 2026 08:16
Comment thread go.sum
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=

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for now, upstream jfr parser handles a subset of events

@r1viollet r1viollet changed the title [PROF-XXXX] Add JFR support and java_cpu_jfr scenario [PROF-15616] Add JFR support and java_cpu_jfr scenario Aug 3, 2026
@r1viollet
r1viollet marked this pull request as ready for review August 3, 2026 08:49
@r1viollet

Copy link
Copy Markdown
Collaborator Author

@jbachorik this is starting to make sense

Comment thread analysis/jfr.go
}

switch event.Type.Name {
case "jdk.ExecutionSample", "datadog.ExecutionSample":

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not handle everything here, this is mainly to have an example

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.

2 participants