other: if in a non-D0 state, short-circuit further logic (#1355)

* other: if in a non-D0 state, short-circuit further logic

* cleanup

* add back an empty name and value

* fix for macos/windows

* some testing things
This commit is contained in:
Clement Tsang 2023-12-20 01:36:08 -05:00 committed by GitHub
parent 004c83728d
commit a67da93c5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 119 additions and 73 deletions

View File

@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Bug Fixes ### Bug Fixes
- [#1314](https://github.com/ClementTsang/bottom/pull/1314): Fix fat32 mounts not showing up in macOS. - [#1314](https://github.com/ClementTsang/bottom/pull/1314): Fix fat32 mounts not showing up in macOS.
- [#1355](https://github.com/ClementTsang/bottom/pull/1355): Reduce chances of non-D0 devices waking up due to temperature checks on Linux.
## [0.9.6] - 2023-08-26 ## [0.9.6] - 2023-08-26

View File

@ -54,7 +54,7 @@ pub fn get_nvidia_vecs(
temp_vec.push(TempHarvest { temp_vec.push(TempHarvest {
name: name.clone(), name: name.clone(),
temperature, temperature: Some(temperature),
}); });
} }
} }

View File

@ -18,7 +18,7 @@ use crate::app::Filter;
#[derive(Default, Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct TempHarvest { pub struct TempHarvest {
pub name: String, pub name: String,
pub temperature: f32, pub temperature: Option<f32>,
} }
#[derive(Clone, Debug, Copy, PartialEq, Eq, Default)] #[derive(Clone, Debug, Copy, PartialEq, Eq, Default)]

View File

@ -9,7 +9,7 @@ use anyhow::Result;
use hashbrown::{HashMap, HashSet}; use hashbrown::{HashMap, HashSet};
use super::{is_temp_filtered, TempHarvest, TemperatureType}; use super::{is_temp_filtered, TempHarvest, TemperatureType};
use crate::app::Filter; use crate::{app::Filter, utils::error::BottomError};
const EMPTY_NAME: &str = "Unknown"; const EMPTY_NAME: &str = "Unknown";
@ -24,7 +24,7 @@ fn read_temp(path: &Path) -> Result<f32> {
Ok(fs::read_to_string(path)? Ok(fs::read_to_string(path)?
.trim_end() .trim_end()
.parse::<f32>() .parse::<f32>()
.map_err(|e| crate::utils::error::BottomError::ConversionError(e.to_string()))? .map_err(|e| BottomError::ConversionError(e.to_string()))?
/ 1_000.0) / 1_000.0)
} }
@ -131,8 +131,8 @@ fn finalize_name(
None => label, None => label,
}, },
(Some(name), None) => name, (Some(name), None) => name,
(None, None) => match &fallback_sensor_name { (None, None) => match fallback_sensor_name {
Some(sensor_name) => sensor_name.clone(), Some(sensor_name) => sensor_name.to_owned(),
None => EMPTY_NAME.to_string(), None => EMPTY_NAME.to_string(),
}, },
}; };
@ -140,6 +140,31 @@ fn finalize_name(
counted_name(seen_names, candidate_name) counted_name(seen_names, candidate_name)
} }
/// Whether the temperature should *actually* be read during enumeration.
/// Will return false if the state is not D0/unknown, or if it does not support `device/power_state`.
#[inline]
fn is_device_awake(path: &Path) -> bool {
// Whether the temperature should *actually* be read during enumeration.
// Set to false if the device is in ACPI D3cold.
// Documented at https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-power_state
let device = path.join("device");
let power_state = device.join("power_state");
if power_state.exists() {
if let Ok(state) = fs::read_to_string(power_state) {
let state = state.trim();
// The zenpower3 kernel module (incorrectly?) reports "unknown", causing this check
// to fail and temperatures to appear as zero instead of having the file not exist.
//
// Their self-hosted git instance has disabled sign up, so this bug cant be reported either.
state == "D0" || state == "unknown"
} else {
true
}
} else {
true
}
}
/// Get temperature sensors from the linux sysfs interface `/sys/class/hwmon` and /// Get temperature sensors from the linux sysfs interface `/sys/class/hwmon` and
/// `/sys/devices/platform/coretemp.*`. It returns all found temperature sensors, and the number /// `/sys/devices/platform/coretemp.*`. It returns all found temperature sensors, and the number
/// of checked hwmon directories (not coretemp directories). /// of checked hwmon directories (not coretemp directories).
@ -178,29 +203,15 @@ fn hwmon_temperatures(temp_type: &TemperatureType, filter: &Option<Filter>) -> H
for file_path in dirs { for file_path in dirs {
let sensor_name = read_to_string_lossy(file_path.join("name")); let sensor_name = read_to_string_lossy(file_path.join("name"));
// Whether the temperature should *actually* be read during enumeration. if !is_device_awake(&file_path) {
// Set to false if the device is in ACPI D3cold. if let Some(sensor_name) = sensor_name {
// temperatures.push(TempHarvest {
// If it is false, then the temperature will be set to 0.0 later down the line. name: sensor_name,
let should_read_temp = { temperature: None,
// Documented at https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-power_state });
let device = file_path.join("device");
let power_state = device.join("power_state");
if power_state.exists() {
if let Ok(state) = fs::read_to_string(power_state) {
let state = state.trim();
// The zenpower3 kernel module (incorrectly?) reports "unknown", causing this check
// to fail and temperatures to appear as zero instead of having the file not exist.
//
// Their self-hosted git instance has disabled sign up, so this bug cant be reported either.
state == "D0" || state == "unknown"
} else {
true
} }
} else { continue;
true
} }
};
if let Ok(dir_entries) = file_path.read_dir() { if let Ok(dir_entries) = file_path.read_dir() {
// Enumerate the devices temperature sensors // Enumerate the devices temperature sensors
@ -272,19 +283,15 @@ fn hwmon_temperatures(temp_type: &TemperatureType, filter: &Option<Filter>) -> H
let name = finalize_name(hwmon_name, sensor_label, &sensor_name, &mut seen_names); let name = finalize_name(hwmon_name, sensor_label, &sensor_name, &mut seen_names);
if is_temp_filtered(filter, &name) { if is_temp_filtered(filter, &name) {
let temp_celsius = if should_read_temp { let temp_celsius = if let Ok(temp) = read_temp(&temp_path) {
if let Ok(temp) = read_temp(&temp_path) {
temp temp
} else { } else {
continue; continue;
}
} else {
0.0
}; };
temperatures.push(TempHarvest { temperatures.push(TempHarvest {
name, name,
temperature: temp_type.convert_temp_unit(temp_celsius), temperature: Some(temp_type.convert_temp_unit(temp_celsius)),
}); });
} }
} }
@ -329,7 +336,7 @@ fn add_thermal_zone_temperatures(
temperatures.push(TempHarvest { temperatures.push(TempHarvest {
name, name,
temperature: temp_type.convert_temp_unit(temp_celsius), temperature: Some(temp_type.convert_temp_unit(temp_celsius)),
}); });
} }
} }

