use serde::{Deserialize, Serialize};
use crate::monitor::btf_render::RenderedValue;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct SdtAllocEntry {
pub idx: i32,
pub genn: i32,
pub user_addr: u64,
pub payload: RenderedValue,
}
impl std::fmt::Display for SdtAllocEntry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"idx={} genn={} user_addr={:#x} payload=",
self.idx, self.genn, self.user_addr
)?;
std::fmt::Display::fmt(&self.payload, f)
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[non_exhaustive]
pub struct SdtAllocatorSnapshot {
pub allocator_name: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub entries: Vec<SdtAllocEntry>,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub truncated: bool,
pub skipped_subtrees: u32,
pub elem_size: u64,
pub target_type_id: u32,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub payload_type_reason: String,
#[serde(skip)]
pub all_slot_addrs: Vec<u64>,
}
impl std::fmt::Display for SdtAllocatorSnapshot {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"sdt_alloc {} (elem_size={}, target_type_id={}",
self.allocator_name, self.elem_size, self.target_type_id
)?;
if !self.payload_type_reason.is_empty() {
write!(f, ", reason={}", self.payload_type_reason)?;
}
write!(f, "): {} live", self.entries.len())?;
if self.truncated {
f.write_str(" (truncated)")?;
}
if self.skipped_subtrees > 0 {
write!(f, " ({} subtrees skipped)", self.skipped_subtrees)?;
}
for entry in &self.entries {
f.write_str("\n")?;
crate::monitor::btf_render::write_value_at_depth(f, &entry.payload, 2)?;
}
Ok(())
}
}