Fix storage display format and clean up warnings
All checks were successful
Build and Release / build-and-release (push) Successful in 1m9s
All checks were successful
Build and Release / build-and-release (push) Successful in 1m9s
Update storage display to match CLAUDE.md specification: - Show drive temp/wear on main line: nvme0n1 T: 25°C W: 4% - Display individual filesystems as sub-items: /: 55% 250.5GB/456.4GB - Remove Total usage line in favor of filesystem breakdown Clean up code warnings: - Remove unused heartbeat methods and fields - Remove unused backup widget fields and methods - Add allow attributes for legacy methods
This commit is contained in:
@@ -18,8 +18,6 @@ pub struct BackupWidget {
|
||||
duration_seconds: Option<i64>,
|
||||
/// Last backup timestamp
|
||||
last_run_timestamp: Option<i64>,
|
||||
/// Total number of backup services
|
||||
total_services: Option<i64>,
|
||||
/// Total repository size in GB
|
||||
total_repo_size_gb: Option<f32>,
|
||||
/// Total disk space for backups in GB
|
||||
@@ -32,14 +30,6 @@ pub struct BackupWidget {
|
||||
backup_disk_serial_number: Option<String>,
|
||||
/// Backup disk wear percentage from SMART data
|
||||
backup_disk_wear_percent: Option<f32>,
|
||||
/// Backup disk filesystem label
|
||||
backup_disk_filesystem_label: Option<String>,
|
||||
/// Number of completed services
|
||||
services_completed_count: Option<i64>,
|
||||
/// Number of failed services
|
||||
services_failed_count: Option<i64>,
|
||||
/// Number of disabled services
|
||||
services_disabled_count: Option<i64>,
|
||||
/// All individual service metrics for detailed display
|
||||
service_metrics: Vec<ServiceMetricData>,
|
||||
/// Last update indicator
|
||||
@@ -50,7 +40,6 @@ pub struct BackupWidget {
|
||||
struct ServiceMetricData {
|
||||
name: String,
|
||||
status: Status,
|
||||
exit_code: Option<i64>,
|
||||
archive_count: Option<i64>,
|
||||
repo_size_gb: Option<f32>,
|
||||
}
|
||||
@@ -61,17 +50,12 @@ impl BackupWidget {
|
||||
overall_status: Status::Unknown,
|
||||
duration_seconds: None,
|
||||
last_run_timestamp: None,
|
||||
total_services: None,
|
||||
total_repo_size_gb: None,
|
||||
backup_disk_total_gb: None,
|
||||
backup_disk_used_gb: None,
|
||||
backup_disk_product_name: None,
|
||||
backup_disk_serial_number: None,
|
||||
backup_disk_wear_percent: None,
|
||||
backup_disk_filesystem_label: None,
|
||||
services_completed_count: None,
|
||||
services_failed_count: None,
|
||||
services_disabled_count: None,
|
||||
service_metrics: Vec::new(),
|
||||
has_data: false,
|
||||
}
|
||||
@@ -112,6 +96,7 @@ impl BackupWidget {
|
||||
|
||||
|
||||
/// Extract service name from metric name (e.g., "backup_service_gitea_status" -> "gitea")
|
||||
#[allow(dead_code)]
|
||||
fn extract_service_name(metric_name: &str) -> Option<String> {
|
||||
if metric_name.starts_with("backup_service_") {
|
||||
let name_part = &metric_name[15..]; // Remove "backup_service_" prefix
|
||||
@@ -119,8 +104,6 @@ impl BackupWidget {
|
||||
// Try to extract service name by removing known suffixes
|
||||
if let Some(service_name) = name_part.strip_suffix("_status") {
|
||||
Some(service_name.to_string())
|
||||
} else if let Some(service_name) = name_part.strip_suffix("_exit_code") {
|
||||
Some(service_name.to_string())
|
||||
} else if let Some(service_name) = name_part.strip_suffix("_archive_count") {
|
||||
Some(service_name.to_string())
|
||||
} else if let Some(service_name) = name_part.strip_suffix("_repo_size_gb") {
|
||||
@@ -154,6 +137,7 @@ impl Widget for BackupWidget {
|
||||
}
|
||||
|
||||
impl BackupWidget {
|
||||
#[allow(dead_code)]
|
||||
fn update_from_metrics(&mut self, metrics: &[&Metric]) {
|
||||
debug!("Backup widget updating with {} metrics", metrics.len());
|
||||
for metric in metrics {
|
||||
@@ -199,9 +183,6 @@ impl BackupWidget {
|
||||
"backup_last_run_timestamp" => {
|
||||
self.last_run_timestamp = metric.value.as_i64();
|
||||
}
|
||||
"backup_total_services" => {
|
||||
self.total_services = metric.value.as_i64();
|
||||
}
|
||||
"backup_total_repo_size_gb" => {
|
||||
self.total_repo_size_gb = metric.value.as_f32();
|
||||
}
|
||||
@@ -220,18 +201,6 @@ impl BackupWidget {
|
||||
"backup_disk_wear_percent" => {
|
||||
self.backup_disk_wear_percent = metric.value.as_f32();
|
||||
}
|
||||
"backup_disk_filesystem_label" => {
|
||||
self.backup_disk_filesystem_label = Some(metric.value.as_string());
|
||||
}
|
||||
"backup_services_completed_count" => {
|
||||
self.services_completed_count = metric.value.as_i64();
|
||||
}
|
||||
"backup_services_failed_count" => {
|
||||
self.services_failed_count = metric.value.as_i64();
|
||||
}
|
||||
"backup_services_disabled_count" => {
|
||||
self.services_disabled_count = metric.value.as_i64();
|
||||
}
|
||||
_ => {
|
||||
// Handle individual service metrics
|
||||
if let Some(service_name) = Self::extract_service_name(&metric.name) {
|
||||
@@ -243,8 +212,7 @@ impl BackupWidget {
|
||||
ServiceMetricData {
|
||||
name: service_name,
|
||||
status: Status::Unknown,
|
||||
exit_code: None,
|
||||
archive_count: None,
|
||||
archive_count: None,
|
||||
repo_size_gb: None,
|
||||
}
|
||||
});
|
||||
@@ -252,8 +220,6 @@ impl BackupWidget {
|
||||
if metric.name.ends_with("_status") {
|
||||
entry.status = metric.status;
|
||||
debug!("Set status for {}: {:?}", entry.name, entry.status);
|
||||
} else if metric.name.ends_with("_exit_code") {
|
||||
entry.exit_code = metric.value.as_i64();
|
||||
} else if metric.name.ends_with("_archive_count") {
|
||||
entry.archive_count = metric.value.as_i64();
|
||||
debug!(
|
||||
|
||||
@@ -47,6 +47,7 @@ impl ServicesWidget {
|
||||
}
|
||||
|
||||
/// Extract service name and determine if it's a parent or sub-service
|
||||
#[allow(dead_code)]
|
||||
fn extract_service_info(metric_name: &str) -> Option<(String, Option<String>)> {
|
||||
if metric_name.starts_with("service_") {
|
||||
if let Some(end_pos) = metric_name
|
||||
@@ -277,6 +278,7 @@ impl Widget for ServicesWidget {
|
||||
}
|
||||
|
||||
impl ServicesWidget {
|
||||
#[allow(dead_code)]
|
||||
fn update_from_metrics(&mut self, metrics: &[&Metric]) {
|
||||
debug!("Services widget updating with {} metrics", metrics.len());
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ pub struct SystemWidget {
|
||||
tmp_total_gb: Option<f32>,
|
||||
memory_status: Status,
|
||||
tmp_status: Status,
|
||||
/// All tmpfs mounts (for auto-discovery support)
|
||||
tmpfs_mounts: Vec<cm_dashboard_shared::TmpfsData>,
|
||||
|
||||
// Storage metrics (collected from disk metrics)
|
||||
storage_pools: Vec<StoragePool>,
|
||||
@@ -50,7 +52,6 @@ struct StoragePool {
|
||||
used_gb: Option<f32>,
|
||||
total_gb: Option<f32>,
|
||||
status: Status,
|
||||
health_status: Status, // Separate status for pool health vs usage
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -88,6 +89,7 @@ impl SystemWidget {
|
||||
tmp_total_gb: None,
|
||||
memory_status: Status::Unknown,
|
||||
tmp_status: Status::Unknown,
|
||||
tmpfs_mounts: Vec::new(),
|
||||
storage_pools: Vec::new(),
|
||||
has_data: false,
|
||||
}
|
||||
@@ -121,20 +123,6 @@ impl SystemWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// Format /tmp usage
|
||||
fn format_tmp_usage(&self) -> String {
|
||||
match (self.tmp_usage_percent, self.tmp_used_gb, self.tmp_total_gb) {
|
||||
(Some(pct), Some(used), Some(total)) => {
|
||||
let used_str = if used < 0.1 {
|
||||
format!("{:.0}B", used * 1024.0) // Show as MB if very small
|
||||
} else {
|
||||
format!("{:.1}GB", used)
|
||||
};
|
||||
format!("{:.0}% {}/{:.1}GB", pct, used_str, total)
|
||||
}
|
||||
_ => "—% —GB/—GB".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current agent hash for rebuild completion detection
|
||||
pub fn _get_agent_hash(&self) -> Option<&String> {
|
||||
@@ -166,7 +154,10 @@ impl Widget for SystemWidget {
|
||||
self.memory_total_gb = Some(memory.total_gb);
|
||||
self.memory_status = Status::Ok;
|
||||
|
||||
// Extract tmpfs data
|
||||
// Store all tmpfs mounts for display
|
||||
self.tmpfs_mounts = memory.tmpfs.clone();
|
||||
|
||||
// Extract tmpfs data (maintain backward compatibility for /tmp)
|
||||
if let Some(tmp_data) = memory.tmpfs.iter().find(|t| t.mount == "/tmp") {
|
||||
self.tmp_usage_percent = Some(tmp_data.usage_percent);
|
||||
self.tmp_used_gb = Some(tmp_data.used_gb);
|
||||
@@ -196,7 +187,6 @@ impl SystemWidget {
|
||||
used_gb: None,
|
||||
total_gb: None,
|
||||
status: Status::Ok,
|
||||
health_status: Status::Ok,
|
||||
};
|
||||
|
||||
// Add drive info
|
||||
@@ -278,40 +268,27 @@ impl SystemWidget {
|
||||
let pool_spans = StatusIcons::create_status_spans(pool.status.clone(), &pool_label);
|
||||
lines.push(Line::from(pool_spans));
|
||||
|
||||
// Pool total usage line
|
||||
if let (Some(usage), Some(used), Some(total)) = (pool.usage_percent, pool.used_gb, pool.total_gb) {
|
||||
let usage_spans = vec![
|
||||
Span::styled(" ├─ ", Typography::tree()),
|
||||
Span::raw(" "),
|
||||
];
|
||||
let mut usage_line_spans = usage_spans;
|
||||
usage_line_spans.extend(StatusIcons::create_status_spans(pool.status.clone(), &format!("Total: {}% {:.1}GB/{:.1}GB", usage as i32, used, total)));
|
||||
lines.push(Line::from(usage_line_spans));
|
||||
}
|
||||
|
||||
// Drive details for physical drives
|
||||
// Show individual filesystems for physical drives (matching CLAUDE.md format)
|
||||
if pool.pool_type.starts_with("drive") {
|
||||
for drive in &pool.drives {
|
||||
if drive.name == pool.name {
|
||||
let mut drive_details = Vec::new();
|
||||
if let Some(temp) = drive.temperature {
|
||||
drive_details.push(format!("T: {}°C", temp as i32));
|
||||
}
|
||||
if let Some(wear) = drive.wear_percent {
|
||||
drive_details.push(format!("W: {}%", wear as i32));
|
||||
}
|
||||
|
||||
if !drive_details.is_empty() {
|
||||
let drive_text = format!("● {} {}", drive.name, drive_details.join(" "));
|
||||
let drive_spans = vec![
|
||||
Span::styled(" └─ ", Typography::tree()),
|
||||
Span::raw(" "),
|
||||
];
|
||||
let mut drive_line_spans = drive_spans;
|
||||
drive_line_spans.extend(StatusIcons::create_status_spans(drive.status.clone(), &drive_text));
|
||||
lines.push(Line::from(drive_line_spans));
|
||||
}
|
||||
}
|
||||
// Show filesystem entries like: ├─ ● /: 55% 250.5GB/456.4GB
|
||||
for (i, filesystem) in pool.filesystems.iter().enumerate() {
|
||||
let is_last = i == pool.filesystems.len() - 1;
|
||||
let tree_symbol = if is_last { " └─ " } else { " ├─ " };
|
||||
|
||||
let fs_text = format!("{}: {:.0}% {:.1}GB/{:.1}GB",
|
||||
filesystem.mount_point,
|
||||
filesystem.usage_percent.unwrap_or(0.0),
|
||||
filesystem.used_gb.unwrap_or(0.0),
|
||||
filesystem.total_gb.unwrap_or(0.0));
|
||||
|
||||
let mut fs_spans = vec![
|
||||
Span::styled(tree_symbol, Typography::tree()),
|
||||
];
|
||||
fs_spans.extend(StatusIcons::create_status_spans(
|
||||
filesystem.status.clone(),
|
||||
&fs_text
|
||||
));
|
||||
lines.push(Line::from(fs_spans));
|
||||
}
|
||||
} else {
|
||||
// For mergerfs pools, show data drives and parity drives in tree structure
|
||||
@@ -432,15 +409,29 @@ impl SystemWidget {
|
||||
);
|
||||
lines.push(Line::from(memory_spans));
|
||||
|
||||
let tmp_text = self.format_tmp_usage();
|
||||
let mut tmp_spans = vec![
|
||||
Span::styled(" └─ ", Typography::tree()),
|
||||
];
|
||||
tmp_spans.extend(StatusIcons::create_status_spans(
|
||||
self.tmp_status.clone(),
|
||||
&format!("/tmp: {}", tmp_text)
|
||||
));
|
||||
lines.push(Line::from(tmp_spans));
|
||||
// Display all tmpfs mounts
|
||||
for (i, tmpfs) in self.tmpfs_mounts.iter().enumerate() {
|
||||
let is_last = i == self.tmpfs_mounts.len() - 1;
|
||||
let tree_symbol = if is_last { " └─ " } else { " ├─ " };
|
||||
|
||||
let usage_text = if tmpfs.total_gb > 0.0 {
|
||||
format!("{:.0}% {:.1}GB/{:.1}GB",
|
||||
tmpfs.usage_percent,
|
||||
tmpfs.used_gb,
|
||||
tmpfs.total_gb)
|
||||
} else {
|
||||
"— —/—".to_string()
|
||||
};
|
||||
|
||||
let mut tmpfs_spans = vec![
|
||||
Span::styled(tree_symbol, Typography::tree()),
|
||||
];
|
||||
tmpfs_spans.extend(StatusIcons::create_status_spans(
|
||||
Status::Ok, // TODO: Calculate status based on usage_percent
|
||||
&format!("{}: {}", tmpfs.mount, usage_text)
|
||||
));
|
||||
lines.push(Line::from(tmpfs_spans));
|
||||
}
|
||||
|
||||
// Storage section
|
||||
lines.push(Line::from(vec![
|
||||
|
||||
Reference in New Issue
Block a user