-
Couldn't load subscription status.
- Fork 18
Tweaks for datadog compatibility #74
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
base: main
Are you sure you want to change the base?
Changes from all commits
77a8653
285a963
5795cd4
75cf270
fbb81b5
aa0f960
785f7c1
0ece3ea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,7 +43,7 @@ function pprof(alloc_profile::Profile.Allocs.AllocResults = Profile.Allocs.fetch | |
| # Allocs-specific arguments: | ||
| frame_for_type::Bool = true, | ||
| ) | ||
| period = UInt64(0x1) | ||
| period = sum(alloc.size for alloc in alloc_profile.allocs, init=0) | ||
|
|
||
| @assert !isempty(basename(out)) "`out=` must specify a file path to write to. Got unexpected: '$out'" | ||
| if !endswith(out, ".pb.gz") | ||
|
|
@@ -72,10 +72,10 @@ function pprof(alloc_profile::Profile.Allocs.AllocResults = Profile.Allocs.fetch | |
| samples = Vector{Sample}() | ||
|
|
||
| sample_type = ValueType[ | ||
| ValueType!("allocs", "count"), # Mandatory | ||
| ValueType!("size", "bytes") | ||
| ValueType!("alloc_objects", "count"), # Mandatory | ||
| ValueType!("alloc_space", "bytes") | ||
| ] | ||
| period_type = ValueType!("heap", "bytes") | ||
| period_type = ValueType!("alloc_space", "bytes") | ||
|
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. oh maybe the period_type should actually be |
||
| drop_frames = isnothing(drop_frames) ? 0 : enter!(drop_frames) | ||
| keep_frames = isnothing(keep_frames) ? 0 : enter!(keep_frames) | ||
|
|
||
|
|
@@ -136,7 +136,7 @@ function pprof(alloc_profile::Profile.Allocs.AllocResults = Profile.Allocs.fetch | |
|
|
||
| push!( | ||
| locations, | ||
| Location(;id = loc_id, line=[Line(function_id, line_number)]) | ||
| Location(;id = loc_id, line=[Line(function_id, line_number > 0 ? line_number : 1)]) | ||
| ) | ||
|
|
||
| return loc_id | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -140,8 +140,8 @@ function pprof(data::Union{Nothing, Vector{UInt}} = nothing, | |
| samples = Vector{Sample}() | ||
|
|
||
| sample_type = [ | ||
| ValueType!("events", "count"), # Mandatory | ||
| ValueType!("stack_depth", "count") | ||
| ValueType!("events", "count"), # Mandatory | ||
| ValueType!("cpu", "nanoseconds") | ||
|
Comment on lines
-143
to
+144
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. can we still emit stack-depth values, or does even their presence break the datadog viewer? I'm fine to drop them though; i don't think they really added much, and they're just there because Valentin and i were trying to understand how the sample_types worked, i think 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. I'm not sure if they break the DD viewer… I'm not sure why you'd need them though, since each sample itself is a full stack, so the depth information is already there |
||
| ] | ||
|
|
||
| period_type = ValueType!("cpu", "nanoseconds") | ||
|
|
@@ -150,7 +150,7 @@ function pprof(data::Union{Nothing, Vector{UInt}} = nothing, | |
| # start decoding backtraces | ||
| location_id = Vector{eltype(data)}() | ||
| lastwaszero = true | ||
|
|
||
| for ip in data | ||
| # ip == 0x0 is the sentinel value for finishing a backtrace, therefore finising a sample | ||
| if ip == 0 | ||
|
|
@@ -163,7 +163,7 @@ function pprof(data::Union{Nothing, Vector{UInt}} = nothing, | |
| # End of sample | ||
| value = [ | ||
| 1, # events | ||
| length(location_id), # stack_depth | ||
| sampling_delay # CPU ns | ||
| ] | ||
| push!(samples, Sample(;location_id, value)) | ||
| location_id = Vector{eltype(data)}() | ||
|
|
@@ -200,7 +200,8 @@ function pprof(data::Union{Nothing, Vector{UInt}} = nothing, | |
|
|
||
| # Use a unique function id for the frame: | ||
| func_id = method_instance_id(frame) | ||
| push!(location.line, Line(function_id = func_id, line = frame.line)) | ||
| line_struct = Line(function_id = func_id, line = frame.line > 0 ? frame.line : 1) | ||
| push!(location.line, line_struct) | ||
|
|
||
| # Known function | ||
| func_id in seen_funcs && continue | ||
|
|
@@ -216,7 +217,9 @@ function pprof(data::Union{Nothing, Vector{UInt}} = nothing, | |
| file = string(meth.file) | ||
| io = IOBuffer() | ||
| Base.show_tuple_as_call(io, meth.name, linfo.specTypes) | ||
| full_name_with_args = _escape_name_for_pprof(String(take!(io))) | ||
| call_str = String(take!(io)) | ||
| # add module name as well | ||
| full_name_with_args = _escape_name_for_pprof("$(meth.module).$call_str") | ||
|
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. adding the module name here should be the only user-visible change in this PR — it's pretty essential to get frames to show up right in DD since it essentially does Without the module name it would parse as
If people don't want the behavior to change though, I could put this behind an option. |
||
| start_line = convert(Int64, meth.line) | ||
| else | ||
| # frame.linfo either nothing or CodeInfo, either way fallback | ||
|
|
||

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.
🤔 this seems weird.. Isn't this supposed to basically represent how much whatever does one sample represent?
So for a CPU profile, this would be like how much time in between samples? So for an allocation profile, it should be 1 allocation per sample, right?
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.
Hm yeah I was misunderstanding this.
Looking at the proto, it says "The number of events between sampled occurrences": https://github.com/google/pprof/blob/131d412537eacd9973045c73835c3ac6ed696765/proto/profile.proto#L85-L86
So I guess it's basically supposed to be the sample interval? E.g. "every 1000th alloc" would be 1000?