diff --git a/src/admin/debug/commands.rs b/src/admin/debug/commands.rs index b6189f6a..ad61440c 100644 --- a/src/admin/debug/commands.rs +++ b/src/admin/debug/commands.rs @@ -843,19 +843,27 @@ pub(super) async fn resolve_true_destination( } #[admin_command] -pub(super) async fn memory_stats(&self) -> Result { - let html_body = conduwuit::alloc::memory_stats(); +pub(super) async fn memory_stats(&self, opts: Option) -> Result { + const OPTS: &str = "abcdefghijklmnopqrstuvwxyz"; - if html_body.is_none() { - return Ok(RoomMessageEventContent::text_plain( - "malloc stats are not supported on your compiled malloc.", - )); - } + let opts: String = OPTS + .chars() + .filter(|&c| { + let allow_any = opts.as_ref().is_some_and(|opts| opts == "*"); - Ok(RoomMessageEventContent::text_html( - "This command's output can only be viewed by clients that render HTML.".to_owned(), - html_body.expect("string result"), - )) + let allow = allow_any || opts.as_ref().is_some_and(|opts| opts.contains(c)); + + !allow + }) + .collect(); + + let stats = conduwuit::alloc::memory_stats(&opts).unwrap_or_default(); + + self.write_str("```\n").await?; + self.write_str(&stats).await?; + self.write_str("\n```").await?; + + Ok(RoomMessageEventContent::text_plain("")) } #[cfg(tokio_unstable)] diff --git a/src/admin/debug/mod.rs b/src/admin/debug/mod.rs index 2367f80d..07f7296b 100644 --- a/src/admin/debug/mod.rs +++ b/src/admin/debug/mod.rs @@ -191,7 +191,13 @@ pub(super) enum DebugCommand { }, /// - Print extended memory usage - MemoryStats, + /// + /// Optional argument is a character mask (a sequence of characters in any + /// order) which enable additional extended statistics. Known characters are + /// "abdeglmx". For convenience, a '*' will enable everything. + MemoryStats { + opts: Option, + }, /// - Print general tokio runtime metric totals. RuntimeMetrics, diff --git a/src/core/alloc/default.rs b/src/core/alloc/default.rs index 5db02884..56e8c407 100644 --- a/src/core/alloc/default.rs +++ b/src/core/alloc/default.rs @@ -5,7 +5,7 @@ pub fn trim() -> crate::Result { Ok(()) } /// Always returns None #[must_use] -pub fn memory_stats() -> Option { None } +pub fn memory_stats(_opts: &str) -> Option { None } /// Always returns None #[must_use] diff --git a/src/core/alloc/hardened.rs b/src/core/alloc/hardened.rs index e2d9b28e..ff10cf2b 100644 --- a/src/core/alloc/hardened.rs +++ b/src/core/alloc/hardened.rs @@ -7,9 +7,9 @@ pub fn trim() -> crate::Result { Ok(()) } #[must_use] //TODO: get usage -pub fn memory_usage() -> Option { None } +pub fn memory_usage() -> Option { None } #[must_use] -pub fn memory_stats() -> Option { +pub fn memory_stats(_opts: &str) -> Option { Some("Extended statistics are not available from hardened_malloc.".to_owned()) } diff --git a/src/core/alloc/je.rs b/src/core/alloc/je.rs index b2c1fe85..ccb213c9 100644 --- a/src/core/alloc/je.rs +++ b/src/core/alloc/je.rs @@ -3,7 +3,7 @@ use std::{ cell::OnceCell, ffi::{c_char, c_void}, - fmt::{Debug, Write}, + fmt::Debug, }; use arrayvec::ArrayVec; @@ -66,15 +66,12 @@ pub fn memory_usage() -> Option { #[cfg(not(feature = "jemalloc_stats"))] pub fn memory_usage() -> Option { None } -#[must_use] -pub fn memory_stats() -> Option { - const MAX_LENGTH: usize = 65536 - 4096; +pub fn memory_stats(opts: &str) -> Option { + const MAX_LENGTH: usize = 1_048_576; - let opts_s = "d"; let mut str = String::new(); - let opaque = std::ptr::from_mut(&mut str).cast::(); - let opts_p: *const c_char = std::ffi::CString::new(opts_s) + let opts_p: *const c_char = std::ffi::CString::new(opts) .expect("cstring") .into_raw() .cast_const(); @@ -84,7 +81,8 @@ pub fn memory_stats() -> Option { unsafe { ffi::malloc_stats_print(Some(malloc_stats_cb), opaque, opts_p) }; str.truncate(MAX_LENGTH); - Some(format!("
{str}
")) + + Some(str) } unsafe extern "C" fn malloc_stats_cb(opaque: *mut c_void, msg: *const c_char) {