feat: add memory footprint to /stats and dashboard (#26)
* feat: add memory footprint to /stats and dashboard Per-structure heap estimation (cache, blocklist, query log, SRTT, overrides) with process RSS via mach_task_basic_info / sysconf. Dashboard gets a 6th stat card and a sidebar breakdown panel with stacked bar visualization. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use phys_footprint on macOS to match Activity Monitor Switch from MACH_TASK_BASIC_INFO (resident_size) to TASK_VM_INFO (phys_footprint) which matches Activity Monitor's Memory column. Also: capacity-aware heap estimation, entry counts in memory payload, heap_bytes tests for all stores. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: remove redundant fields and fix naming in memory stats Remove duplicate entry counts from MemoryStats (already in parent StatsResponse), rename process_rss_bytes to process_memory_bytes to match macOS phys_footprint semantics, drop restating comments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
52
src/api.rs
52
src/api.rs
@@ -170,6 +170,7 @@ struct StatsResponse {
|
||||
overrides: OverrideStats,
|
||||
blocking: BlockingStatsResponse,
|
||||
lan: LanStatsResponse,
|
||||
memory: MemoryStats,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -210,6 +211,19 @@ struct BlockingStatsResponse {
|
||||
allowlist_size: usize,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct MemoryStats {
|
||||
cache_bytes: usize,
|
||||
blocklist_bytes: usize,
|
||||
query_log_bytes: usize,
|
||||
query_log_entries: usize,
|
||||
srtt_bytes: usize,
|
||||
srtt_entries: usize,
|
||||
overrides_bytes: usize,
|
||||
total_estimated_bytes: usize,
|
||||
process_memory_bytes: usize,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct DiagnoseResponse {
|
||||
domain: String,
|
||||
@@ -471,12 +485,29 @@ async fn query_log(
|
||||
|
||||
async fn stats(State(ctx): State<Arc<ServerCtx>>) -> Json<StatsResponse> {
|
||||
let snap = ctx.stats.lock().unwrap().snapshot();
|
||||
let (cache_len, cache_max) = {
|
||||
let (cache_len, cache_max, cache_bytes) = {
|
||||
let cache = ctx.cache.read().unwrap();
|
||||
(cache.len(), cache.max_entries())
|
||||
(cache.len(), cache.max_entries(), cache.heap_bytes())
|
||||
};
|
||||
let override_count = ctx.overrides.read().unwrap().active_count();
|
||||
let bl_stats = ctx.blocklist.read().unwrap().stats();
|
||||
let (override_count, overrides_bytes) = {
|
||||
let ov = ctx.overrides.read().unwrap();
|
||||
(ov.active_count(), ov.heap_bytes())
|
||||
};
|
||||
let (bl_stats, blocklist_bytes) = {
|
||||
let bl = ctx.blocklist.read().unwrap();
|
||||
(bl.stats(), bl.heap_bytes())
|
||||
};
|
||||
let (query_log_bytes, query_log_entries) = {
|
||||
let log = ctx.query_log.lock().unwrap();
|
||||
(log.heap_bytes(), log.len())
|
||||
};
|
||||
let (srtt_bytes, srtt_entries, srtt_enabled) = {
|
||||
let s = ctx.srtt.read().unwrap();
|
||||
(s.heap_bytes(), s.len(), s.is_enabled())
|
||||
};
|
||||
|
||||
let total_estimated =
|
||||
cache_bytes + blocklist_bytes + query_log_bytes + srtt_bytes + overrides_bytes;
|
||||
|
||||
let upstream = if ctx.upstream_mode == crate::config::UpstreamMode::Recursive {
|
||||
"recursive (root hints)".to_string()
|
||||
@@ -491,7 +522,7 @@ async fn stats(State(ctx): State<Arc<ServerCtx>>) -> Json<StatsResponse> {
|
||||
config_path: ctx.config_path.clone(),
|
||||
data_dir: ctx.data_dir.to_string_lossy().to_string(),
|
||||
dnssec: ctx.dnssec_enabled,
|
||||
srtt: ctx.srtt.read().unwrap().is_enabled(),
|
||||
srtt: srtt_enabled,
|
||||
queries: QueriesStats {
|
||||
total: snap.total,
|
||||
forwarded: snap.forwarded,
|
||||
@@ -520,6 +551,17 @@ async fn stats(State(ctx): State<Arc<ServerCtx>>) -> Json<StatsResponse> {
|
||||
enabled: ctx.lan_enabled,
|
||||
peers: ctx.lan_peers.lock().unwrap().list().len(),
|
||||
},
|
||||
memory: MemoryStats {
|
||||
cache_bytes,
|
||||
blocklist_bytes,
|
||||
query_log_bytes,
|
||||
query_log_entries,
|
||||
srtt_bytes,
|
||||
srtt_entries,
|
||||
overrides_bytes,
|
||||
total_estimated_bytes: total_estimated,
|
||||
process_memory_bytes: crate::stats::process_memory_bytes(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user