From 93ada31ba7122955b32a953faac76083ce454407 Mon Sep 17 00:00:00 2001 From: d-netto Date: Thu, 6 Jun 2024 10:29:28 -0300 Subject: [PATCH 1/2] use different filenames in profiles to avoid overwritting previous profiles --- src/ProfileEndpoints.jl | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/ProfileEndpoints.jl b/src/ProfileEndpoints.jl index da3a4bc..81a37b0 100644 --- a/src/ProfileEndpoints.jl +++ b/src/ProfileEndpoints.jl @@ -22,10 +22,9 @@ using Serialization: serialize # #---------------------------------------------------------- -function _http_create_response_with_profile_inlined(binary_data, filename) +function _http_create_response_with_profile_inlined(binary_data) return HTTP.Response(200, [ "Content-Type" => "application/octet-stream" - "Content-Disposition" => "attachment; filename=$(repr(filename))" ], body = binary_data) end @@ -108,12 +107,13 @@ function _do_cpu_profile(n, delay, duration, with_pprof, stage_path = nothing) Profile.clear() Profile.init(n, delay) Profile.@profile sleep(duration) - path = "cpu_profile-duration=$duration&delay=$delay&n=$n" + local path if stage_path === nothing + path = tempname() # Defer the potentially expensive profile symbolication to a non-interactive thread - return fetch(Threads.@spawn _cpu_profile_get_response($path; with_pprof=$with_pprof)) + return fetch(Threads.@spawn _cpu_profile_get_response(with_pprof=$with_pprof)) end - path = joinpath(stage_path, path) + path = tempname(stage_path) # Defer the potentially expensive profile symbolication to a non-interactive thread return fetch(Threads.@spawn _cpu_profile_get_response_and_write_to_file($path; with_pprof=$with_pprof)) end @@ -133,12 +133,13 @@ function _start_cpu_profile(n, delay) end function handle_cpu_profile_stop(with_pprof, stage_path = nothing) - path = "cpu_profile" + local path if stage_path === nothing + path = tempname() # Defer the potentially expensive profile symbolication to a non-interactive thread - return fetch(Threads.@spawn _cpu_profile_get_response($path; with_pprof=$with_pprof)) + return fetch(Threads.@spawn _cpu_profile_get_response(with_pprof=$with_pprof)) end - path = joinpath(stage_path, "cpu_profile") + path = tempname(stage_path) # Defer the potentially expensive profile symbolication to a non-interactive thread return fetch(Threads.@spawn _cpu_profile_get_response_and_write_to_file($path; with_pprof=$with_pprof)) end @@ -160,17 +161,17 @@ function _cpu_profile_get_response_and_write_to_file(filename; with_pprof::Bool) end end -function _cpu_profile_get_response(filename; with_pprof::Bool) +function _cpu_profile_get_response(;with_pprof::Bool) if with_pprof prof_name = tempname() PProf.pprof(out=prof_name, web=false) prof_name = "$prof_name.pb.gz" - return _http_create_response_with_profile_inlined(read(prof_name), "$filename.pb.gz") + return _http_create_response_with_profile_inlined(read(prof_name)) else iobuf = IOBuffer() data = Profile.retrieve() serialize(iobuf, data) - return _http_create_response_with_profile_inlined(iobuf.data, "$filename.profile") + return _http_create_response_with_profile_inlined(iobuf.data) end end @@ -197,7 +198,7 @@ function heap_snapshot_endpoint(req::HTTP.Request) file_path = joinpath(tempdir(), "$(getpid())_$(time_ns()).heapsnapshot") file_path = Profile.take_heap_snapshot(file_path, all_one) @info "Taking heap snapshot from ProfileEndpoints" all_one file_path - return _http_create_response_with_profile_inlined(read(file_path), file_path) + return _http_create_response_with_profile_inlined(read(file_path)) end end # if isdefined @@ -267,8 +268,7 @@ function _do_alloc_profile(duration, sample_rate) prof_name = tempname() PProf.Allocs.pprof(out=prof_name, web=false) prof_name = "$prof_name.pb.gz" - return _http_create_response_with_profile_inlined(read(prof_name), - "allocs_profile-duration=$duration&sample_rate=$sample_rate.pb.gz") + return _http_create_response_with_profile_inlined(read(prof_name)) end function _start_alloc_profile(sample_rate) @@ -284,7 +284,7 @@ function _stop_alloc_profile() prof_name = tempname() PProf.Allocs.pprof(out=prof_name, web=false) prof_name = "$prof_name.pb.gz" - return _http_create_response_with_profile_inlined(read(prof_name), "allocs_profile.pb.gz") + return _http_create_response_with_profile_inlined(read(prof_name)) end end # if isdefined @@ -305,10 +305,12 @@ function handle_task_backtraces(stage_path = nothing) @static if VERSION < v"1.10.0-DEV.0" return HTTP.Response(501, "Task backtraces are only available in Julia 1.10+") end + local backtrace_file if stage_path === nothing - stage_path = tempdir() + backtrace_file = tempname() + else + backtrace_file = tempname(stage_path) end - backtrace_file = joinpath(stage_path, "task_backtraces.txt") open(backtrace_file, "w") do io redirect_stderr(io) do ccall(:jl_print_task_backtraces, Cvoid, ()) From 8f7a6efbe425b585f74bdc9e0b769b3288e107d9 Mon Sep 17 00:00:00 2001 From: d-netto Date: Fri, 7 Jun 2024 11:15:25 -0300 Subject: [PATCH 2/2] suggestions from review --- src/ProfileEndpoints.jl | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/ProfileEndpoints.jl b/src/ProfileEndpoints.jl index 81a37b0..fe0462e 100644 --- a/src/ProfileEndpoints.jl +++ b/src/ProfileEndpoints.jl @@ -107,13 +107,11 @@ function _do_cpu_profile(n, delay, duration, with_pprof, stage_path = nothing) Profile.clear() Profile.init(n, delay) Profile.@profile sleep(duration) - local path if stage_path === nothing - path = tempname() # Defer the potentially expensive profile symbolication to a non-interactive thread return fetch(Threads.@spawn _cpu_profile_get_response(with_pprof=$with_pprof)) end - path = tempname(stage_path) + path = tempname(stage_path; cleanup=false) # Defer the potentially expensive profile symbolication to a non-interactive thread return fetch(Threads.@spawn _cpu_profile_get_response_and_write_to_file($path; with_pprof=$with_pprof)) end @@ -133,13 +131,11 @@ function _start_cpu_profile(n, delay) end function handle_cpu_profile_stop(with_pprof, stage_path = nothing) - local path if stage_path === nothing - path = tempname() # Defer the potentially expensive profile symbolication to a non-interactive thread return fetch(Threads.@spawn _cpu_profile_get_response(with_pprof=$with_pprof)) end - path = tempname(stage_path) + path = tempname(stage_path; cleanup=false) # Defer the potentially expensive profile symbolication to a non-interactive thread return fetch(Threads.@spawn _cpu_profile_get_response_and_write_to_file($path; with_pprof=$with_pprof)) end @@ -163,7 +159,7 @@ end function _cpu_profile_get_response(;with_pprof::Bool) if with_pprof - prof_name = tempname() + prof_name = tempname(;cleanup=false) PProf.pprof(out=prof_name, web=false) prof_name = "$prof_name.pb.gz" return _http_create_response_with_profile_inlined(read(prof_name)) @@ -265,7 +261,7 @@ function _do_alloc_profile(duration, sample_rate) Profile.Allocs.@profile sample_rate=sample_rate sleep(duration) - prof_name = tempname() + prof_name = tempname(;cleanup=false) PProf.Allocs.pprof(out=prof_name, web=false) prof_name = "$prof_name.pb.gz" return _http_create_response_with_profile_inlined(read(prof_name)) @@ -281,7 +277,7 @@ end function _stop_alloc_profile() Profile.Allocs.stop() - prof_name = tempname() + prof_name = tempname(;cleanup=false) PProf.Allocs.pprof(out=prof_name, web=false) prof_name = "$prof_name.pb.gz" return _http_create_response_with_profile_inlined(read(prof_name)) @@ -307,9 +303,9 @@ function handle_task_backtraces(stage_path = nothing) end local backtrace_file if stage_path === nothing - backtrace_file = tempname() + backtrace_file = tempname(;cleanup=false) else - backtrace_file = tempname(stage_path) + backtrace_file = tempname(stage_path; cleanup=false) end open(backtrace_file, "w") do io redirect_stderr(io) do