risingwave_common_heap_profiling/
jeprof.rs1use std::path::Path;
16use std::process::Command;
17use std::{env, fs};
18
19#[derive(thiserror::Error, Debug, thiserror_ext::ContextInto)]
21pub enum JeprofError {
22    #[error(transparent)]
23    IoError(#[from] std::io::Error),
24
25    #[error("jeprof exit with an error (stdout: {stdout}, stderr: {stderr}): {inner}")]
26    ExitError {
27        #[source]
28        inner: std::process::ExitStatusError,
29        stdout: String,
30        stderr: String,
31    },
32}
33
34pub async fn run(profile_path: String, collapsed_path: String) -> Result<(), JeprofError> {
36    let executable_path = env::current_exe()?;
37
38    let prof_cmd = move || {
39        Command::new("jeprof")
40            .arg("--collapsed")
41            .arg(executable_path)
42            .arg(Path::new(&profile_path))
43            .output()
44    };
45
46    let output = tokio::task::spawn_blocking(prof_cmd).await.unwrap()?;
47
48    output.status.exit_ok().into_exit_error(
49        String::from_utf8_lossy(&output.stdout),
50        String::from_utf8_lossy(&output.stderr),
51    )?;
52
53    fs::write(Path::new(&collapsed_path), &output.stdout)?;
54
55    Ok(())
56}