use serde::Serialize;
use super::DiagnosticsResult;
#[derive(Debug, Clone, Serialize)]
pub(super) struct MemoryDump {
pub name: String,
pub data: String,
pub size: u64,
pub timestamp: Option<u64>,
}
pub(super) async fn load_memory_dumps(
memory_directory: &std::path::Path,
) -> DiagnosticsResult<Vec<MemoryDump>> {
use tokio::fs;
let mut dumps = Vec::new();
if memory_directory.exists() {
let mut entries = fs::read_dir(memory_directory).await.map_err(|e| {
super::DiagnosticsError::Internal(format!(
"Failed to read memory directory '{}': {}",
memory_directory.display(),
e
))
})?;
while let Some(entry) = entries.next_entry().await.map_err(|e| {
super::DiagnosticsError::Internal(format!("Failed to read directory entry: {}", e))
})? {
let path = entry.path();
if path.is_file()
&& path.extension().is_some_and(|ext| ext == "prof")
&& let Some(file_name) = path.file_name().and_then(|n| n.to_str())
{
match load_single_memory_dump(&path, file_name).await {
Ok(dump) => dumps.push(dump),
Err(e) => {
tracing::warn!("Failed to process dump {}: {}", file_name, e);
}
}
}
}
}
dumps.sort_by(|a, b| a.name.cmp(&b.name));
Ok(dumps)
}
async fn load_single_memory_dump(
path: &std::path::Path,
file_name: &str,
) -> DiagnosticsResult<MemoryDump> {
use base64::Engine;
use tokio::fs;
let content = fs::read(path).await.map_err(|e| {
super::DiagnosticsError::Internal(format!(
"Failed to read dump file '{}': {}",
path.display(),
e
))
})?;
let metadata = fs::metadata(path).await.map_err(|e| {
super::DiagnosticsError::Internal(format!(
"Failed to read dump metadata '{}': {}",
path.display(),
e
))
})?;
let encoded_content = base64::engine::general_purpose::STANDARD.encode(&content);
let timestamp = metadata
.created()
.ok()
.and_then(|t| t.duration_since(std::time::UNIX_EPOCH).ok())
.map(|d| d.as_secs());
Ok(MemoryDump {
name: file_name.to_string(),
size: metadata.len(),
data: encoded_content,
timestamp,
})
}
#[cfg(all(target_family = "unix", feature = "global-allocator"))]
mod supported;
#[cfg(not(all(target_family = "unix", feature = "global-allocator")))]
mod unsupported;
pub(super) mod symbol_resolver;
#[cfg(all(target_family = "unix", feature = "global-allocator"))]
pub(super) use supported::MemoryService;
#[cfg(not(all(target_family = "unix", feature = "global-allocator")))]
pub(super) use unsupported::MemoryService;
#[cfg(all(target_family = "unix", feature = "global-allocator"))]
#[cfg(test)]
mod tests;