#json-api #profiler #symbolication #symbols #querying #samply

samply-api

用于查询符号信息的JSON API,使用samply-symbols

11个版本 (6个重大变更)

0.23.2 2024年6月28日
0.23.0 2024年4月15日
0.22.0 2024年2月12日
0.21.1 2023年1月11日
0.18.0 2022年7月21日

#244WebAssembly

Download history 160/week @ 2024-04-22 146/week @ 2024-04-29 164/week @ 2024-05-06 148/week @ 2024-05-13 164/week @ 2024-05-20 163/week @ 2024-05-27 118/week @ 2024-06-03 169/week @ 2024-06-10 279/week @ 2024-06-17 280/week @ 2024-06-24 132/week @ 2024-07-01 130/week @ 2024-07-08 124/week @ 2024-07-15 80/week @ 2024-07-22 239/week @ 2024-07-29 107/week @ 2024-08-05

每月559次下载
3 个crate中使用 (通过 wholesym)

MIT/Apache

430KB
9K SLoC

samply-api

此crate通过本地符号文件实现用于分析符号化的JSON API。它暴露了一个名为API的单个类型,并使用samply-symbols crate来实现。

API在API.md中有文档说明。

samply-symbols crate一样,此crate不包含任何直接文件访问。它是这样编写的,可以编译成WebAssembly,所有文件访问都通过FileAndPathHelper trait进行中介。

除非您必须这样做,否则请不要直接使用此crate。相反,使用wholesym,它提供了一个更易用的Rust API。wholesym通过SymbolManager::query_json_api公开JSON API功能。

示例

use samply_api::samply_symbols::{
    FileContents, FileAndPathHelper, FileAndPathHelperResult, LibraryInfo, OptionallySendFuture,
    CandidatePathInfo, FileLocation, SymbolManager,
};
use samply_api::samply_symbols::debugid::DebugId;

async fn run_query() -> String {
    let this_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let helper = ExampleHelper {
        artifact_directory: this_dir.join("..").join("fixtures").join("win64-ci")
    };
    let symbol_manager = SymbolManager::with_helper(&helper);
    let api = samply_api::Api::new(&symbol_manager);

    api.query_api(
        "/symbolicate/v5",
        r#"{
            "memoryMap": [
              [
                "firefox.pdb",
                "AA152DEB2D9B76084C4C44205044422E1"
              ]
            ],
            "stacks": [
              [
                [0, 204776],
                [0, 129423],
                [0, 244290],
                [0, 244219]
              ]
            ]
          }"#,
    ).await
}

struct ExampleHelper {
    artifact_directory: std::path::PathBuf,
}

impl FileAndPathHelper for ExampleHelper {
    type F = Vec<u8>;
    type FL = ExampleFileLocation;
    type OpenFileFuture = std::pin::Pin<
        Box<dyn OptionallySendFuture<Output = FileAndPathHelperResult<Self::F>> + 'h>,
    >;

    fn get_candidate_paths_for_debug_file(
        &self,
        library_info: &LibraryInfo,
    ) -> FileAndPathHelperResult<Vec<CandidatePathInfo<ExampleFileLocation>>> {
        if let Some(debug_name) = library_info.debug_name.as_deref() {
            Ok(vec![CandidatePathInfo::SingleFile(ExampleFileLocation(
                self.artifact_directory.join(debug_name),
            ))])
        } else {
            Ok(vec![])
        }
    }

    fn get_candidate_paths_for_binary(
        &self,
        library_info: &LibraryInfo,
    ) -> FileAndPathHelperResult<Vec<CandidatePathInfo<ExampleFileLocation>>> {
        if let Some(name) = library_info.name.as_deref() {
            Ok(vec![CandidatePathInfo::SingleFile(ExampleFileLocation(
                self.artifact_directory.join(name),
            ))])
        } else {
            Ok(vec![])
        }
    }

   fn get_dyld_shared_cache_paths(
       &self,
       _arch: Option<&str>,
   ) -> FileAndPathHelperResult<Vec<ExampleFileLocation>> {
       Ok(vec![])
   }

    fn load_file(
        &'h self,
        location: ExampleFileLocation,
    ) -> std::pin::Pin<
        Box<dyn OptionallySendFuture<Output = FileAndPathHelperResult<Self::F>> + 'h>,
    > {
        async fn load_file_impl(path: std::path::PathBuf) -> FileAndPathHelperResult<Vec<u8>> {
            Ok(std::fs::read(&path)?)
        }

        Box::pin(load_file_impl(location.0))
    }
}

#[derive(Clone, Debug)]
struct ExampleFileLocation(std::path::PathBuf);

impl std::fmt::Display for ExampleFileLocation {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.0.to_string_lossy().fmt(f)
    }
}

impl FileLocation for ExampleFileLocation {
    fn location_for_dyld_subcache(&self, suffix: &str) -> Option<Self> {
        let mut filename = self.0.file_name().unwrap().to_owned();
        filename.push(suffix);
        Some(Self(self.0.with_file_name(filename)))
    }

    fn location_for_external_object_file(&self, object_file: &str) -> Option<Self> {
        Some(Self(object_file.into()))
    }

    fn location_for_pdb_from_binary(&self, pdb_path_in_binary: &str) -> Option<Self> {
        Some(Self(pdb_path_in_binary.into()))
    }

    fn location_for_source_file(&self, source_file_path: &str) -> Option<Self> {
        Some(Self(source_file_path.into()))
    }

    fn location_for_breakpad_symindex(&self) -> Option<Self> {
        Some(Self(self.0.with_extension("symindex")))
    }
}

依赖项

~21MB
~346K SLoC