View File

@ -19,7 +19,7 @@ pub fn get_temperature_data(
if is_temp_filtered(filter, &name) { if is_temp_filtered(filter, &name) {
temperature_vec.push(TempHarvest { temperature_vec.push(TempHarvest {
name, name,
temperature: temp_type.convert_temp_unit(component.temperature()), temperature: Some(temp_type.convert_temp_unit(component.temperature())),
}); });
} }
} }
@ -36,11 +36,11 @@ pub fn get_temperature_data(
if let Some(temp) = temp.as_temperature() { if let Some(temp) = temp.as_temperature() {
temperature_vec.push(TempHarvest { temperature_vec.push(TempHarvest {
name, name,
temperature: match temp_type { temperature: Some(match temp_type {
TemperatureType::Celsius => temp.celsius(), TemperatureType::Celsius => temp.celsius(),
TemperatureType::Kelvin => temp.kelvin(), TemperatureType::Kelvin => temp.kelvin(),
TemperatureType::Fahrenheit => temp.fahrenheit(), TemperatureType::Fahrenheit => temp.fahrenheit(),
}, }),
}); });
} }
} }

View File

@ -21,10 +21,14 @@ use crossterm::{
use tui::{backend::CrosstermBackend, Terminal}; use tui::{backend::CrosstermBackend, Terminal};
use bottom::{ use bottom::{
args,
canvas::{self, canvas_styling::CanvasStyling}, canvas::{self, canvas_styling::CanvasStyling},
check_if_terminal, cleanup_terminal, create_collection_thread, create_input_thread,
create_or_get_config,
data_conversion::*, data_conversion::*,
handle_key_event_or_break, handle_mouse_event,
options::*, options::*,
*, panic_hook, read_config, try_drawing, update_data, BottomEvent,
}; };
// Used for heap allocation debugging purposes. // Used for heap allocation debugging purposes.
@ -38,7 +42,10 @@ fn main() -> Result<()> {
#[cfg(feature = "logging")] #[cfg(feature = "logging")]
{ {
if let Err(err) = init_logger(log::LevelFilter::Debug, std::ffi::OsStr::new("debug.log")) { if let Err(err) = bottom::init_logger(
log::LevelFilter::Debug,
Some(std::ffi::OsStr::new("debug.log")),
) {
println!("Issue initializing logger: {err}"); println!("Issue initializing logger: {err}");
} }
} }

View File

@ -132,7 +132,7 @@ impl ConvertedData {
data.temp_harvest.iter().for_each(|temp_harvest| { data.temp_harvest.iter().for_each(|temp_harvest| {
self.temp_data.push(TempWidgetData { self.temp_data.push(TempWidgetData {
sensor: KString::from_ref(&temp_harvest.name), sensor: KString::from_ref(&temp_harvest.name),
temperature_value: temp_harvest.temperature.ceil() as u64, temperature_value: temp_harvest.temperature.map(|temp| temp.ceil() as u64),
temperature_type, temperature_type,
}); });
}); });

View File

@ -20,9 +20,9 @@ pub static OFFSET: once_cell::sync::Lazy<time::UtcOffset> = once_cell::sync::Laz
#[cfg(feature = "logging")] #[cfg(feature = "logging")]
pub fn init_logger( pub fn init_logger(
min_level: log::LevelFilter, debug_file_name: &std::ffi::OsStr, min_level: log::LevelFilter, debug_file_name: Option<&std::ffi::OsStr>,
) -> Result<(), fern::InitError> { ) -> Result<(), fern::InitError> {
fern::Dispatch::new() let dispatch = fern::Dispatch::new()
.format(|out, message, record| { .format(|out, message, record| {
let offset_time = { let offset_time = {
let utc = time::OffsetDateTime::now_utc(); let utc = time::OffsetDateTime::now_utc();
@ -43,25 +43,19 @@ pub fn init_logger(
message message
)) ))
}) })
.level(min_level) .level(min_level);
.chain(fern::log_file(debug_file_name)?)
.apply()?; if let Some(debug_file_name) = debug_file_name {
dispatch.chain(fern::log_file(debug_file_name)?).apply()?;
} else {
dispatch.chain(std::io::stdout()).apply()?;
}
Ok(()) Ok(())
} }
#[macro_export] #[macro_export]
macro_rules! c_debug { macro_rules! error {
($($x:tt)*) => {
#[cfg(feature = "logging")]
{
log::debug!($($x)*)
}
};
}
#[macro_export]
macro_rules! c_error {
($($x:tt)*) => { ($($x:tt)*) => {
#[cfg(feature = "logging")] #[cfg(feature = "logging")]
{ {
@ -71,7 +65,17 @@ macro_rules! c_error {
} }
#[macro_export] #[macro_export]
macro_rules! c_info { macro_rules! warn {
($($x:tt)*) => {
#[cfg(feature = "logging")]
{
log::warn!($($x)*)
}
};
}
#[macro_export]
macro_rules! info {
($($x:tt)*) => { ($($x:tt)*) => {
#[cfg(feature = "logging")] #[cfg(feature = "logging")]
{ {
@ -81,17 +85,17 @@ macro_rules! c_info {
} }
#[macro_export] #[macro_export]
macro_rules! c_log { macro_rules! debug {
($($x:tt)*) => { ($($x:tt)*) => {
#[cfg(feature = "logging")] #[cfg(feature = "logging")]
{ {
log::log!($($x)*) log::debug!($($x)*)
} }
}; };
} }
#[macro_export] #[macro_export]
macro_rules! c_trace { macro_rules! trace {
($($x:tt)*) => { ($($x:tt)*) => {
#[cfg(feature = "logging")] #[cfg(feature = "logging")]
{ {
@ -101,11 +105,34 @@ macro_rules! c_trace {
} }
#[macro_export] #[macro_export]
macro_rules! c_warn { macro_rules! log {
($($x:tt)*) => { ($($x:tt)*) => {
#[cfg(feature = "logging")] #[cfg(feature = "logging")]
{ {
log::warn!($($x)*) log::log!(log::Level::Trace, $($x)*)
}
};
($level:expr, $($x:tt)*) => {
#[cfg(feature = "logging")]
{
log::log!($level, $($x)*)
} }
}; };
} }
#[cfg(test)]
mod test {
#[cfg(feature = "logging")]
#[test]
fn test_logging_macros() {
super::init_logger(log::LevelFilter::Trace, None)
.expect("initializing the logger should succeed");
error!("This is an error.");
warn!("This is a warning.");
info!("This is an info.");
debug!("This is a debug.");
info!("This is a trace.");
}
}

View File

@ -17,7 +17,7 @@ use crate::{
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct TempWidgetData { pub struct TempWidgetData {
pub sensor: KString, pub sensor: KString,
pub temperature_value: u64, pub temperature_value: Option<u64>,
pub temperature_type: TemperatureType, pub temperature_type: TemperatureType,
} }
@ -37,13 +37,17 @@ impl ColumnHeader for TempWidgetColumn {
impl TempWidgetData { impl TempWidgetData {
pub fn temperature(&self) -> KString { pub fn temperature(&self) -> KString {
let temp_val = self.temperature_value.to_string(); match self.temperature_value {
Some(temp_val) => {
let temp_type = match self.temperature_type { let temp_type = match self.temperature_type {
TemperatureType::Celsius => "°C", TemperatureType::Celsius => "°C",
TemperatureType::Kelvin => "K", TemperatureType::Kelvin => "K",
TemperatureType::Fahrenheit => "°F", TemperatureType::Fahrenheit => "°F",
}; };
concat_string!(temp_val, temp_type).into() concat_string!(temp_val.to_string(), temp_type).into()
}
None => "N/A".to_string().into(),
}
} }
} }