Make SystemInfo a Resource (#12584)

# Objective

We already collect a lot of system information on startup when possible
but we don't make this information available. With the upcoming work on
a diagnostic overlay it would be useful to be able to display this
information.

## Solution

Make the already existing SystemInfo a Resource

---

## Changelog

Added `SystemInfo` Resource

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Afonso Lage <lage.afonso@gmail.com>
This commit is contained in:
IceSentry 2024-03-23 02:16:02 -04:00 committed by GitHub
parent 34c8778bf0
commit 85b488b73d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 42 deletions

View File

@ -19,7 +19,7 @@ pub use entity_count_diagnostics_plugin::EntityCountDiagnosticsPlugin;
pub use frame_time_diagnostics_plugin::FrameTimeDiagnosticsPlugin; pub use frame_time_diagnostics_plugin::FrameTimeDiagnosticsPlugin;
pub use log_diagnostics_plugin::LogDiagnosticsPlugin; pub use log_diagnostics_plugin::LogDiagnosticsPlugin;
#[cfg(feature = "sysinfo_plugin")] #[cfg(feature = "sysinfo_plugin")]
pub use system_information_diagnostics_plugin::SystemInformationDiagnosticsPlugin; pub use system_information_diagnostics_plugin::{SystemInfo, SystemInformationDiagnosticsPlugin};
use bevy_app::prelude::*; use bevy_app::prelude::*;
@ -28,12 +28,11 @@ use bevy_app::prelude::*;
pub struct DiagnosticsPlugin; pub struct DiagnosticsPlugin;
impl Plugin for DiagnosticsPlugin { impl Plugin for DiagnosticsPlugin {
fn build(&self, _app: &mut App) { fn build(&self, app: &mut App) {
app.init_resource::<DiagnosticsStore>();
#[cfg(feature = "sysinfo_plugin")] #[cfg(feature = "sysinfo_plugin")]
_app.init_resource::<DiagnosticsStore>().add_systems( app.init_resource::<system_information_diagnostics_plugin::SystemInfo>();
Startup,
system_information_diagnostics_plugin::internal::log_system_info,
);
} }
} }

View File

@ -1,5 +1,6 @@
use crate::DiagnosticPath; use crate::DiagnosticPath;
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_ecs::system::Resource;
/// Adds a System Information Diagnostic, specifically `cpu_usage` (in %) and `mem_usage` (in %) /// Adds a System Information Diagnostic, specifically `cpu_usage` (in %) and `mem_usage` (in %)
/// ///
@ -24,10 +25,27 @@ impl Plugin for SystemInformationDiagnosticsPlugin {
} }
impl SystemInformationDiagnosticsPlugin { impl SystemInformationDiagnosticsPlugin {
/// Total system cpu usage in %
pub const CPU_USAGE: DiagnosticPath = DiagnosticPath::const_new("system/cpu_usage"); pub const CPU_USAGE: DiagnosticPath = DiagnosticPath::const_new("system/cpu_usage");
/// Total system memory usage in %
pub const MEM_USAGE: DiagnosticPath = DiagnosticPath::const_new("system/mem_usage"); pub const MEM_USAGE: DiagnosticPath = DiagnosticPath::const_new("system/mem_usage");
} }
/// A resource that stores diagnostic information about the system.
/// This information can be useful for debugging and profiling purposes.
///
/// # See also
///
/// [`SystemInformationDiagnosticsPlugin`] for more information.
#[derive(Debug, Resource)]
pub struct SystemInfo {
pub os: String,
pub kernel: String,
pub cpu: String,
pub core_count: String,
pub memory: String,
}
// NOTE: sysinfo fails to compile when using bevy dynamic or on iOS and does nothing on wasm // NOTE: sysinfo fails to compile when using bevy dynamic or on iOS and does nothing on wasm
#[cfg(all( #[cfg(all(
any( any(
@ -45,7 +63,7 @@ pub mod internal {
use crate::{Diagnostic, Diagnostics, DiagnosticsStore}; use crate::{Diagnostic, Diagnostics, DiagnosticsStore};
use super::SystemInformationDiagnosticsPlugin; use super::{SystemInfo, SystemInformationDiagnosticsPlugin};
const BYTES_TO_GIB: f64 = 1.0 / 1024.0 / 1024.0 / 1024.0; const BYTES_TO_GIB: f64 = 1.0 / 1024.0 / 1024.0 / 1024.0;
@ -87,41 +105,33 @@ pub mod internal {
}); });
} }
#[derive(Debug)] impl Default for SystemInfo {
// This is required because the Debug trait doesn't detect it's used when it's only used in a print :( fn default() -> Self {
#[allow(dead_code)] let sys = System::new_with_specifics(
struct SystemInfo { RefreshKind::new()
os: String, .with_cpu(CpuRefreshKind::new())
kernel: String, .with_memory(MemoryRefreshKind::new().with_ram()),
cpu: String, );
core_count: String,
memory: String,
}
pub(crate) fn log_system_info() { let system_info = SystemInfo {
let sys = System::new_with_specifics( os: System::long_os_version().unwrap_or_else(|| String::from("not available")),
RefreshKind::new() kernel: System::kernel_version().unwrap_or_else(|| String::from("not available")),
.with_cpu(CpuRefreshKind::new()) cpu: sys
.with_memory(MemoryRefreshKind::new().with_ram()), .cpus()
); .first()
.map(|cpu| cpu.brand().trim().to_string())
.unwrap_or_else(|| String::from("not available")),
core_count: sys
.physical_core_count()
.map(|x| x.to_string())
.unwrap_or_else(|| String::from("not available")),
// Convert from Bytes to GibiBytes since it's probably what people expect most of the time
memory: format!("{:.1} GiB", sys.total_memory() as f64 * BYTES_TO_GIB),
};
let info = SystemInfo { info!("{:?}", system_info);
os: System::long_os_version().unwrap_or_else(|| String::from("not available")), system_info
kernel: System::kernel_version().unwrap_or_else(|| String::from("not available")), }
cpu: sys
.cpus()
.first()
.map(|cpu| cpu.brand().trim().to_string())
.unwrap_or_else(|| String::from("not available")),
core_count: sys
.physical_core_count()
.map(|x| x.to_string())
.unwrap_or_else(|| String::from("not available")),
// Convert from Bytes to GibiBytes since it's probably what people expect most of the time
memory: format!("{:.1} GiB", sys.total_memory() as f64 * BYTES_TO_GIB),
};
info!("{:?}", info);
} }
} }
@ -143,7 +153,16 @@ pub mod internal {
// no-op // no-op
} }
pub(crate) fn log_system_info() { impl Default for super::SystemInfo {
// no-op fn default() -> Self {
let unknown = "Unknown".to_string();
Self {
os: unknown.clone(),
kernel: unknown.clone(),
cpu: unknown.clone(),
core_count: unknown.clone(),
memory: unknown.clone(),
}
}
} }
} }