diff --git a/Cargo.toml b/Cargo.toml index a77d21af..1f037cb0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "resources" version = "1.7.1" -authors = ["nokyan "] +authors = ["nokyan "] edition = "2021" rust-version = "1.80.0" homepage = "https://apps.gnome.org/app/net.nokyan.Resources/" diff --git a/data/net.nokyan.Resources.metainfo.xml.in.in b/data/net.nokyan.Resources.metainfo.xml.in.in index 0c01e76e..396da97e 100644 --- a/data/net.nokyan.Resources.metainfo.xml.in.in +++ b/data/net.nokyan.Resources.metainfo.xml.in.in @@ -38,7 +38,7 @@ nokyan - nokyan@tuta.io + hello@nokyan.net @gettext-package@ @app-id@.desktop diff --git a/lib/process_data/Cargo.toml b/lib/process_data/Cargo.toml index 52489eb8..6f9d641b 100644 --- a/lib/process_data/Cargo.toml +++ b/lib/process_data/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "process-data" version = "1.7.1" -authors = ["nokyan "] +authors = ["nokyan "] edition = "2021" rust-version = "1.80.0" homepage = "https://apps.gnome.org/app/net.nokyan.Resources/" diff --git a/lib/process_data/src/lib.rs b/lib/process_data/src/lib.rs index db60fd1e..3de390bf 100644 --- a/lib/process_data/src/lib.rs +++ b/lib/process_data/src/lib.rs @@ -108,7 +108,7 @@ static NVIDIA_PROCESS_INFOS: Lazy>>> = #[nutype( validate(less_or_equal = 19), validate(greater_or_equal = -20), - derive(Debug, Default, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Copy, FromStr, Deref, TryFrom), + derive(Debug, Default, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Copy, FromStr, Deref, TryFrom, Display), default = 0 )] pub struct Niceness(i8); diff --git a/lib/process_data/src/meson.build b/lib/process_data/src/meson.build index 5b94e5db..c168c641 100644 --- a/lib/process_data/src/meson.build +++ b/lib/process_data/src/meson.build @@ -9,6 +9,6 @@ test( 'Cargo tests (process_data)', cargo, args: ['test', cargo_options], - timeout: 600, + timeout: 3600, env: cargo_env, ) \ No newline at end of file diff --git a/po/de.po b/po/de.po index 93461e39..8875cdbe 100644 --- a/po/de.po +++ b/po/de.po @@ -1,6 +1,6 @@ # # piekay <>, 2024. -# nokyan , 2022-2024. +# nokyan , 2022-2024. # msgid "" msgstr "" @@ -8,8 +8,8 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-10-19 13:51+0200\n" "PO-Revision-Date: 2024-10-19 13:57+0200\n" -"Last-Translator: nokyan \n" -"Language-Team: German \n" +"Last-Translator: nokyan \n" +"Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -133,7 +133,7 @@ msgstr "Probleme melden" #. One name per line, please do not remove previous names. #: src/application.rs:278 msgid "translator-credits" -msgstr "nokyan piekay" +msgstr "nokyan piekay" #: src/application.rs:279 msgid "Icon by" diff --git a/resources.doap b/resources.doap index 41f00353..225695ed 100644 --- a/resources.doap +++ b/resources.doap @@ -1,23 +1,16 @@ - - + Resources Keep an eye on system resources - Rust GTK 4 Libadwaita - nokyan - + @@ -26,4 +19,4 @@ - + \ No newline at end of file diff --git a/src/application.rs b/src/application.rs index 7d1a1ff9..8d681ad9 100644 --- a/src/application.rs +++ b/src/application.rs @@ -1,4 +1,4 @@ -use log::{debug, info}; +use log::{debug, info, trace}; use adw::{prelude::*, subclass::prelude::*}; use glib::clone; @@ -78,6 +78,8 @@ glib::wrapper! { impl Application { pub fn new() -> Self { + trace!("Creating Application GObject…"); + glib::Object::builder::() .property("application-id", Some(APP_ID)) .property("flags", gio::ApplicationFlags::empty()) @@ -263,7 +265,7 @@ impl Application { .application_name(i18n("Resources")) .application_icon(config::APP_ID) .developer_name(i18n("The Nalux Team")) - .developers(vec!["nokyan ".to_string()]) + .developers(vec!["nokyan "]) .license_type(gtk::License::Gpl30) .version(config::VERSION) .website("https://apps.gnome.org/app/net.nokyan.Resources/") @@ -283,19 +285,22 @@ impl Application { } pub fn run(&self) { + trace!("Starting the application"); info!("Resources ({APP_ID})"); - info!("Version: {VERSION}"); - info!("Datadir: {PKGDATADIR}"); - - let os_info = OsInfo::get(); - debug!( - "Operating system: {}", - os_info.name.as_deref().unwrap_or("N/A") - ); - debug!( - "Kernel version: {}", - os_info.kernel_version.as_deref().unwrap_or("N/A") - ); + info!("Version: {VERSION} ({PROFILE})"); + info!("Datadir: `{PKGDATADIR}`"); + + if log::log_enabled!(log::Level::Debug) { + let os_info = OsInfo::get(); + debug!( + "Operating system: {}", + os_info.name.as_deref().unwrap_or("N/A") + ); + debug!( + "Kernel version: {}", + os_info.kernel_version.as_deref().unwrap_or("N/A") + ); + } if PROFILE == "Devel" { info!( diff --git a/src/gui.rs b/src/gui.rs index b71c1240..c04c56ec 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -10,6 +10,7 @@ use crate::utils::IS_FLATPAK; use clap::{command, Parser}; use gettextrs::{gettext, LocaleCategory}; use gtk::{gio, glib}; +use log::trace; use self::application::Application; use self::config::{GETTEXT_PACKAGE, LOCALEDIR, RESOURCES_FILE}; @@ -65,6 +66,7 @@ pub fn main() { // Initialize logger pretty_env_logger::init(); + trace!("Trace logs activated. Brace yourself for *lots* of logs. Slowdowns may occur."); // reset XDG_DATA_DIRS to use absolute paths instead of relative paths because Flatpak seemingly cannot resolve them // this must happen now because once the GTK app is loaded, it's too late diff --git a/src/meson.build b/src/meson.build index fa8d850e..46de9ca0 100644 --- a/src/meson.build +++ b/src/meson.build @@ -33,7 +33,7 @@ test( 'Cargo tests (main application)', cargo, args: ['test', cargo_options], - timeout: 600, + timeout: 3600, env: cargo_env, ) diff --git a/src/ui/dialogs/app_dialog.rs b/src/ui/dialogs/app_dialog.rs index 3a1f012f..dae2f9d8 100644 --- a/src/ui/dialogs/app_dialog.rs +++ b/src/ui/dialogs/app_dialog.rs @@ -5,6 +5,7 @@ use crate::utils::units::{convert_speed, convert_storage}; use adw::{prelude::*, subclass::prelude::*}; use gtk::gio::ThemedIcon; use gtk::glib; +use log::trace; mod imp { @@ -99,6 +100,8 @@ impl Default for ResAppDialog { impl ResAppDialog { pub fn new() -> Self { + trace!("Creating ResAppDialog GObject…"); + glib::Object::new::() } @@ -107,6 +110,8 @@ impl ResAppDialog { } pub fn setup_widgets(&self, app: &ApplicationEntry) { + trace!("Setting up ResAppDialog widgets…"); + let imp = self.imp(); if app.id().is_none() // this will be the case for System Processes @@ -153,6 +158,8 @@ impl ResAppDialog { } pub fn update(&self, app: &ApplicationEntry) { + trace!("Refreshing ResAppDialog…"); + let imp = self.imp(); imp.cpu_usage diff --git a/src/ui/dialogs/process_dialog.rs b/src/ui/dialogs/process_dialog.rs index a98a25af..63f5d2fb 100644 --- a/src/ui/dialogs/process_dialog.rs +++ b/src/ui/dialogs/process_dialog.rs @@ -1,5 +1,6 @@ use adw::{prelude::*, subclass::prelude::*}; use gtk::glib::{self, GString}; +use log::trace; use crate::config::PROFILE; use crate::i18n::i18n; @@ -105,6 +106,7 @@ impl Default for ResProcessDialog { impl ResProcessDialog { pub fn new() -> Self { + trace!("Creating ResProcessDialog GObject…"); glib::Object::new::() } @@ -113,6 +115,8 @@ impl ResProcessDialog { } pub fn setup_widgets(&self, process: &ProcessEntry, user: &str) { + trace!("Setting up ResProcessDialog widgets…"); + let imp = self.imp(); imp.name.set_label(&process.name()); @@ -148,6 +152,8 @@ impl ResProcessDialog { } pub fn update(&self, process: &ProcessEntry) { + trace!("Refreshing ResProcessDialog…"); + let imp = self.imp(); imp.cpu_usage diff --git a/src/ui/dialogs/process_options_dialog.rs b/src/ui/dialogs/process_options_dialog.rs index dc30f2ae..877e17ee 100644 --- a/src/ui/dialogs/process_options_dialog.rs +++ b/src/ui/dialogs/process_options_dialog.rs @@ -10,6 +10,7 @@ use crate::{ use adw::{prelude::*, subclass::prelude::*, ToastOverlay}; use async_channel::Sender; use gtk::glib::{self, clone, MainContext}; +use log::trace; use process_data::Niceness; mod imp { @@ -87,6 +88,7 @@ impl Default for ResProcessOptionsDialog { impl ResProcessOptionsDialog { pub fn new() -> Self { + trace!("Creating ResProcessOptionsDialog GObject…"); glib::Object::new::() } @@ -118,6 +120,8 @@ impl ResProcessOptionsDialog { } pub fn setup_widgets(&self, process: &ProcessEntry) { + trace!("Setting up ResProcessOptionsDialog widgets…"); + let imp = self.imp(); imp.name.set_label(&process.name()); @@ -168,6 +172,8 @@ impl ResProcessOptionsDialog { sender: Sender, toast_overlay: &ToastOverlay, ) { + trace!("Setting up ResProcessOptionsDialog signals…"); + let imp = self.imp(); imp.select_all_button.connect_clicked(clone!( diff --git a/src/ui/dialogs/settings_dialog.rs b/src/ui/dialogs/settings_dialog.rs index 3e2f4f85..bb180e5f 100644 --- a/src/ui/dialogs/settings_dialog.rs +++ b/src/ui/dialogs/settings_dialog.rs @@ -1,5 +1,6 @@ use adw::{prelude::*, subclass::prelude::*}; use gtk::glib; +use log::trace; use crate::{ config::PROFILE, @@ -155,6 +156,8 @@ impl Default for ResSettingsDialog { impl ResSettingsDialog { pub fn new() -> Self { + trace!("Creating ResSettingsDialog GObject…"); + glib::Object::new::() } @@ -164,6 +167,8 @@ impl ResSettingsDialog { } pub fn setup_widgets(&self) { + trace!("Setting up ResSettingsDialog widgets…"); + let imp = self.imp(); imp.prefix_combo_row .set_selected((SETTINGS.base() as u8) as u32); @@ -252,6 +257,8 @@ impl ResSettingsDialog { } pub fn setup_signals(&self) { + trace!("Setting up ResSettingsDialog signals…"); + let imp = self.imp(); imp.prefix_combo_row .connect_selected_item_notify(|combo_row| { diff --git a/src/ui/pages/applications/application_entry.rs b/src/ui/pages/applications/application_entry.rs index c01a6c55..e309fdef 100644 --- a/src/ui/pages/applications/application_entry.rs +++ b/src/ui/pages/applications/application_entry.rs @@ -1,4 +1,5 @@ use gtk::glib::{self}; +use log::trace; use process_data::Containerization; use crate::{ @@ -179,6 +180,8 @@ glib::wrapper! { impl ApplicationEntry { pub fn new(app: &App, apps_context: &AppsContext) -> Self { + trace!("Creating ApplicationEntry ({}) GObject…", app.display_name); + let containerization = match app.containerization { Containerization::None => i18n("No"), Containerization::Flatpak => i18n("Yes (Flatpak)"), @@ -198,6 +201,8 @@ impl ApplicationEntry { } pub fn update(&self, app: &App, apps_context: &AppsContext) { + trace!("Refreshing ApplicationEntry ({})…", app.display_name); + self.set_cpu_usage(app.cpu_time_ratio(apps_context)); self.set_memory_usage(app.memory_usage(apps_context) as u64); self.set_swap_usage(app.swap_usage(apps_context) as u64); diff --git a/src/ui/pages/applications/application_name_cell.rs b/src/ui/pages/applications/application_name_cell.rs index 54c0b6ae..99583c3b 100644 --- a/src/ui/pages/applications/application_name_cell.rs +++ b/src/ui/pages/applications/application_name_cell.rs @@ -1,5 +1,6 @@ use adw::{glib::property::PropertySet, prelude::*, subclass::prelude::*}; use gtk::{gio::Icon, glib}; +use log::trace; mod imp { use std::cell::{Cell, RefCell}; @@ -160,6 +161,8 @@ impl Default for ResApplicationNameCell { impl ResApplicationNameCell { pub fn new() -> Self { + trace!("Creating ResApplicationNameCell GObject…"); + glib::Object::new::() } } diff --git a/src/ui/pages/battery.rs b/src/ui/pages/battery.rs index 17e5102d..48ed24d5 100644 --- a/src/ui/pages/battery.rs +++ b/src/ui/pages/battery.rs @@ -1,5 +1,6 @@ use adw::{prelude::*, subclass::prelude::*}; use gtk::glib; +use log::trace; use crate::config::PROFILE; use crate::i18n::i18n; @@ -168,6 +169,8 @@ impl ResBattery { const MAIN_GRAPH_COLOR: [u8; 3] = [0x33, 0xd1, 0x7a]; pub fn new() -> Self { + trace!("Creating ResBattery GObject…"); + glib::Object::new::() } @@ -177,6 +180,11 @@ impl ResBattery { } pub fn setup_widgets(&self, battery_data: &BatteryData) { + trace!( + "Setting up ResBattery ({:?}) widgets…", + battery_data.inner.sysfs_path + ); + let imp = self.imp(); let battery = &battery_data.inner; @@ -231,6 +239,11 @@ impl ResBattery { } pub fn refresh_page(&self, battery_data: BatteryData) { + trace!( + "Refreshing ResBattery ({:?})…", + battery_data.inner.sysfs_path + ); + let imp = self.imp(); let mut usage_string = String::new(); diff --git a/src/ui/pages/cpu.rs b/src/ui/pages/cpu.rs index 9f575883..0e1c46f2 100644 --- a/src/ui/pages/cpu.rs +++ b/src/ui/pages/cpu.rs @@ -1,6 +1,7 @@ use adw::{prelude::*, subclass::prelude::*}; use gtk::glib::{self, clone}; use gtk::FlowBoxChild; +use log::trace; use crate::config::PROFILE; use crate::i18n::{i18n, i18n_f}; @@ -8,7 +9,7 @@ use crate::ui::widgets::graph_box::ResGraphBox; use crate::utils::cpu::{CpuData, CpuInfo}; use crate::utils::settings::SETTINGS; use crate::utils::units::{convert_frequency, convert_temperature}; -use crate::utils::{cpu, FiniteOr, NUM_CPUS}; +use crate::utils::{FiniteOr, NUM_CPUS}; pub const TAB_ID: &str = "cpu"; @@ -192,6 +193,8 @@ impl ResCPU { const MAIN_GRAPH_COLOR: [u8; 3] = [0x35, 0x84, 0xe4]; pub fn new() -> Self { + trace!("Creating ResCPU GObject…"); + glib::Object::new::() } @@ -201,14 +204,31 @@ impl ResCPU { } pub fn setup_widgets(&self, cpu_info: CpuInfo) { + trace!("Setting up ResCPU widgets…"); + let imp = self.imp(); - let old_total_usage = cpu::get_cpu_usage(None).unwrap_or((0, 0)); + let logical_cpus = cpu_info.logical_cpus.unwrap_or(0); + + let CpuData { + new_thread_usages, + temperature: _, + frequencies: _, + } = CpuData::new(logical_cpus); + + let old_total_usage = new_thread_usages + .iter() + .flatten() + .copied() + .reduce(|acc, x| (acc.0 + x.0, acc.1 + x.1)) + .unwrap_or_default(); imp.old_total_usage.set(old_total_usage); - let logical_cpus = cpu_info.logical_cpus.unwrap_or(0); for i in 0..logical_cpus { - let old_thread_usage = cpu::get_cpu_usage(Some(i)).unwrap_or((0, 0)); + let old_thread_usage = new_thread_usages + .get(i) + .map(|i| *i.as_ref().unwrap_or(&(0, 0))) + .unwrap_or((0, 0)); imp.old_thread_usages.borrow_mut().push(old_thread_usage); } @@ -282,6 +302,8 @@ impl ResCPU { } pub fn setup_signals(&self) { + trace!("Setting up ResCPU signals…"); + let imp = self.imp(); imp.logical_switch.connect_active_notify(clone!( #[weak(rename_to = this)] @@ -301,8 +323,9 @@ impl ResCPU { } pub fn refresh_page(&self, cpu_data: &CpuData) { + trace!("Refreshing ResCPU…"); + let CpuData { - new_total_usage, new_thread_usages, temperature, frequencies, @@ -310,6 +333,13 @@ impl ResCPU { let imp = self.imp(); + let new_total_usage = new_thread_usages + .iter() + .flatten() + .copied() + .reduce(|acc, x| (acc.0 + x.0, acc.1 + x.1)) + .unwrap_or_default(); + let idle_total_delta = new_total_usage .0 .saturating_sub(imp.old_total_usage.get().0); @@ -331,7 +361,7 @@ impl ResCPU { let mut percentage_string = format!("{} %", percentage.round()); imp.total_cpu.set_subtitle(&percentage_string); - imp.old_total_usage.set(*new_total_usage); + imp.old_total_usage.set(new_total_usage); if imp.logical_cpus_amount.get() > 1 { for (i, old_thread_usage) in imp @@ -341,7 +371,10 @@ impl ResCPU { .enumerate() .take(imp.logical_cpus_amount.get()) { - let new_thread_usage = new_thread_usages[i]; + let new_thread_usage = new_thread_usages + .get(i) + .map(|i| *i.as_ref().unwrap_or(&(0, 0))) + .unwrap_or((0, 0)); let idle_thread_delta = new_thread_usage.0.saturating_sub(old_thread_usage.0); let sum_thread_delta = new_thread_usage.1.saturating_sub(old_thread_usage.1); let work_thread_time = sum_thread_delta.saturating_sub(idle_thread_delta); diff --git a/src/ui/pages/drive.rs b/src/ui/pages/drive.rs index e5e01aa6..0b5369eb 100644 --- a/src/ui/pages/drive.rs +++ b/src/ui/pages/drive.rs @@ -2,6 +2,7 @@ use std::time::{Duration, SystemTime}; use adw::{glib::property::PropertySet, prelude::*, subclass::prelude::*}; use gtk::glib; +use log::trace; use crate::config::PROFILE; use crate::i18n::{i18n, i18n_f}; @@ -196,6 +197,8 @@ impl ResDrive { const SECTOR_SIZE: usize = 512; pub fn new() -> Self { + trace!("Creating ResDrive GObject…"); + glib::Object::new::() } @@ -205,6 +208,11 @@ impl ResDrive { } pub fn setup_widgets(&self, drive_data: &DriveData) { + trace!( + "Setting up ResDrive ({:?}) widgets…", + drive_data.inner.sysfs_path + ); + let imp = self.imp(); let drive = &drive_data.inner; @@ -258,6 +266,8 @@ impl ResDrive { } pub fn refresh_page(&self, drive_data: DriveData) { + trace!("Refreshing ResDrive ({:?})…", drive_data.inner.sysfs_path); + let imp = self.imp(); let DriveData { diff --git a/src/ui/pages/gpu.rs b/src/ui/pages/gpu.rs index 9499d9d4..42db09a3 100644 --- a/src/ui/pages/gpu.rs +++ b/src/ui/pages/gpu.rs @@ -1,5 +1,6 @@ use adw::{prelude::*, subclass::prelude::*}; use gtk::glib::{self}; +use log::trace; use crate::config::PROFILE; use crate::i18n::{i18n, i18n_f}; @@ -181,6 +182,8 @@ impl ResGPU { const MAIN_GRAPH_COLOR: [u8; 3] = [0xed, 0x33, 0x3b]; pub fn new() -> Self { + trace!("Creating ResGPU GObject…"); + glib::Object::new::() } @@ -190,6 +193,8 @@ impl ResGPU { } pub fn setup_widgets(&self, gpu: &Gpu) { + trace!("Setting up ResGPU ({}) widgets…", gpu.gpu_identifier()); + let imp = self.imp(); let tab_id = format!("{}-{}", TAB_ID_PREFIX, &gpu.gpu_identifier()); @@ -254,6 +259,8 @@ impl ResGPU { } pub fn refresh_page(&self, gpu_data: &GpuData) { + trace!("Refreshing ResGPU ({})…", gpu_data.gpu_identifier); + let imp = self.imp(); let GpuData { diff --git a/src/ui/pages/memory.rs b/src/ui/pages/memory.rs index 9db5cccf..75bf690b 100644 --- a/src/ui/pages/memory.rs +++ b/src/ui/pages/memory.rs @@ -1,5 +1,6 @@ use adw::{prelude::*, subclass::prelude::*}; use gtk::glib::{self, clone}; +use log::trace; use crate::config::PROFILE; use crate::i18n::{i18n, i18n_f}; @@ -172,6 +173,8 @@ impl ResMemory { const MAIN_GRAPH_COLOR: [u8; 3] = [0xc5, 0x2f, 0x90]; pub fn new() -> Self { + trace!("Creating ResMemory GObject…"); + glib::Object::new::() } @@ -181,6 +184,8 @@ impl ResMemory { } pub fn setup_widgets(&self) { + trace!("Setting up ResMemory widgets…"); + let imp = self.imp(); imp.memory.set_title_label(&i18n("Memory")); @@ -268,6 +273,8 @@ impl ResMemory { } pub fn setup_signals(&self) { + trace!("Setting up ResMemory signals…"); + let imp = self.imp(); imp.authentication_banner.connect_button_clicked(clone!( @@ -285,6 +292,8 @@ impl ResMemory { } pub fn refresh_page(&self, memdata: MemoryData) { + trace!("Refreshing ResMemory…"); + let imp = self.imp(); let MemoryData { diff --git a/src/ui/pages/network.rs b/src/ui/pages/network.rs index 73a0bf1c..0c0705dd 100644 --- a/src/ui/pages/network.rs +++ b/src/ui/pages/network.rs @@ -2,6 +2,7 @@ use std::time::{Duration, SystemTime}; use adw::{glib::property::PropertySet, prelude::*, subclass::prelude::*}; use gtk::glib; +use log::trace; use crate::config::PROFILE; use crate::i18n::{i18n, i18n_f}; @@ -192,6 +193,8 @@ impl ResNetwork { const MAIN_GRAPH_COLOR: [u8; 3] = [0x25, 0x9a, 0xab]; pub fn new() -> Self { + trace!("Creating ResNetwork GObject…"); + glib::Object::new::() } @@ -201,6 +204,11 @@ impl ResNetwork { } pub fn setup_widgets(&self, network_data: &NetworkData) { + trace!( + "Setting up ResNetwork ({:?}) widgets…", + network_data.inner.sysfs_path + ); + let imp = self.imp(); let network_interface = &network_data.inner; @@ -269,6 +277,11 @@ impl ResNetwork { } pub fn refresh_page(&self, network_data: NetworkData) { + trace!( + "Refreshing ResNetwork ({:?})…", + network_data.inner.sysfs_path + ); + let NetworkData { received_bytes, sent_bytes, diff --git a/src/ui/pages/npu.rs b/src/ui/pages/npu.rs index 5a8be1d6..7b3add65 100644 --- a/src/ui/pages/npu.rs +++ b/src/ui/pages/npu.rs @@ -1,5 +1,6 @@ use adw::{prelude::*, subclass::prelude::*}; use gtk::glib::{self}; +use log::trace; use crate::config::PROFILE; use crate::i18n::{i18n, i18n_f}; @@ -172,6 +173,8 @@ impl ResNPU { const MAIN_GRAPH_COLOR: [u8; 3] = [0xb5, 0x27, 0xe3]; pub fn new() -> Self { + trace!("Creating ResNPU GObject…"); + glib::Object::new::() } @@ -181,6 +184,8 @@ impl ResNPU { } pub fn setup_widgets(&self, npu: &Npu) { + trace!("Setting up ResNPU ({}) widgets…", npu.pci_slot()); + let imp = self.imp(); let tab_id = format!("{}-{}", TAB_ID_PREFIX, &npu.pci_slot().to_string()); @@ -215,6 +220,8 @@ impl ResNPU { } pub fn refresh_page(&self, npu_data: &NpuData) { + trace!("Refreshing ResNPU ({})…", npu_data.pci_slot); + let imp = self.imp(); let NpuData { diff --git a/src/ui/pages/processes/process_entry.rs b/src/ui/pages/processes/process_entry.rs index 863613ce..fc76423c 100644 --- a/src/ui/pages/processes/process_entry.rs +++ b/src/ui/pages/processes/process_entry.rs @@ -2,6 +2,7 @@ use gtk::{ glib::{self, GString}, subclass::prelude::ObjectSubclassIsExt, }; +use log::trace; use process_data::Containerization; use crate::{ @@ -200,6 +201,8 @@ glib::wrapper! { impl ProcessEntry { pub fn new(process: &Process) -> Self { + trace!("Creating ProcessEntry GObject ({})…", process.data.pid); + let containerization = match process.data.containerization { Containerization::None => i18n("No"), Containerization::Flatpak => i18n("Yes (Flatpak)"), @@ -221,6 +224,8 @@ impl ProcessEntry { } pub fn update(&self, process: &Process) { + trace!("Refreshing ProcessEntry ({})…", process.data.pid); + self.set_cpu_usage(process.cpu_time_ratio()); self.set_memory_usage(process.data.memory_usage as u64); self.set_swap_usage(process.data.swap_usage as u64); diff --git a/src/ui/pages/processes/process_name_cell.rs b/src/ui/pages/processes/process_name_cell.rs index 724f6092..36644341 100644 --- a/src/ui/pages/processes/process_name_cell.rs +++ b/src/ui/pages/processes/process_name_cell.rs @@ -1,5 +1,6 @@ use adw::{glib::property::PropertySet, prelude::*, subclass::prelude::*}; use gtk::{gio::Icon, glib}; +use log::trace; mod imp { use std::cell::{Cell, RefCell}; @@ -153,6 +154,8 @@ impl Default for ResProcessNameCell { impl ResProcessNameCell { pub fn new() -> Self { + trace!("Creating ResProcessNameCell GObject…"); + glib::Object::new::() } } diff --git a/src/ui/widgets/double_graph_box.rs b/src/ui/widgets/double_graph_box.rs index f01caea7..f5badf43 100644 --- a/src/ui/widgets/double_graph_box.rs +++ b/src/ui/widgets/double_graph_box.rs @@ -1,5 +1,6 @@ use adw::{prelude::*, subclass::prelude::*}; use gtk::glib; +use log::trace; use crate::config::PROFILE; @@ -77,6 +78,8 @@ impl Default for ResDoubleGraphBox { impl ResDoubleGraphBox { pub fn new() -> Self { + trace!("Creating ResDoubleGraphBox GObject…"); + glib::Object::new::() } diff --git a/src/ui/widgets/graph.rs b/src/ui/widgets/graph.rs index 21dad31b..2afdce7a 100644 --- a/src/ui/widgets/graph.rs +++ b/src/ui/widgets/graph.rs @@ -1,6 +1,7 @@ use adw::prelude::WidgetExt; use gtk::glib::{self}; use gtk::subclass::prelude::*; +use log::trace; use plotters::style::RGBColor; use std::f64; @@ -152,6 +153,8 @@ impl Default for ResGraph { impl ResGraph { pub fn new() -> Self { + trace!("Creating ResGraph GObject…"); + glib::Object::new::() } diff --git a/src/ui/widgets/graph_box.rs b/src/ui/widgets/graph_box.rs index 7a476f5e..26fac686 100644 --- a/src/ui/widgets/graph_box.rs +++ b/src/ui/widgets/graph_box.rs @@ -1,5 +1,6 @@ use adw::{prelude::*, subclass::prelude::*}; use gtk::glib; +use log::trace; use crate::config::PROFILE; @@ -71,6 +72,8 @@ impl Default for ResGraphBox { impl ResGraphBox { pub fn new() -> Self { + trace!("Creating ResGraphBox GObject…"); + glib::Object::new::() } diff --git a/src/ui/widgets/stack_sidebar.rs b/src/ui/widgets/stack_sidebar.rs index 7f9b1fcd..47f92133 100644 --- a/src/ui/widgets/stack_sidebar.rs +++ b/src/ui/widgets/stack_sidebar.rs @@ -5,6 +5,7 @@ use gtk::{ glib::{self, clone, GString}, Ordering, }; +use log::trace; use std::collections::HashMap; use crate::utils::settings::{SidebarMeterType, SETTINGS}; @@ -92,6 +93,8 @@ impl Default for ResStackSidebar { impl ResStackSidebar { pub fn new() -> Self { + trace!("Creating ResStackSidebar GObject…"); + glib::Object::new::() } diff --git a/src/ui/widgets/stack_sidebar_item.rs b/src/ui/widgets/stack_sidebar_item.rs index 7148b571..5fcf2105 100644 --- a/src/ui/widgets/stack_sidebar_item.rs +++ b/src/ui/widgets/stack_sidebar_item.rs @@ -4,6 +4,7 @@ use gtk::{ glib::{self}, Ordering, }; +use log::trace; use super::graph::ResGraph; @@ -206,6 +207,8 @@ impl ResStackSidebarItem { primary_ord: u32, secondary_ord: u32, ) -> Self { + trace!("Creating ResStackSidebarItem GObject…"); + let detail = detail.unwrap_or_default(); let this: Self = glib::Object::builder() .property("name", name) diff --git a/src/ui/window.rs b/src/ui/window.rs index 6c35bca2..081fe166 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -1,13 +1,13 @@ use process_data::{Niceness, ProcessData}; use std::path::PathBuf; -use std::time::Duration; +use std::time::{Duration, Instant}; use adw::{prelude::*, subclass::prelude::*, ToolbarView}; use adw::{Toast, ToastOverlay}; use anyhow::{Context, Result}; use gtk::glib::{clone, timeout_future, GString, MainContext}; use gtk::{gio, glib, Widget}; -use log::{info, warn}; +use log::{info, trace, warn}; use crate::application::Application; use crate::config::PROFILE; @@ -59,6 +59,7 @@ mod imp { use async_channel::{unbounded, Receiver, Sender}; use gtk::CompositeTemplate; + use log::debug; use process_data::{pci_slot::PciSlot, GpuIdentifier}; #[derive(Debug, CompositeTemplate)] @@ -174,8 +175,10 @@ mod imp { impl WindowImpl for MainWindow { // Save window state on delete event fn close_request(&self) -> glib::Propagation { + debug!("Closing the application…"); + if let Err(err) = self.obj().save_window_size() { - log::warn!("Failed to save window state, {}", &err); + warn!("Failed to save window state, {}", &err); } // Pass close request on to the parent @@ -210,6 +213,8 @@ struct RefreshData { impl MainWindow { pub fn new(app: &Application) -> Self { + trace!("Creating MainWindow GObject…"); + let window = glib::Object::builder::() .property("application", app) .build(); @@ -362,6 +367,7 @@ impl MainWindow { } fn setup_widgets(&self) { + trace!("Setting up Application widgets…"); let imp = self.imp(); let gpus = Gpu::get_gpus().unwrap_or_default(); @@ -433,6 +439,10 @@ impl MainWindow { } fn gather_refresh_data(logical_cpus: usize, gpus: &[Gpu], npus: &[Npu]) -> RefreshData { + let start = Instant::now(); + + trace!("Gathering refresh data of all devices…"); + let cpu_data = if ARGS.disable_cpu_monitoring { None } else { @@ -502,7 +512,7 @@ impl MainWindow { .unwrap_or_default() }; - RefreshData { + let refresh_data = RefreshData { cpu_data, mem_data, gpu_data, @@ -514,10 +524,18 @@ impl MainWindow { battery_paths, battery_data, process_data, - } + }; + + trace!("Finished gathering refresh data in {:.2?}", start.elapsed()); + + refresh_data } fn refresh_ui(&self, refresh_data: RefreshData) { + let start = Instant::now(); + + trace!("Refreshing UI using gathered data…"); + let imp = self.imp(); let RefreshData { @@ -661,6 +679,8 @@ impl MainWindow { page.refresh_page(battery_data); } + + trace!("UI refresh done in {:.2?}", start.elapsed()); } pub async fn periodic_refresh_all(&self) { @@ -694,6 +714,8 @@ impl MainWindow { let (tx_wait, rx_wait) = std::sync::mpsc::sync_channel(1); std::thread::spawn(move || { + trace!("Spawning refresh thread"); + loop { let data = Self::gather_refresh_data(logical_cpus, &gpus, &npus); tx_data.send(data).unwrap(); @@ -706,6 +728,8 @@ impl MainWindow { let mut first_refresh = true; + trace!("Going into refresh loop"); + loop { // gather_refresh_data() let refresh_data = rx_data.recv().unwrap(); @@ -769,6 +793,8 @@ impl MainWindow { /// Create page for every drive that is shown fn refresh_drive_pages(&self, mut paths: Vec, drive_data: &[DriveData]) { + trace!("Refreshing drive pages…"); + let imp = self.imp(); let mut drive_pages = imp.drive_pages.borrow_mut(); @@ -842,6 +868,8 @@ impl MainWindow { /// Create page for every network interface that is shown fn refresh_network_pages(&self, mut paths: Vec, network_data: &[NetworkData]) { + trace!("Refreshing network pages…"); + let imp = self.imp(); let mut network_pages = imp.network_pages.borrow_mut(); @@ -914,6 +942,8 @@ impl MainWindow { /// Create page for every battery that is shown fn refresh_battery_pages(&self, paths: Vec, battery_data: &[BatteryData]) { + trace!("Refreshing battery pages…"); + let imp = self.imp(); let mut battery_pages = imp.battery_pages.borrow_mut(); @@ -1078,6 +1108,8 @@ impl MainWindow { window_title: &str, window_subtitle: &str, ) -> adw::ToolbarView { + trace!("Adding page {window_title} ({window_subtitle})…"); + let imp = self.imp(); let title_widget = adw::WindowTitle::new(window_title, window_subtitle); diff --git a/src/utils/app.rs b/src/utils/app.rs index 43aeb070..80fbc4e2 100644 --- a/src/utils/app.rs +++ b/src/utils/app.rs @@ -11,7 +11,7 @@ use gtk::{ glib::GString, }; use lazy_regex::{lazy_regex, Lazy, Regex}; -use log::{debug, info}; +use log::{debug, info, trace}; use process_data::{Containerization, GpuIdentifier, ProcessData}; use crate::i18n::i18n; @@ -234,6 +234,7 @@ impl App { pub fn from_desktop_file>(file_path: P) -> Result { let file_path = file_path.as_ref(); + trace!("Reading {file_path:?}…"); let ini = ini::Ini::load_from_file(file_path)?; @@ -249,7 +250,8 @@ impl App { // if not, presume that the ID is in the file name Some(file_path.file_stem()?.to_string_lossy().to_string()) }) - .context("unable to get ID of desktop file")?; + .context("unable to get ID of desktop file") + .inspect_err(|_| trace!("Unable to get an ID for this .desktop file"))?; if let Some(reason) = APP_ID_BLOCKLIST.get(id.as_str()) { debug!("Skipping {id} because it's blocklisted ({reason})"); @@ -760,9 +762,13 @@ impl AppsContext { /// Refreshes the statistics about the running applications and processes. pub fn refresh(&mut self, new_process_data: Vec) { + trace!("Refreshing AppsContext…"); + let start = Instant::now(); + let mut updated_processes = HashSet::new(); for mut process_data in new_process_data { + trace!("Refreshing process {}…", process_data.pid); updated_processes.insert(process_data.pid); // this is awkward: since AppsContext is the only object around that knows what GPUs have combined media @@ -772,13 +778,17 @@ impl AppsContext { .gpu_usage_stats .iter_mut() .filter(|(pci_slot, _)| self.gpus_with_combined_media_engine.contains(pci_slot)) - .for_each(|(_, stats)| { + .for_each(|(pci_slot, stats)| { + trace!("Manually adjusting GPU stats of {} for {pci_slot} due to combined media engine", process_data.pid); + stats.dec = u64::max(stats.dec, stats.enc); stats.enc = u64::max(stats.dec, stats.enc); }); // refresh our old processes if let Some(old_process) = self.processes.get_mut(&process_data.pid) { + trace!("{} has been there before, updating it", process_data.pid); + old_process.cpu_time_last = old_process .data .user_cpu_time @@ -791,6 +801,7 @@ impl AppsContext { old_process.data = process_data.clone(); } else { // this is a new process, see if it belongs to a graphical app + trace!("{} is a new process", process_data.pid); let mut new_process = Process::from_process_data(process_data); @@ -830,6 +841,13 @@ impl AppsContext { app.read_bytes_from_dead_processes += read_dead; app.write_bytes_from_dead_processes += write_dead; + if read_dead > 0 || write_dead > 0 { + trace!( + "{} has a process which died earlier, keeping I/O stats", + app.display_name + ); + } + app.processes.retain(|pid| updated_processes.contains(pid)); if !app.is_running() { @@ -841,5 +859,7 @@ impl AppsContext { // all the not-updated processes have unfortunately died, probably self.processes .retain(|pid, _| updated_processes.contains(pid)); + + trace!("AppsContext refresh done within {:.2?}", start.elapsed()); } } diff --git a/src/utils/battery.rs b/src/utils/battery.rs index cee9602a..c33288a5 100644 --- a/src/utils/battery.rs +++ b/src/utils/battery.rs @@ -7,12 +7,14 @@ use std::{ use crate::i18n::{i18n, i18n_f}; use anyhow::{bail, Context, Result}; use lazy_regex::{lazy_regex, Lazy, Regex}; +use log::trace; use super::units::convert_energy; // For (at least) Lenovo Yoga 6 13ALC7 static HEX_ENCODED_REGEX: Lazy = lazy_regex!(r"^(0x[0-9a-fA-F]{2}\s*)*$"); +#[derive(Debug)] pub struct BatteryData { pub inner: Battery, pub charge: Result, @@ -24,21 +26,32 @@ pub struct BatteryData { impl BatteryData { pub fn new>(path: P) -> Self { - let inner = Battery::from_sysfs(path.as_ref()); + let path = path.as_ref(); + + trace!("Gathering battery data for {path:?}…"); + + let inner = Battery::from_sysfs(path); let charge = inner.charge(); let power_usage = inner.power_usage(); let health = inner.health(); let state = inner.state(); let charge_cycles = inner.charge_cycles(); - Self { + let battery_data = Self { inner, charge, power_usage, health, state, charge_cycles, - } + }; + + trace!( + "Gathered battery data for {}: {battery_data:?}", + path.to_string_lossy() + ); + + battery_data } } @@ -171,6 +184,8 @@ impl Battery { pub fn from_sysfs>(sysfs_path: P) -> Battery { let sysfs_path = sysfs_path.as_ref().to_path_buf(); + trace!("Creating Battery object of {sysfs_path:?}…"); + let manufacturer = std::fs::read_to_string(sysfs_path.join("manufacturer")) .map(|s| Self::untangle_weird_encoding(s.replace('\n', ""))) .ok(); @@ -197,13 +212,17 @@ impl Battery { }) .ok(); - Battery { - sysfs_path, + let battery = Battery { + sysfs_path: sysfs_path.clone(), manufacturer, model_name, design_capacity, technology, - } + }; + + trace!("Created Battery object of {sysfs_path:?}: {battery:?}"); + + battery } // apparently some manufacturers like to for whatever reason reencode the manufacturer and model name in hex or diff --git a/src/utils/cpu.rs b/src/utils/cpu.rs index 9a26af43..1c0cd66b 100644 --- a/src/utils/cpu.rs +++ b/src/utils/cpu.rs @@ -1,12 +1,14 @@ use anyhow::{anyhow, bail, Context, Result}; use glob::glob; use lazy_regex::{lazy_regex, Lazy, Regex}; -use log::{debug, warn}; +use log::{debug, trace, warn}; use std::{ path::{Path, PathBuf}, sync::LazyLock, }; +const PROC_STAT: &str = "/proc/stat"; + const KNOWN_HWMONS: &[&str] = &["zenpower", "coretemp", "k10temp"]; const KNOWN_THERMAL_ZONES: &[&str] = &["cpu-thermal", "x86_pkg_temp", "acpitz"]; @@ -26,7 +28,7 @@ static RE_LSCPU_VIRTUALIZATION: Lazy = lazy_regex!(r"Virtualization:\s*(. static RE_LSCPU_MAX_MHZ: Lazy = lazy_regex!(r"CPU max MHz:\s*(.*)"); static RE_PROC_STAT: Lazy = lazy_regex!( - r"cpu[0-9]* *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*)" + r"cpu[0-9]+ *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*)" ); static CPU_TEMPERATURE_PATH: LazyLock> = LazyLock::new(|| { @@ -77,36 +79,36 @@ fn search_for_thermal_zones(types: &[&'static str]) -> Option<(&'static str, Pat None } +#[derive(Debug)] pub struct CpuData { - pub new_total_usage: (u64, u64), - pub new_thread_usages: Vec<(u64, u64)>, + pub new_thread_usages: Vec>, pub temperature: Result, pub frequencies: Vec>, } impl CpuData { pub fn new(logical_cpus: usize) -> Self { - let new_total_usage = get_cpu_usage(None).unwrap_or((0, 0)); + trace!("Gathering CPU data…"); + let new_thread_usages = get_cpu_usage(); let temperature = get_temperature(); let mut frequencies = Vec::with_capacity(logical_cpus); - let mut new_thread_usages = Vec::with_capacity(logical_cpus); for i in 0..logical_cpus { - let smth = get_cpu_usage(Some(i)).unwrap_or((0, 0)); - new_thread_usages.push(smth); - let freq = get_cpu_freq(i); frequencies.push(freq.ok()); } - Self { - new_total_usage, + let cpu_data = Self { new_thread_usages, temperature, frequencies, - } + }; + + trace!("Gathered CPU data: {cpu_data:?}"); + + cpu_data } } @@ -218,31 +220,36 @@ impl CpuInfo { /// Will return `Err` if the are problems during reading or parsing /// of the corresponding file in sysfs pub fn get_cpu_freq(core: usize) -> Result { + trace!("Finding CPU frequency for core {core}…"); + std::fs::read_to_string(format!( "/sys/devices/system/cpu/cpu{core}/cpufreq/scaling_cur_freq" )) + .inspect_err(|err| trace!("Unable to get CPU frequency for core {core}: {err}")) .with_context(|| format!("unable to read scaling_cur_freq for core {core}"))? .replace('\n', "") .parse::() .context("can't parse scaling_cur_freq to usize") .map(|x| x * 1000) + .inspect(|freq| trace!("Frequency of core {core}: {freq} Hz")) } fn parse_proc_stat_line>(line: S) -> Result<(u64, u64)> { let captures = RE_PROC_STAT .captures(line.as_ref()) - .ok_or_else(|| anyhow!("using regex to parse /proc/stat failed"))?; - let idle_time = captures + .context("using regex to parse /proc/stat failed")?; + + let idle = captures .name("idle") .and_then(|x| x.as_str().parse::().ok()) - .ok_or_else(|| anyhow!("unable to get idle time"))? - .saturating_add( - captures - .name("iowait") - .and_then(|x| x.as_str().parse::().ok()) - .ok_or_else(|| anyhow!("unable to get iowait time"))?, - ); - let sum = captures + .context("unable to get idle time")?; + + let iowait = captures + .name("iowait") + .and_then(|x| x.as_str().parse::().ok()) + .context("unable to get idle time")?; + + let total = captures .iter() .skip(1) .flat_map(|cap| { @@ -250,22 +257,19 @@ fn parse_proc_stat_line>(line: S) -> Result<(u64, u64)> { .ok_or_else(|| anyhow!("unable to sum CPU times from /proc/stat")) }) .sum(); - Ok((idle_time, sum)) + + Ok((idle.saturating_add(iowait), total)) } -fn get_proc_stat(core: Option) -> Result { - // the combined stats are in line 0, the other cores are in the following lines, - // since our `core` argument starts with 0, we must add 1 to it if it's not `None`. - let selected_line_number = core.map_or(0, |x| x + 1); - let proc_stat_raw = - std::fs::read_to_string("/proc/stat").context("unable to read /proc/stat")?; - let mut proc_stat = proc_stat_raw.split('\n').collect::>(); - proc_stat.retain(|x| x.starts_with("cpu")); - // return an `Error` if `core` is greater than the number of cores - if selected_line_number >= proc_stat.len() { - bail!("`core` argument greater than amount of cores") - } - Ok(proc_stat[selected_line_number].to_string()) +fn parse_proc_stat>(stat: S) -> Vec> { + trace!("Parsing {PROC_STAT}…"); + + stat.as_ref() + .lines() + .skip(1) + .filter(|line| line.starts_with("cpu")) + .map(|line| parse_proc_stat_line(line)) + .collect() } /// Returns the CPU usage of either all cores combined (if supplied argument is `None`), @@ -277,8 +281,14 @@ fn get_proc_stat(core: Option) -> Result { /// /// Will return `Err` if the are problems during reading or parsing /// of /proc/stat -pub fn get_cpu_usage(core: Option) -> Result<(u64, u64)> { - parse_proc_stat_line(get_proc_stat(core)?) +pub fn get_cpu_usage() -> Vec> { + trace!("Reading {PROC_STAT}…"); + + let raw = std::fs::read_to_string("/proc/stat") + .context("unable to read /proc/stat") + .unwrap_or_default(); + + parse_proc_stat(raw) } /// Returns the CPU temperature. diff --git a/src/utils/drive.rs b/src/utils/drive.rs index f2d96542..96103e3e 100644 --- a/src/utils/drive.rs +++ b/src/utils/drive.rs @@ -1,6 +1,7 @@ use anyhow::{Context, Result}; use gtk::gio::{Icon, ThemedIcon}; use lazy_regex::{lazy_regex, Lazy, Regex}; +use log::trace; use std::{ collections::HashMap, fmt::Display, @@ -11,6 +12,8 @@ use crate::i18n::{i18n, i18n_f}; use super::units::convert_storage; +const PATH_SYSFS: &str = "/sys/block"; + static RE_DRIVE: Lazy = lazy_regex!( r" *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*) *(?P[0-9]*)" ); @@ -26,7 +29,11 @@ pub struct DriveData { } impl DriveData { - pub fn new(path: &Path) -> Self { + pub fn new>(path: P) -> Self { + let path = path.as_ref(); + + trace!("Gathering drive data for {path:?}…"); + let inner = Drive::from_sysfs(path); let is_virtual = inner.is_virtual(); let writable = inner.writable(); @@ -34,14 +41,21 @@ impl DriveData { let disk_stats = inner.sys_stats().unwrap_or_default(); let capacity = inner.capacity(); - Self { + let drive_data = Self { inner, is_virtual, writable, removable, disk_stats, capacity, - } + }; + + trace!( + "Gathered drive data for {}: {drive_data:?}", + path.to_string_lossy() + ); + + drive_data } } @@ -112,6 +126,9 @@ impl Drive { /// reading or parsing pub fn from_sysfs>(sysfs_path: P) -> Drive { let path = sysfs_path.as_ref().to_path_buf(); + + trace!("Creating Drive object of {path:?}"); + let block_device = path .file_name() .expect("sysfs path ends with \"..\"?") @@ -119,10 +136,13 @@ impl Drive { .to_string(); let mut drive = Self::default(); - drive.sysfs_path = path; + drive.sysfs_path = path.clone(); drive.block_device = block_device; drive.model = drive.model().ok().map(|model| model.trim().to_string()); drive.drive_type = drive.drive_type().unwrap_or_default(); + + trace!("Created Drive object of {path:?}: {drive:?}"); + drive } @@ -134,10 +154,12 @@ impl Drive { /// reading or parsing pub fn get_sysfs_paths() -> Result> { let mut list = Vec::new(); - let entries = std::fs::read_dir("/sys/block")?; + trace!("Finding entries in {PATH_SYSFS}"); + let entries = std::fs::read_dir(PATH_SYSFS)?; for entry in entries { let entry = entry?; let block_device = entry.file_name().to_string_lossy().to_string(); + trace!("Found block device {block_device}"); if block_device.is_empty() { continue; } diff --git a/src/utils/gpu/amd.rs b/src/utils/gpu/amd.rs index 9cf850b0..3fa2135f 100644 --- a/src/utils/gpu/amd.rs +++ b/src/utils/gpu/amd.rs @@ -1,6 +1,6 @@ use anyhow::{bail, Result}; use lazy_regex::{lazy_regex, Lazy, Regex}; -use log::{debug, warn}; +use log::{debug, trace, warn}; use process_data::GpuIdentifier; use std::{collections::HashMap, path::PathBuf, sync::LazyLock, time::Instant}; @@ -79,6 +79,7 @@ impl AmdGpu { let device_id = u16::from_str_radix(device_id.as_str().trim(), 16).unwrap(); let revision = u8::from_str_radix(revision.as_str().trim(), 16).unwrap(); let name = name.as_str().into(); + trace!("Found {name} ({device_id:04x}, rev {revision:02x})"); map.insert((device_id, revision), name); } } diff --git a/src/utils/gpu/mod.rs b/src/utils/gpu/mod.rs index 4ffd01bc..82af12b6 100644 --- a/src/utils/gpu/mod.rs +++ b/src/utils/gpu/mod.rs @@ -6,7 +6,7 @@ mod v3d; use anyhow::{bail, Context, Result}; use lazy_regex::{lazy_regex, Lazy, Regex}; -use log::{debug, info}; +use log::{debug, info, trace}; use process_data::{pci_slot::PciSlot, GpuIdentifier}; use v3d::V3dGpu; @@ -26,9 +26,9 @@ use self::{amd::AmdGpu, intel::IntelGpu, nvidia::NvidiaGpu, other::OtherGpu}; use super::pci::Vendor; -pub const VID_AMD: u16 = 4098; -pub const VID_INTEL: u16 = 32902; -pub const VID_NVIDIA: u16 = 4318; +pub const VID_AMD: u16 = 0x1002; +pub const VID_INTEL: u16 = 0x8086; +pub const VID_NVIDIA: u16 = 0x10DE; const RE_CARD_ENUMARATOR: Lazy = lazy_regex!(r"(\d+)\/?$"); @@ -61,6 +61,8 @@ impl GpuData { pub fn new(gpu: &Gpu) -> Self { let gpu_identifier = gpu.gpu_identifier(); + trace!("Gathering GPU data for {}…", gpu_identifier); + let usage_fraction = gpu.usage().map(|usage| usage.clamp(0.0, 1.0)).ok(); let encode_fraction = gpu.encode_usage().map(|usage| usage.clamp(0.0, 1.0)).ok(); @@ -81,7 +83,7 @@ impl GpuData { let nvidia = matches!(gpu, Gpu::Nvidia(_)); - Self { + let gpu_data = Self { gpu_identifier, usage_fraction, encode_fraction, @@ -95,7 +97,11 @@ impl GpuData { power_cap, power_cap_max, nvidia, - } + }; + + trace!("Gathered GPU data for {}: {gpu_data:?}", gpu_identifier); + + gpu_data } } @@ -137,6 +143,7 @@ pub trait GpuImpl { fn read_sysfs_int + std::marker::Send>(&self, file: P) -> Result { let path = self.sysfs_path().join(file); + trace!("Reading {path:?}…"); std::fs::read_to_string(&path)? .replace('\n', "") .parse::() @@ -145,6 +152,7 @@ pub trait GpuImpl { fn read_device_file + std::marker::Send>(&self, file: P) -> Result { let path = self.sysfs_path().join("device").join(file); + trace!("Reading {path:?}…"); Ok(std::fs::read_to_string(path)?.replace('\n', "")) } @@ -157,6 +165,7 @@ pub trait GpuImpl { fn read_hwmon_int + std::marker::Send>(&self, file: P) -> Result { let path = self.first_hwmon().context("no hwmon found")?.join(file); + trace!("Reading {path:?}…"); std::fs::read_to_string(&path)? .replace('\n', "") .parse::() @@ -234,6 +243,9 @@ impl Gpu { fn from_sysfs_path>(path: P, i: usize) -> Result { let path = path.as_ref().to_path_buf(); + + trace!("Creating GPU object of {path:?}…"); + let enumarator = RE_CARD_ENUMARATOR .captures(&path.to_string_lossy()) .and_then(|captures| captures.get(1)) @@ -292,7 +304,7 @@ impl Gpu { device, gpu_identifier, driver, - path, + path.to_path_buf(), hwmon_vec.first().cloned(), )), "AMD", @@ -303,7 +315,7 @@ impl Gpu { device, gpu_identifier, driver, - path, + path.to_path_buf(), hwmon_vec.first().cloned(), )), "Intel", @@ -314,7 +326,7 @@ impl Gpu { device, gpu_identifier, driver, - path, + path.to_path_buf(), hwmon_vec.first().cloned(), )), "NVIDIA", @@ -325,7 +337,7 @@ impl Gpu { device, gpu_identifier, driver, - path, + path.to_path_buf(), hwmon_vec.first().cloned(), )), "v3d", @@ -336,7 +348,7 @@ impl Gpu { device, gpu_identifier, driver, - path, + path.to_path_buf(), hwmon_vec.first().cloned(), )), "Other", @@ -349,6 +361,8 @@ impl Gpu { gpu.gpu_identifier(), ); + trace!("Created GPU object of {path:?}: {gpu:?}"); + Ok(gpu) } diff --git a/src/utils/memory.rs b/src/utils/memory.rs index ab126760..130d11fd 100644 --- a/src/utils/memory.rs +++ b/src/utils/memory.rs @@ -2,10 +2,12 @@ use std::process::Command; use anyhow::{bail, Context, Result}; use lazy_regex::{lazy_regex, Lazy, Regex}; -use log::debug; +use log::{debug, trace}; use super::{FLATPAK_APP_PATH, FLATPAK_SPAWN, IS_FLATPAK}; +const PROC_MEMINFO: &str = "/proc/meminfo"; + const TEMPLATE_RE_PRESENT: &str = r"MEMORY_DEVICE_%_PRESENT=(\d)"; const TEMPLATE_RE_CONFIGURED_SPEED_MTS: &str = r"MEMORY_DEVICE_%_CONFIGURED_SPEED_MTS=(\d*)"; @@ -54,8 +56,12 @@ pub struct MemoryData { impl MemoryData { pub fn new() -> Result { - let proc_mem = - std::fs::read_to_string("/proc/meminfo").context("unable to read /proc/meminfo")?; + trace!("Gathering memory data…"); + + trace!("Reading {PROC_MEMINFO}…"); + let proc_mem = std::fs::read_to_string("/proc/meminfo") + .inspect_err(|err| trace!("Unable to read {PROC_MEMINFO}: {err}")) + .context("unable to read /proc/meminfo")?; let total_mem = RE_MEM_TOTAL .captures(&proc_mem) @@ -121,12 +127,16 @@ impl MemoryData { }) })?; - Ok(Self { + let memory_data = Self { total_mem, available_mem, total_swap, free_swap, - }) + }; + + trace!("Gathered memory data: {memory_data:?}"); + + Ok(memory_data) } } @@ -142,6 +152,7 @@ pub struct MemoryDevice { impl MemoryDevice { fn parse_dmidecode>(dmi: S) -> Vec { + trace!("Parsing dmidecode output…"); let mut devices = Vec::new(); let device_strings = dmi.as_ref().split("\n\n"); @@ -150,6 +161,7 @@ impl MemoryDevice { if device_string.is_empty() { continue; } + let memory_device = Self { speed_mts: RE_CONFIGURED_SPEED .captures(device_string) @@ -171,6 +183,8 @@ impl MemoryDevice { .is_some(), }; + trace!("Found memory device: {:?}", memory_device); + devices.push(memory_device); } @@ -179,6 +193,7 @@ impl MemoryDevice { fn virtual_dmi() -> Vec { let command = if *IS_FLATPAK { + trace!("Executing udevadm outside Flatpak's sandbox…"); Command::new(FLATPAK_SPAWN) .args([ "--host", @@ -189,6 +204,7 @@ impl MemoryDevice { ]) .output() } else { + trace!("Executing udevadm…"); Command::new("udevadm") .args(["info", "-p", "/sys/devices/virtual/dmi/id"]) .output() @@ -206,6 +222,7 @@ impl MemoryDevice { } fn parse_virtual_dmi>(dmi: S) -> Vec { + trace!("Parsing udevadm output…"); let dmi = dmi.as_ref(); let devices_amount: usize = RE_NUM_MEMORY_DEVICES @@ -266,14 +283,18 @@ impl MemoryDevice { .and_then(|captures| captures.get(1)) .and_then(|capture| capture.as_str().parse().ok()); - devices.push(Self { + let memory_device = Self { speed_mts: speed, form_factor, r#type, type_detail, size, installed, - }); + }; + + trace!("Found memory device: {:?}", memory_device); + + devices.push(memory_device); } devices diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 9b6a37cb..2969f37f 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, path::Path, sync::LazyLock}; use anyhow::{Context, Result}; use gtk::glib::DateTime; use ini::Ini; -use log::debug; +use log::{debug, trace}; use process_data::unix_as_millis; pub mod app; @@ -52,6 +52,7 @@ pub static NUM_CPUS: LazyLock = LazyLock::new(num_cpus::get); // Adapted from Mission Center: https://gitlab.com/mission-center-devs/mission-center/ pub static IS_FLATPAK: LazyLock = LazyLock::new(|| { + trace!("Determining whether /.flatpak-info exists…"); let is_flatpak = std::path::Path::new("/.flatpak-info").exists(); if is_flatpak { @@ -98,6 +99,10 @@ pub fn read_uevent_contents>(contents: S) -> Result>(uevent_path: P) -> Result> { + trace!( + "Reading uevent contents of {}", + uevent_path.as_ref().to_string_lossy() + ); read_uevent_contents(std::fs::read_to_string(uevent_path)?) } diff --git a/src/utils/network.rs b/src/utils/network.rs index c80c8d71..9159ac68 100644 --- a/src/utils/network.rs +++ b/src/utils/network.rs @@ -6,11 +6,14 @@ use std::{ use anyhow::{Context, Result}; use gtk::gio::{Icon, ThemedIcon}; +use log::trace; use crate::i18n::i18n; use super::{pci::Device, read_uevent}; +const PATH_SYSFS: &str = "/sys/class/net"; + // this is a list because we don't look for exact matches but for if the device name starts with a certain string const INTERFACE_TYPE_MAP: &[(&str, InterfaceType)] = &[ ("bn", InterfaceType::Bluetooth), @@ -40,20 +43,31 @@ pub struct NetworkData { } impl NetworkData { - pub fn new(path: &Path) -> Self { + pub fn new>(path: P) -> Self { + let path = path.as_ref(); + + trace!("Gathering network data for {path:?}…"); + let inner = NetworkInterface::from_sysfs(path); let is_virtual = inner.is_virtual(); let received_bytes = inner.received_bytes(); let sent_bytes = inner.sent_bytes(); let display_name = inner.display_name(); - Self { + let network_data = Self { inner, is_virtual, received_bytes, sent_bytes, display_name, - } + }; + + trace!( + "Gathered network data for {}: {network_data:?}", + path.to_string_lossy() + ); + + network_data } } @@ -136,11 +150,16 @@ impl PartialEq for NetworkInterface { impl NetworkInterface { pub fn get_sysfs_paths() -> Result> { let mut list = Vec::new(); - let entries = std::fs::read_dir("/sys/class/net")?; + + trace!("Finding entries in {PATH_SYSFS}"); + + let entries = std::fs::read_dir(PATH_SYSFS)?; for entry in entries { let entry = entry?; let block_device = entry.file_name().to_string_lossy().to_string(); + trace!("Found block device {block_device}"); if block_device.starts_with("lo") { + trace!("Skipping loopback interface {block_device}"); continue; } list.push(entry.path()); @@ -157,6 +176,8 @@ impl NetworkInterface { /// been passed or if there has been problems parsing /// information pub fn from_sysfs(sysfs_path: &Path) -> NetworkInterface { + trace!("Creating NetworkInterface object of {sysfs_path:?}…"); + let dev_uevent = read_uevent(sysfs_path.join("device/uevent")).unwrap_or_default(); let interface_name = sysfs_path @@ -188,10 +209,14 @@ impl NetworkInterface { .map(|x| x.replace('\n', "")) .ok(); - NetworkInterface { + let interface_type = InterfaceType::from_interface_name(interface_name.to_string_lossy()); + + let driver = dev_uevent.get("DRIVER"); + + let network_interface = NetworkInterface { interface_name: interface_name.clone(), - driver_name: dev_uevent.get("DRIVER").cloned(), - interface_type: InterfaceType::from_interface_name(interface_name.to_string_lossy()), + driver_name: driver.cloned(), + interface_type, speed, device, device_label, @@ -199,7 +224,11 @@ impl NetworkInterface { sysfs_path: sysfs_path.to_path_buf(), received_bytes_path: sysfs_path.join(PathBuf::from("statistics/rx_bytes")), sent_bytes_path: sysfs_path.join(PathBuf::from("statistics/tx_bytes")), - } + }; + + trace!("Created NetworkInterface object of {sysfs_path:?}: {network_interface:?}"); + + network_interface } /// Returns a display name for this Network Interface. diff --git a/src/utils/npu/mod.rs b/src/utils/npu/mod.rs index 97e80f55..a263fd87 100644 --- a/src/utils/npu/mod.rs +++ b/src/utils/npu/mod.rs @@ -2,7 +2,7 @@ mod intel; mod other; use anyhow::{bail, Context, Result}; -use log::{debug, info}; +use log::{debug, info, trace}; use process_data::pci_slot::PciSlot; use std::{ @@ -46,6 +46,8 @@ impl NpuData { pub fn new(npu: &Npu) -> Self { let pci_slot = npu.pci_slot(); + trace!("Gathering NPU data for {}…", pci_slot); + let usage_fraction = npu.usage().ok(); let total_memory = npu.total_vram().ok(); @@ -60,7 +62,7 @@ impl NpuData { let power_cap = npu.power_cap().ok(); let power_cap_max = npu.power_cap_max().ok(); - Self { + let npu_data = Self { pci_slot, usage_fraction, total_memory, @@ -71,7 +73,11 @@ impl NpuData { power_usage, power_cap, power_cap_max, - } + }; + + trace!("Gathered NPU data for {}: {npu_data:?}", pci_slot); + + npu_data } } @@ -107,6 +113,7 @@ pub trait NpuImpl { fn read_sysfs_int + std::marker::Send>(&self, file: P) -> Result { let path = self.sysfs_path().join(file); + trace!("Reading {path:?}…"); std::fs::read_to_string(&path)? .replace('\n', "") .parse::() @@ -115,11 +122,13 @@ pub trait NpuImpl { fn read_device_file + std::marker::Send>(&self, file: P) -> Result { let path = self.sysfs_path().join("device").join(file); + trace!("Reading {path:?}…"); Ok(std::fs::read_to_string(path)?.replace('\n', "")) } fn read_device_int + std::marker::Send>(&self, file: P) -> Result { let path = self.sysfs_path().join("device").join(file); + trace!("Reading {path:?}…"); self.read_device_file(&path)? .parse::() .with_context(|| format!("error parsing file {}", &path.to_string_lossy())) @@ -127,6 +136,7 @@ pub trait NpuImpl { fn read_hwmon_int + std::marker::Send>(&self, file: P) -> Result { let path = self.first_hwmon().context("no hwmon found")?.join(file); + trace!("Reading {path:?}…"); std::fs::read_to_string(&path)? .replace('\n', "") .parse::() @@ -203,7 +213,11 @@ impl Npu { } fn from_sysfs_path>(path: P) -> Result { - let sysfs_device_path = path.as_ref().join("device"); + let path = path.as_ref(); + + trace!("Creating NPU object of {path:?}…"); + + let sysfs_device_path = path.join("device"); let uevent_contents = read_uevent(sysfs_device_path.join("uevent"))?; let (device, vid, pid) = if let Some(pci_line) = uevent_contents.get("PCI_ID") { @@ -243,15 +257,13 @@ impl Npu { bail!("this is a simple framebuffer"); } - let path = path.as_ref().to_path_buf(); - let (npu, npu_category) = if vid == VID_INTEL || driver == "intel_vpu" { ( Npu::Intel(IntelNpu::new( device, pci_slot, driver, - path, + path.to_path_buf(), hwmon_vec.first().cloned(), )), "Intel", @@ -262,7 +274,7 @@ impl Npu { device, pci_slot, driver, - path, + path.to_path_buf(), hwmon_vec.first().cloned(), )), "Other", @@ -275,6 +287,8 @@ impl Npu { npu.pci_slot(), ); + trace!("Created NPU object of {path:?}: {npu:?}"); + Ok(npu) } diff --git a/src/utils/os.rs b/src/utils/os.rs index 213d29df..a9b74b55 100644 --- a/src/utils/os.rs +++ b/src/utils/os.rs @@ -1,4 +1,5 @@ use lazy_regex::{lazy_regex, Lazy, Regex}; +use log::trace; use super::IS_FLATPAK; @@ -21,6 +22,8 @@ impl OsInfo { PATH_OS_RELEASE }; + trace!("Path for the os-release file is determined to be `{os_path}`"); + let name = RE_PRETTY_NAME .captures(&std::fs::read_to_string(os_path).unwrap_or_default()) .and_then(|captures| captures.get(1)) diff --git a/src/utils/pci.rs b/src/utils/pci.rs index 4490be3b..a9fb935d 100644 --- a/src/utils/pci.rs +++ b/src/utils/pci.rs @@ -1,7 +1,10 @@ use std::{collections::BTreeMap, io::BufRead, sync::LazyLock, time::Instant}; use anyhow::{Context, Result}; -use log::{debug, info, warn}; +use log::{debug, info, trace, warn}; + +const PATH_PCI_IDS: &str = "/usr/share/hwdata/pci.ids"; +const PATH_PCI_IDS_FLATPAK: &str = "/run/host/usr/share/hwdata/pci.ids"; static VENDORS: LazyLock> = LazyLock::new(|| { init() @@ -16,7 +19,7 @@ pub struct Subdevice { name: String, } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq)] pub struct Device { id: u16, vendor_id: u16, @@ -24,13 +27,23 @@ pub struct Device { sub_devices: Vec, } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq)] pub struct Vendor { id: u16, name: String, devices: BTreeMap, } +impl std::fmt::Debug for Device { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Device") + .field("id", &self.id) + .field("vendor_id", &self.vendor_id) + .field("name", &self.name) + .finish() + } +} + impl Device { pub fn subdevices(&'static self) -> impl Iterator { self.sub_devices.iter() @@ -55,6 +68,15 @@ impl Device { } } +impl std::fmt::Debug for Vendor { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Vendor") + .field("id", &self.id) + .field("name", &self.name) + .finish() + } +} + impl Vendor { pub fn from_vid(vid: u16) -> Option<&'static Vendor> { VENDORS.get(&vid) @@ -80,11 +102,13 @@ impl Vendor { fn parse_pci_ids(reader: R) -> Result> { let mut seen: BTreeMap = BTreeMap::new(); - for line in reader.lines().map_while(Result::ok) { + for (number, line) in reader.lines().map_while(Result::ok).enumerate() { if line.starts_with('C') { // case 1: we've reached the classes, time to stop + trace!("Line {}: Classes reached, parsing done", number + 1); break; } else if line.starts_with('#') || line.is_empty() { + trace!("Line {}: Empty line or comment", number + 1); // case 2: we're seeing a comment, don't care // case 3: we're seeing an empty line, also don't care continue; @@ -117,6 +141,8 @@ fn parse_pci_ids(reader: R) -> Result> { name, }; + trace!("Line {}: New subdevice found: {subdevice:?}", number + 1); + seen.values_mut() .last() .and_then(|vendor| vendor.devices.values_mut().last()) @@ -151,6 +177,8 @@ fn parse_pci_ids(reader: R) -> Result> { sub_devices: Vec::new(), }; + trace!("Line {}: New device found: {device:?}", number + 1); + seen.values_mut() .last() .with_context(|| format!("no preceding device (line: {line})"))? @@ -178,6 +206,8 @@ fn parse_pci_ids(reader: R) -> Result> { devices: BTreeMap::new(), }; + trace!("Line {}: New vendor found: {vendor:?}", number + 1); + seen.insert(vid, vendor); } } @@ -194,11 +224,13 @@ fn init() -> Result> { // // if that doesn't work, we're either not on flatpak or we're not allowed to see the host's pci.ids for some reason, // so try to either access flatpak's own (probably older) pci.ids or the host's if we're not on flatpak - let file = std::fs::File::open("/run/host/usr/share/hwdata/pci.ids") - .or_else(|_| std::fs::File::open("/usr/share/hwdata/pci.ids"))?; + let file = + std::fs::File::open(PATH_PCI_IDS_FLATPAK).or_else(|_| std::fs::File::open(PATH_PCI_IDS))?; + trace!("pci.ids file opened"); let reader = std::io::BufReader::new(file); + trace!("Calling parse_pci_ids()"); let map = parse_pci_ids(reader)?; let vendors_count = map.len(); diff --git a/src/utils/process.rs b/src/utils/process.rs index 6d409be5..83cc865c 100644 --- a/src/utils/process.rs +++ b/src/utils/process.rs @@ -1,6 +1,6 @@ use anyhow::{bail, Context, Result}; use config::LIBEXECDIR; -use log::{debug, error, info}; +use log::{debug, error, info, trace}; use process_data::{GpuIdentifier, GpuUsageStats, Niceness, ProcessData}; use std::{ collections::BTreeMap, @@ -8,6 +8,7 @@ use std::{ io::{Read, Write}, process::{ChildStdin, ChildStdout, Command, Stdio}, sync::{LazyLock, Mutex}, + time::Instant, }; use strum_macros::Display; @@ -22,7 +23,7 @@ use super::{ boot_time, FiniteOr, FLATPAK_APP_PATH, FLATPAK_SPAWN, IS_FLATPAK, NUM_CPUS, TICK_RATE, }; -static OTHER_PROCESS: LazyLock> = LazyLock::new(|| { +static COMPANION_PROCESS: LazyLock> = LazyLock::new(|| { let proxy_path = if *IS_FLATPAK { format!( "{}/libexec/resources/resources-processes", @@ -89,24 +90,43 @@ impl Process { /// Will return `Err` if there are problems traversing and /// parsing procfs pub fn all_data() -> Result> { + trace!("all_data() called"); + + let start = Instant::now(); let output = { - let mut process = OTHER_PROCESS.lock().unwrap(); + trace!("Acquiring companion process lock"); + let mut process = COMPANION_PROCESS.lock().unwrap(); + trace!("Writing b\"\\n\" into companion process stdin"); let _ = process.0.write_all(b"\n"); + trace!("Flushing"); let _ = process.0.flush(); let mut len_bytes = [0_u8; (usize::BITS / 8) as usize]; + trace!("Reading companion process output length as little-endian"); process.1.read_exact(&mut len_bytes)?; let len = usize::from_le_bytes(len_bytes); + trace!("Companion process output is {len} bytes long"); let mut output_bytes = vec![0; len]; + trace!("Reading companion process output"); process.1.read_exact(&mut output_bytes)?; output_bytes }; - Ok(rmp_serde::from_slice(&output)?) + let elapsed = start.elapsed(); + trace!("Companion process was done in {elapsed:.2?}"); + + trace!("Parsing companion process output"); + let parsed = + rmp_serde::from_slice(&output).context("unable to decode companion process output"); + + let elapsed = start.elapsed(); + trace!("all_data() done in {elapsed:.2?}"); + + parsed } pub fn from_process_data(process_data: ProcessData) -> Self { @@ -249,17 +269,19 @@ impl Process { format!("{LIBEXECDIR}/resources-adjust") }; - let adjust_string = affinity + let affinity_string = affinity .into_iter() .map(|b| if b { '1' } else { '0' }) .collect::(); + debug!("Trying to adjust with niceness = {niceness} and affinity = {affinity_string}"); + let result = Self::maybe_pkexec_command( adjust_path, [ self.data.pid.to_string(), niceness.to_string(), - adjust_string, + affinity_string, ], ); diff --git a/src/utils/settings.rs b/src/utils/settings.rs index 427312ea..a3e41faa 100644 --- a/src/utils/settings.rs +++ b/src/utils/settings.rs @@ -3,6 +3,7 @@ use std::{ops::Deref, str::FromStr, sync::LazyLock}; use adw::prelude::*; use gtk::{gio, glib, SortType}; +use log::debug; use strum_macros::{Display, EnumString, FromRepr}; use paste::paste; @@ -20,6 +21,7 @@ macro_rules! bool_settings { paste! { pub fn [](&self, value: bool) -> Result<(), glib::error::BoolError> { + debug!("Setting boolean {} to {}", stringify!($setting_name).replace("_", "-"), value); self.set_boolean(&stringify!($setting_name).replace("_", "-"), value) } @@ -45,6 +47,7 @@ macro_rules! int_settings { paste! { pub fn [](&self, value: i32) -> Result<(), glib::error::BoolError> { + debug!("Setting int {} to {}", stringify!($setting_name).replace("_", "-"), value); self.set_int(&stringify!($setting_name).replace("_", "-"), value) } @@ -70,6 +73,7 @@ macro_rules! uint_settings { paste! { pub fn [](&self, value: u32) -> Result<(), glib::error::BoolError> { + debug!("Setting uint {} to {}", stringify!($setting_name).replace("_", "-"), value); self.set_uint(&stringify!($setting_name).replace("_", "-"), value) } @@ -155,6 +159,7 @@ impl Settings { &self, value: TemperatureUnit, ) -> Result<(), glib::error::BoolError> { + debug!("Setting temperature-unit to {}", value); self.set_string("temperature-unit", &value.to_string()) } @@ -175,6 +180,7 @@ impl Settings { } pub fn set_base(&self, value: Base) -> Result<(), glib::error::BoolError> { + debug!("Setting base to {}", value); self.set_string("base", &value.to_string()) } @@ -192,6 +198,7 @@ impl Settings { &self, value: S, ) -> Result<(), glib::error::BoolError> { + debug!("Setting last-viewed-page to {}", value.as_ref()); self.set_string("last-viewed-page", value.as_ref()) } @@ -206,6 +213,7 @@ impl Settings { } pub fn set_refresh_speed(&self, value: RefreshSpeed) -> Result<(), glib::error::BoolError> { + debug!("Setting refresh-speed to {}", value); self.set_string("refresh-speed", &value.to_string()) } @@ -229,6 +237,7 @@ impl Settings { &self, value: SidebarMeterType, ) -> Result<(), glib::error::BoolError> { + debug!("Setting sidebar-meter-type to {}", value); self.set_string("sidebar-meter-type", &value.to_string()) } @@ -251,6 +260,7 @@ impl Settings { } pub fn set_maximized(&self, value: bool) -> Result<(), glib::error::BoolError> { + debug!("Setting boolean is-maximized to {}", value); self.set_boolean("is-maximized", value) } @@ -272,10 +282,9 @@ impl Settings { &self, value: SortType, ) -> Result<(), glib::error::BoolError> { - self.set_boolean( - "processes-sort-by-ascending", - matches!(value, SortType::Ascending), - ) + let setting = matches!(value, SortType::Ascending); + debug!("Setting boolean processes-sort-by-ascending to {}", setting); + self.set_boolean("processes-sort-by-ascending", setting) } pub fn connect_processes_sort_by_ascending( @@ -308,10 +317,9 @@ impl Settings { &self, value: SortType, ) -> Result<(), glib::error::BoolError> { - self.set_boolean( - "apps-sort-by-ascending", - matches!(value, SortType::Ascending), - ) + let setting = matches!(value, SortType::Ascending); + debug!("Setting boolean apps-sort-by-ascending to {}", setting); + self.set_boolean("apps-sort-by-ascending", setting) } pub fn connect_apps_sort_by_ascending(