-
Notifications
You must be signed in to change notification settings - Fork 2
[PROF-15616] Add JFR support and java_cpu_jfr scenario #156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
r1viollet
wants to merge
6
commits into
main
Choose a base branch
from
r1viollet/jfr-support
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
900ef71
Add JFR support and java_cpu_jfr scenario
r1viollet 9bd5b68
ci: add java job for JFR scenarios
r1viollet 1e07eb3
Generalize JFR pprof conversion
r1viollet 8a8ba18
Use JFR parser fork with Datadog event aliases
r1viollet d8e9594
Parse JFR directly into profile model
r1viollet 96c4983
Run Java JFR scenario with Datadog profiler
r1viollet File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| // Package analysis — JFR support. | ||
| // | ||
| // This file adds the ability to read JFR (Java Flight Recorder) files and map | ||
| // JFR events directly into the analyzer's neutral ProfileSet. The mapping from | ||
| // event names to profile semantics intentionally lives here: prof-correctness is | ||
| // the consumer that knows which JDK / Datadog profiler events should satisfy a | ||
| // given expected_profile.json assertion. | ||
| package analysis | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "io" | ||
| "strings" | ||
|
|
||
| "github.com/grafana/jfr-parser/parser" | ||
| "github.com/grafana/jfr-parser/parser/types" | ||
| ) | ||
|
|
||
| // FromJFR builds a ProfileSet directly from Java Flight Recorder events. | ||
| func FromJFR(data []byte) (*ProfileSet, error) { | ||
| p := parser.NewParser(data, parser.Options{ | ||
| SymbolProcessor: parser.ProcessSymbols, | ||
| }) | ||
| ps := newProfileSet() | ||
|
|
||
| var cpuTotal int64 | ||
| var durationNanos uint64 | ||
| seenChunks := map[jfrChunkKey]bool{} | ||
|
|
||
| for { | ||
| event, err := p.ParseRawEvent() | ||
| if err == io.EOF { | ||
| break | ||
| } | ||
| if err != nil { | ||
| return nil, fmt.Errorf("jfr ParseRawEvent: %w", err) | ||
| } | ||
| if event.Type == nil { | ||
| continue | ||
| } | ||
|
|
||
| header := p.ChunkHeader() | ||
| chunk := jfrChunkKey{startNanos: header.StartNanos, durationNanos: header.DurationNanos} | ||
| if !seenChunks[chunk] { | ||
| seenChunks[chunk] = true | ||
| durationNanos += header.DurationNanos | ||
| } | ||
|
|
||
| switch event.Type.Name { | ||
| case "jdk.ExecutionSample", "datadog.ExecutionSample": | ||
| fields, err := p.DecodeRawEventFields(event) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("jfr decode %s: %w", event.Type.Name, err) | ||
| } | ||
| cpuTotal += addJFRCPU(ps, p, fields) | ||
| } | ||
| } | ||
|
|
||
| if cpuTotal > 0 && durationNanos > 0 { | ||
| ps.addProfileDuration("cpu", cpuTotal, float64(durationNanos)/1e9) | ||
| } | ||
|
|
||
| return ps.finalize(), nil | ||
|
r1viollet marked this conversation as resolved.
|
||
| } | ||
|
|
||
| type jfrChunkKey struct { | ||
| startNanos uint64 | ||
| durationNanos uint64 | ||
| } | ||
|
|
||
| func addJFRCPU(ps *ProfileSet, p *parser.Parser, fields map[string]parser.RawField) int64 { | ||
| stackField, ok := jfrField(fields, "stackTrace") | ||
| if !ok { | ||
| return 0 | ||
| } | ||
|
|
||
| // Match jfr-parser/pprof's CPU semantics: execution samples from sleeping | ||
| // threads do not count as CPU samples. If the state is absent, keep the | ||
| // sample rather than silently dropping producer-specific events. | ||
| if state, ok := jfrField(fields, "state"); ok { | ||
| if ts := p.GetThreadState(types.ThreadStateRef(state.Uint64)); ts != nil && ts.Name == "STATE_SLEEPING" { | ||
| return 0 | ||
| } | ||
| } | ||
|
|
||
| folded := foldJFRStack(p, types.StackTraceRef(stackField.Uint64)) | ||
| if folded == "" { | ||
| return 0 | ||
| } | ||
|
|
||
| val := int64(1) | ||
| if weight, ok := jfrField(fields, "weight"); ok && weight.Uint64 > 0 { | ||
| val = int64(weight.Uint64) | ||
| } | ||
|
|
||
| ps.add("cpu", StackSample{Stack: folded, Val: val, Labels: executionSampleLabels(fields)}) | ||
| return val | ||
| } | ||
|
|
||
| func executionSampleLabels(fields map[string]parser.RawField) map[string][]string { | ||
| labels := map[string][]string{} | ||
| if spanID, ok := jfrField(fields, "spanId"); ok && spanID.Uint64 != 0 { | ||
| labels[LabelSpanID] = []string{fmt.Sprintf("%d", spanID.Uint64)} | ||
| } | ||
| if localRootSpanID, ok := jfrField(fields, "localRootSpanId"); ok && localRootSpanID.Uint64 != 0 { | ||
| labels[LabelLocalRootSID] = []string{fmt.Sprintf("%d", localRootSpanID.Uint64)} | ||
| } | ||
| traceHi, traceHiOK := jfrField(fields, "traceIdHi") | ||
| traceLo, traceLoOK := jfrField(fields, "traceIdLo") | ||
| if (traceHiOK || traceLoOK) && (traceHi.Uint64 != 0 || traceLo.Uint64 != 0) { | ||
| labels[LabelTraceID] = []string{fmt.Sprintf("%016x%016x", traceHi.Uint64, traceLo.Uint64)} | ||
| } | ||
| return labels | ||
| } | ||
|
|
||
| func jfrField(fields map[string]parser.RawField, name string) (parser.RawValue, bool) { | ||
| field, ok := fields[name] | ||
| if !ok { | ||
| return parser.RawValue{}, false | ||
| } | ||
| return field.First() | ||
| } | ||
|
|
||
| func foldJFRStack(p *parser.Parser, stackRef types.StackTraceRef) string { | ||
| st := p.GetStacktrace(stackRef) | ||
| if st == nil || len(st.Frames) == 0 { | ||
| return "" | ||
| } | ||
| // JFR frames are leaf-first. The analyzer uses root-first folded stacks, | ||
| // matching FromPprof and the historical expected_profile.json captures. | ||
| frames := make([]string, 0, len(st.Frames)) | ||
| for i := len(st.Frames) - 1; i >= 0; i-- { | ||
| name := jfrFrameName(p, st.Frames[i].Method) | ||
| if name != "" { | ||
| frames = append(frames, name) | ||
| } | ||
| } | ||
| return strings.Join(frames, ";") | ||
| } | ||
|
|
||
| func jfrFrameName(p *parser.Parser, methodRef types.MethodRef) string { | ||
| m := p.GetMethod(methodRef) | ||
| if m == nil { | ||
| return "" | ||
| } | ||
| methodName := p.GetSymbolString(m.Name) | ||
| cls := p.GetClass(m.Type) | ||
| if cls == nil { | ||
| return methodName | ||
| } | ||
| clsName := strings.ReplaceAll(p.GetSymbolString(cls.Name), "/", ".") | ||
| return clsName + "." + methodName | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,22 @@ | ||
| github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||
| github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= | ||
| github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | ||
| github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
| github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= | ||
| github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
| github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= | ||
| github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= | ||
| github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= | ||
| github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= | ||
| github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= | ||
| github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= | ||
| github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= | ||
| github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= | ||
| github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | ||
| github.com/google/pprof v0.0.0-20240528025155-186aa0362fba h1:ql1qNgCyOB7iAEk8JTNM+zJrgIbnyCKX/wdlyPufP5g= | ||
| github.com/google/pprof v0.0.0-20240528025155-186aa0362fba/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= | ||
| github.com/google/pprof v0.0.0-20260507013755-92041b743c96 h1:YDDnaZ9afWajDboPMt9Vikqca/yWAX7KAxVzb4lJU1M= | ||
| github.com/google/pprof v0.0.0-20260507013755-92041b743c96/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= | ||
| github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= | ||
| github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||
| github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA= | ||
| github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= | ||
| github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= | ||
|
|
@@ -18,34 +31,64 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd | |
| github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= | ||
| github.com/pierrec/lz4/v4 v4.1.25 h1:kocOqRffaIbU5djlIBr7Wh+cx82C0vtFb0fOurZHqD0= | ||
| github.com/pierrec/lz4/v4 v4.1.25/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4= | ||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
| 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= | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for now, upstream jfr parser handles a subset of events |
||
| github.com/r1viollet/pyroscope-jfr-parser v0.0.0-20260803080954-eddc025c5c4e/go.mod h1:jNzwTrMNDUt6p/HcWjjtkTuZEfxUqr/gn/8hw0LaBJY= | ||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
| github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= | ||
| github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||
| github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= | ||
| github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= | ||
| github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= | ||
| github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= | ||
| github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= | ||
| github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= | ||
| github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= | ||
| github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= | ||
| go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= | ||
| go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= | ||
| go.opentelemetry.io/collector/featuregate v1.62.0 h1:pYY7RlulSCTOS9mFWxasMLwYJCfNXHtnOkZlv3jg/V4= | ||
| go.opentelemetry.io/collector/featuregate v1.62.0/go.mod h1:4ga1QBMPEejXXmpyJS8lmaRpknJ3Lb9Bvk6e420bUFU= | ||
| go.opentelemetry.io/collector/internal/testutil v0.156.0 h1:Nu02vhHA2UQ3Yjyjisk3N24HHxwvw7PQiTz9O1PuiUY= | ||
| go.opentelemetry.io/collector/internal/testutil v0.156.0/go.mod h1:Jkjs6rkqs973LqgZ0Fe3zrokQRKULYXPIf4HuqStiEE= | ||
| go.opentelemetry.io/collector/pdata v1.62.0 h1:xGdwl2Cs5Rq5nKs0nYvAxm3Qq20HcySVAmUElATS8Es= | ||
| go.opentelemetry.io/collector/pdata v1.62.0/go.mod h1:WFy5R6XGpz2Q4MaekeEm+qc4GY5V3+BhQIwGPkp+fj0= | ||
| go.opentelemetry.io/collector/pdata/pprofile v0.156.0 h1:TnQzA2d5iMGH5//mGLqPjwdYqsFD/A7o2WgDdppxdVM= | ||
| go.opentelemetry.io/collector/pdata/pprofile v0.156.0/go.mod h1:3dtjs/mliblJJCCTXUE0AkpBNfBEybPruj3ml6WCOoI= | ||
| go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= | ||
| go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= | ||
| go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= | ||
| go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= | ||
| go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= | ||
| go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= | ||
| go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= | ||
| go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= | ||
| go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= | ||
| go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= | ||
| go.opentelemetry.io/proto/slim/otlp v1.10.0 h1:iR97Vs/ZDR+y9TfuP9b1XBtdPWeC+OMslIBmhcLU7jM= | ||
| go.opentelemetry.io/proto/slim/otlp v1.10.0/go.mod h1:lV9250stpjYLPNA5viFabIgP2QlUGRT1GdTgAf8SIUk= | ||
| go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.3.0 h1:RUF5rO0hAlgiJt1fzQVzcVs3vZVNHIcMLgOgG4rWNcQ= | ||
| go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.3.0/go.mod h1:I89cynRj8y+383o7tEQVg2SVA6SRgDVIouWPUVXjx0U= | ||
| go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.3.0 h1:CQvJSldHRUN6Z8jsUeYv8J0lXRvygALXIzsmAeCcZE0= | ||
| go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.3.0/go.mod h1:xSQ+mEfJe/GjK1LXEyVOoSI1N9JV9ZI923X5kup43W4= | ||
| go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= | ||
| go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= | ||
| go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= | ||
| go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= | ||
| golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= | ||
| golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= | ||
| golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= | ||
| golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= | ||
| golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= | ||
| golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= | ||
| golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus= | ||
| golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM= | ||
| gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= | ||
| gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= | ||
| google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw= | ||
| google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= | ||
| google.golang.org/grpc v1.82.0 h1:vguDnZUPjE26w09A63VoxZPnvPjB5Riyc0mkXPFmAIU= | ||
| google.golang.org/grpc v1.82.0/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA= | ||
| google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= | ||
| google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= | ||
| gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
| gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| FROM eclipse-temurin:21-jdk | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| RUN apt-get update \ | ||
| && apt-get install -y --no-install-recommends curl ca-certificates \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| # Install the Datadog Java tracer, which carries the Datadog native Java | ||
| # profiler (ddprof). The profiler writes Datadog-specific JFR events such as | ||
| # datadog.ExecutionSample; this scenario validates that prof-correctness can | ||
| # consume those recordings directly. | ||
| RUN curl -fsSL -o /app/dd-java-agent.jar https://dtdg.co/latest-java-tracer | ||
|
|
||
| COPY ./scenarios/java_cpu_jfr/DummyApp.java . | ||
| RUN javac DummyApp.java | ||
|
|
||
| # EXECUTION_TIME_SEC is injected by the test harness; default to 60 s. | ||
| ENV EXECUTION_TIME_SEC=60 | ||
|
|
||
| # Run the app under the Datadog Java profiler and use the tracer's built-in | ||
| # debug dump path to persist the JFR snapshot locally. The prof-correctness | ||
| # harness finds the timestamped dd-profiler-debug-*.jfr file by regex. | ||
| CMD sh -eu -c '\ | ||
| mkdir -p /app/data/dumps /app/data/tmp; \ | ||
| java \ | ||
| -javaagent:/app/dd-java-agent.jar \ | ||
| -Ddd.service=prof-correctness-java-cpu-jfr \ | ||
| -Ddd.env=local \ | ||
| -Ddd.trace.enabled=false \ | ||
| -Ddd.profiling.enabled=true \ | ||
| -Ddd.profiling.ddprof.enabled=true \ | ||
| -Ddd.profiling.ddprof.cpu.enabled=true \ | ||
| -Ddd.profiling.ddprof.wall.enabled=false \ | ||
| -Ddd.profiling.upload.period=30 \ | ||
| -Ddd.profiling.upload.timeout=1 \ | ||
| -Ddd.profiling.start-force-first=true \ | ||
| -Ddd.profiling.tempdir=/app/data/tmp \ | ||
| -Ddd.profiling.debug.dump_path=/app/data/dumps \ | ||
| -Ddd.profiling.url=http://127.0.0.1:8126/ \ | ||
| -Ddd.telemetry.enabled=false \ | ||
| -Ddd.jmxfetch.enabled=false \ | ||
| DummyApp \ | ||
| ' |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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