windows stuff

This commit is contained in:
Robin Appelman 2023-05-18 17:23:50 +02:00
commit 0bb314e5d3
14 changed files with 602 additions and 102 deletions

253
Cargo.lock generated
View file

@ -28,6 +28,15 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -114,6 +123,12 @@ dependencies = [
"serde_with", "serde_with",
] ]
[[package]]
name = "bumpalo"
version = "3.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.4.3" version = "1.4.3"
@ -138,6 +153,19 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
dependencies = [
"iana-time-zone",
"num-integer",
"num-traits",
"serde",
"winapi 0.3.9",
]
[[package]] [[package]]
name = "color-eyre" name = "color-eyre"
version = "0.6.2" version = "0.6.2"
@ -390,6 +418,21 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "futures"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.28" version = "0.3.28"
@ -406,6 +449,23 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
[[package]]
name = "futures-executor"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]] [[package]]
name = "futures-macro" name = "futures-macro"
version = "0.3.28" version = "0.3.28"
@ -435,10 +495,13 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
dependencies = [ dependencies = [
"futures-channel",
"futures-core", "futures-core",
"futures-io",
"futures-macro", "futures-macro",
"futures-sink", "futures-sink",
"futures-task", "futures-task",
"memchr",
"pin-project-lite", "pin-project-lite",
"pin-utils", "pin-utils",
"slab", "slab",
@ -624,6 +687,29 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678" checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678"
[[package]]
name = "iana-time-zone"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "ident_case" name = "ident_case"
version = "1.0.1" version = "1.0.1"
@ -672,6 +758,15 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "js-sys"
version = "0.3.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790"
dependencies = [
"wasm-bindgen",
]
[[package]] [[package]]
name = "kernel32-sys" name = "kernel32-sys"
version = "0.2.2" version = "0.2.2"
@ -690,9 +785,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.142" version = "0.2.144"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
[[package]] [[package]]
name = "libloading" name = "libloading"
@ -871,6 +966,25 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.15.0" version = "1.15.0"
@ -919,6 +1033,16 @@ version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "os-thread-local"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd7fc7fa9ea7dc8907f9b10e730106ed0011926e7f5abb382530ac91d1af2b7c"
dependencies = [
"libc",
"winapi 0.3.9",
]
[[package]] [[package]]
name = "overload" name = "overload"
version = "0.1.1" version = "0.1.1"
@ -948,7 +1072,9 @@ dependencies = [
"libmdns", "libmdns",
"nvml-wrapper", "nvml-wrapper",
"once_cell", "once_cell",
"os-thread-local",
"regex", "regex",
"serde",
"sysconf", "sysconf",
"sysinfo", "sysinfo",
"thiserror", "thiserror",
@ -956,6 +1082,9 @@ dependencies = [
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
"warp", "warp",
"winapi 0.3.9",
"winreg",
"wmi",
] ]
[[package]] [[package]]
@ -1122,18 +1251,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.160" version = "1.0.163"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.160" version = "1.0.163"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1625,6 +1754,60 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.15",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.2.8" version = "0.2.8"
@ -1659,6 +1842,39 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [
"windows-implement",
"windows-interface",
"windows-targets 0.48.0",
]
[[package]]
name = "windows-implement"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e2ee588991b9e7e6c8338edf3333fbe4da35dc72092643958ebb43f0ab2c49c"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "windows-interface"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6fb8df20c9bcaa8ad6ab513f7b40104840c8867d5751126e4df3b08388d0cc7"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.45.0" version = "0.45.0"
@ -1791,6 +2007,31 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winreg"
version = "0.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
dependencies = [
"cfg-if",
"serde",
"windows-sys 0.48.0",
]
[[package]]
name = "wmi"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6dbd3e812d0a4be60879f3f10b14527c1b6f2b34400696ad30dd334833c7ab1"
dependencies = [
"chrono",
"futures",
"log",
"serde",
"thiserror",
"windows",
]
[[package]] [[package]]
name = "wrapcenum-derive" name = "wrapcenum-derive"
version = "0.4.0" version = "0.4.0"

View file

@ -24,7 +24,14 @@ nvml-wrapper = "0.8.0"
if-addrs = "0.7.0" if-addrs = "0.7.0"
sysconf = "0.3.4" sysconf = "0.3.4"
thiserror = "1.0.40" thiserror = "1.0.40"
sysinfo = { version = "0.29.0", optional = true }
[target.'cfg(windows)'.dependencies]
serde = { version = "1.0.163", features = ["derive"] }
sysinfo = { version = "0.29.0" }
winapi = { version = "0.3.9", features = ["sysinfoapi", "processthreadsapi", "powerbase", "minwindef", "winnt", "winbase", "winerror", "impl-default"] }
wmi = { version = "0.13.0" }
winreg = { version = "0.50.0", features = ["serialization-serde"] }
os-thread-local = "0.1.3"
[dev-dependencies] [dev-dependencies]
iai = "0.1.1" iai = "0.1.1"

View file

@ -60,7 +60,7 @@
mingw_w64_cc mingw_w64_cc
]; ];
depsBuildBuild = [ pkgs.wine64 ]; depsBuildBuild = [ pkgs.wine64 ];
# buildInputs = [ windows.pthreads ]; buildInputs = [ windows.pthreads ];
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = "${mingw_w64_cc.targetPrefix}cc"; CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = "${mingw_w64_cc.targetPrefix}cc";
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUNNER = "wine64"; CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUNNER = "wine64";

View file

@ -1,5 +1,6 @@
use crate::SensorData; use crate::SensorData;
use std::array::IntoIter; use std::array::IntoIter;
use std::borrow::Cow;
use std::fmt::Write; use std::fmt::Write;
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
@ -115,7 +116,7 @@ impl SensorData for NetStats {
} }
pub struct GpuUsage { pub struct GpuUsage {
pub system: &'static str, pub system: Cow<'static, str>,
pub usage: u32, pub usage: u32,
} }
@ -129,3 +130,55 @@ impl GpuUsage {
.ok(); .ok();
} }
} }
#[derive(Debug, Clone, Default)]
pub struct DiskStats {
pub interface: String,
pub bytes_sent: u64,
pub bytes_received: u64,
}
impl SensorData for DiskStats {
fn write<W: Write>(&self, mut w: W, hostname: &str) {
if self.bytes_received > 0 || self.bytes_sent > 0 {
writeln!(
&mut w,
"disk_sent{{host=\"{}\", disk=\"{}\"}} {}",
hostname, self.interface, self.bytes_sent
)
.ok();
writeln!(
&mut w,
"disk_received{{host=\"{}\", disk=\"{}\"}} {}",
hostname, self.interface, self.bytes_received
)
.ok();
}
}
}
#[derive(Clone, Debug)]
pub struct DiskUsage {
pub name: String,
pub size: u64,
pub free: u64,
}
impl SensorData for DiskUsage {
fn write<W: Write>(&self, mut w: W, hostname: &str) {
if self.size > 0 {
writeln!(
&mut w,
"disk_size{{host=\"{}\", disk=\"{}\"}} {}",
hostname, self.name, self.size
)
.ok();
writeln!(
&mut w,
"disk_free{{host=\"{}\", disk=\"{}\"}} {}",
hostname, self.name, self.free
)
.ok();
}
}
}

View file

@ -7,20 +7,22 @@ use std::string::FromUtf8Error;
pub mod data; pub mod data;
pub mod docker; pub mod docker;
#[cfg(not(feature = "sysinfo"))] #[cfg(not(target_os = "windows"))]
mod linux; mod linux;
#[cfg(feature = "sysinfo")] #[cfg(target_os = "windows")]
mod sys; pub mod win;
#[cfg(not(feature = "sysinfo"))] #[cfg(not(target_os = "windows"))]
pub use linux::{get_metrics, Sensors}; pub use linux::{get_metrics, Sensors};
#[cfg(feature = "sysinfo")] #[cfg(target_os = "windows")]
pub use sys::{get_metrics, Sensors}; pub use win::{get_metrics, Sensors};
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum Error { pub enum Error {
#[error(transparent)] #[error(transparent)]
Io(#[from] std::io::Error), Io(#[from] std::io::Error),
#[error("{1}: {0}")]
Os(std::io::Error, &'static str),
#[error("{0}")] #[error("{0}")]
Other(String), Other(String),
#[error("Non UTF8 hostname")] #[error("Non UTF8 hostname")]
@ -35,6 +37,19 @@ pub enum Error {
InvalidCStringData(#[from] NulError), InvalidCStringData(#[from] NulError),
#[error("Failed to query vfs stats")] #[error("Failed to query vfs stats")]
StatVfs, StatVfs,
#[cfg(target_os = "windows")]
#[error(transparent)]
Wmi(#[from] wmi::WMIError),
#[cfg(target_os = "windows")]
#[error("{0}")]
Reg(String),
}
impl Error {
pub fn last_os_error(context: &'static str) -> Error {
let err = std::io::Error::last_os_error();
Error::Os(err, context)
}
} }
impl From<FromUtf8Error> for Error { impl From<FromUtf8Error> for Error {

View file

@ -1,3 +1,4 @@
use crate::data::{DiskStats, DiskUsage};
use crate::{Error, MultiSensorSource, Result, SensorData}; use crate::{Error, MultiSensorSource, Result, SensorData};
use ahash::{AHashSet, AHasher}; use ahash::{AHashSet, AHasher};
use regex::Regex; use regex::Regex;
@ -10,32 +11,6 @@ use std::mem::MaybeUninit;
pub mod zfs; pub mod zfs;
#[derive(Debug, Clone, Default)]
pub struct DiskStats {
pub interface: String,
pub bytes_sent: u64,
pub bytes_received: u64,
}
impl SensorData for DiskStats {
fn write<W: Write>(&self, mut w: W, hostname: &str) {
if self.bytes_received > 0 || self.bytes_sent > 0 {
writeln!(
&mut w,
"disk_sent{{host=\"{}\", disk=\"{}\"}} {}",
hostname, self.interface, self.bytes_sent
)
.ok();
writeln!(
&mut w,
"disk_received{{host=\"{}\", disk=\"{}\"}} {}",
hostname, self.interface, self.bytes_received
)
.ok();
}
}
}
pub struct DiskStatSource { pub struct DiskStatSource {
source: File, source: File,
buff: String, buff: String,
@ -100,32 +75,6 @@ impl Iterator for DiskStatParser<'_> {
} }
} }
#[derive(Clone, Debug)]
pub struct DiskUsage {
pub name: String,
pub size: u64,
pub free: u64,
}
impl SensorData for DiskUsage {
fn write<W: Write>(&self, mut w: W, hostname: &str) {
if self.size > 0 {
writeln!(
&mut w,
"disk_size{{host=\"{}\", disk=\"{}\"}} {}",
hostname, self.name, self.size
)
.ok();
writeln!(
&mut w,
"disk_free{{host=\"{}\", disk=\"{}\"}} {}",
hostname, self.name, self.free
)
.ok();
}
}
}
pub struct DiskUsageSource { pub struct DiskUsageSource {
source: File, source: File,
buff: String, buff: String,

View file

@ -1,5 +1,6 @@
use crate::data::{GpuMemory, GpuUsage}; use crate::data::{GpuMemory, GpuUsage};
use crate::linux::hwmon::FileSource; use crate::linux::hwmon::FileSource;
use std::borrow::Cow;
use std::fs::read_to_string; use std::fs::read_to_string;
use std::str::FromStr; use std::str::FromStr;
use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::atomic::{AtomicU64, Ordering};
@ -41,7 +42,7 @@ pub fn utilization() -> impl Iterator<Item = GpuUsage> {
]; ];
let drm = sources.into_iter().flat_map(|(system, usage)| { let drm = sources.into_iter().flat_map(|(system, usage)| {
Some(GpuUsage { Some(GpuUsage {
system, system: Cow::Borrowed(system),
usage: usage?, usage: usage?,
}) })
}); });

View file

@ -2,6 +2,7 @@ use crate::data::{GpuMemory, GpuUsage};
use nvml_wrapper::enum_wrappers::device::TemperatureSensor; use nvml_wrapper::enum_wrappers::device::TemperatureSensor;
use nvml_wrapper::{Device, Nvml}; use nvml_wrapper::{Device, Nvml};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::borrow::Cow;
static NVIDIA: Lazy<Option<Nvml>> = Lazy::new(|| Nvml::init().ok()); static NVIDIA: Lazy<Option<Nvml>> = Lazy::new(|| Nvml::init().ok());
@ -49,7 +50,7 @@ pub fn utilization() -> impl Iterator<Item = GpuUsage> {
}; };
sources.into_iter().flat_map(|(system, usage)| { sources.into_iter().flat_map(|(system, usage)| {
Some(GpuUsage { Some(GpuUsage {
system, system: Cow::Borrowed(system),
usage: usage?, usage: usage?,
}) })
}) })

View file

@ -1,33 +0,0 @@
use crate::data::Temperatures;
use crate::hostname;
use crate::Result;
use std::fmt::Write;
use sysinfo::{ComponentExt, System, SystemExt};
pub struct Sensors {
pub hostname: String,
}
impl Sensors {
pub fn new() -> Result<Sensors> {
let s = System::new_all();
for component in s.components() {
println!("{} :{}°C", component.label(), component.temperature());
}
Ok(Sensors {
hostname: hostname()?,
})
}
}
fn temps() -> Temperatures {
Temperatures { cpu: 0.0, gpu: 0.0 }
}
pub fn get_metrics(sensors: &Sensors) -> Result<String> {
let hostname = &sensors.hostname;
let mut result = String::with_capacity(256);
Ok(result)
}

59
src/win/cpu.rs Normal file
View file

@ -0,0 +1,59 @@
use crate::data::CpuTime;
use crate::{Error, Result, SensorSource};
use winapi::shared::minwindef;
use winapi::um::{processthreadsapi, winbase, winnt};
pub struct CpuTimeSource {
cpu_count: f32,
}
impl CpuTimeSource {
pub fn new() -> Result<CpuTimeSource> {
Ok(CpuTimeSource {
cpu_count: dbg!(cpu_count()?),
})
}
}
impl SensorSource for CpuTimeSource {
type Data = CpuTime;
fn read(&mut self) -> Result<Self::Data> {
let mut user = minwindef::FILETIME::default();
let mut kernel = minwindef::FILETIME::default();
let mut idle = minwindef::FILETIME::default();
let result =
unsafe { processthreadsapi::GetSystemTimes(&mut idle, &mut kernel, &mut user) };
if result == 0 {
Err(Error::last_os_error("GetSystemTimes"))
} else {
let user = time_to_float(user);
let idle = time_to_float(idle);
// Same as `psutil` subtracting idle time
// and leaving only busy kernel time
let system = time_to_float(kernel) - idle;
Ok(CpuTime((user + system) / self.cpu_count))
}
}
}
fn time_to_float(time: minwindef::FILETIME) -> f32 {
const HI_T: f64 = 429.496_729_6;
const LO_T: f64 = 1e-7;
let low = LO_T * f64::from(time.dwLowDateTime);
HI_T.mul_add(f64::from(time.dwHighDateTime), low) as f32
}
fn cpu_count() -> Result<f32> {
let result = unsafe { winbase::GetActiveProcessorCount(winnt::ALL_PROCESSOR_GROUPS) };
if result > 0 {
Ok(result as f32)
} else {
Err(Error::last_os_error("GetActiveProcessorCount"))
}
}

0
src/win/disk.rs Normal file
View file

101
src/win/mod.rs Normal file
View file

@ -0,0 +1,101 @@
mod cpu;
mod disk;
mod reg;
mod wmi;
use self::cpu::CpuTimeSource;
use crate::data::{DiskUsage, GpuMemory, GpuUsage, Memory, NetStats};
use crate::win::wmi::WmiSensor;
use crate::Result;
use crate::{hostname, SensorData, SensorSource};
use once_cell::sync::Lazy;
use os_thread_local::ThreadLocal;
use std::borrow::Cow;
use std::sync::Mutex;
use sysinfo::{ComponentExt, DiskExt, NetworkExt, System, SystemExt};
pub struct Sensors {
pub hostname: String,
pub system: Mutex<System>,
cpu: Mutex<CpuTimeSource>,
gpu_mem_total: u64,
}
static WMI: Lazy<ThreadLocal<WmiSensor>> =
Lazy::new(|| ThreadLocal::new(|| WmiSensor::new().expect("failed to init wmi")));
impl Sensors {
pub fn new() -> Result<Sensors> {
let mut system = System::new_all();
system.refresh_all();
println!("{:?}", system);
for component in system.components() {
println!("{} :{}°C", component.label(), component.temperature());
}
let gpu_mem_total = reg::total_gpu_memory()?;
Ok(Sensors {
hostname: hostname()?,
system: Mutex::new(system),
cpu: Mutex::new(CpuTimeSource::new()?),
gpu_mem_total,
})
}
}
pub fn get_metrics(sensors: &Sensors) -> Result<String> {
let mut system = sensors.system.lock().unwrap();
system.refresh_disks();
system.refresh_networks();
system.refresh_memory();
let hostname = &sensors.hostname;
let mut result = String::with_capacity(256);
let memory = Memory {
total: system.total_memory(),
available: system.available_memory(),
free: system.free_memory(),
};
memory.write(&mut result, &hostname);
for disk in system.disks() {
let space = DiskUsage {
name: disk.name().to_string_lossy().into(),
size: disk.total_space(),
free: disk.available_space(),
};
space.write(&mut result, &hostname);
}
for (interface, net) in system.networks() {
let usage = NetStats {
interface: interface.into(),
bytes_received: net.total_received(),
bytes_sent: net.total_transmitted(),
};
usage.write(&mut result, &hostname);
}
let cpu = sensors.cpu.lock().unwrap().read()?;
cpu.write(&mut result, &hostname);
let gpu_mem_used = WMI.with(|wmi| wmi.gpu_mem())?;
let gpu_mem = GpuMemory {
total: sensors.gpu_mem_total,
free: sensors.gpu_mem_total - gpu_mem_used,
};
gpu_mem.write(&mut result, &hostname);
let gpu_engines = WMI.with(|wmi| wmi.gpu_usage())?;
for (name, usage) in gpu_engines.into_iter() {
let gpu_usage = GpuUsage {
system: Cow::Owned(name),
usage,
};
gpu_usage.write(&mut result, &hostname);
}
if let Some(disk_usage) = WMI.with(|wmi| wmi.disk_usage())? {
disk_usage.write(&mut result, &hostname);
}
Ok(result)
}

24
src/win/reg.rs Normal file
View file

@ -0,0 +1,24 @@
use crate::{Error, Result};
use serde::Deserialize;
use winreg::enums::*;
use winreg::RegKey;
#[derive(Debug, Deserialize)]
struct GpuInfo {
#[serde(rename = "HardwareInformation.qwMemorySize")]
memory_size: Option<u64>,
}
pub fn total_gpu_memory() -> Result<u64> {
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
let mut mem = 0;
for i in 0..3 {
if let Ok(gpu_key) = hklm.open_subkey(
format!("SYSTEM\\ControlSet001\\Control\\Class\\{{4d36e968-e325-11ce-bfc1-08002be10318}}\\{:04}", i),
) {
let info: GpuInfo = gpu_key.decode().map_err(|e| Error::Reg(e.to_string()))?;
mem += info.memory_size.unwrap_or_default();
}
}
Ok(mem)
}

82
src/win/wmi.rs Normal file
View file

@ -0,0 +1,82 @@
use crate::data::DiskStats;
use crate::Result;
use serde::Deserialize;
use std::collections::HashMap;
use wmi::{COMLibrary, WMIConnection};
pub struct WmiSensor {
wmi_con: WMIConnection,
}
impl WmiSensor {
pub fn new() -> Result<Self> {
let com_con = COMLibrary::new()?;
let wmi_con = WMIConnection::new(com_con.into())?;
Ok(WmiSensor { wmi_con })
}
pub fn gpu_mem(&self) -> Result<u64> {
#[derive(Deserialize, Debug)]
#[allow(non_camel_case_types)]
struct Win32_PerfFormattedData_GPUPerformanceCounters_GPUAdapterMemory {
#[serde(rename = "DedicatedUsage")]
dedicated_usage: u64,
}
let results: Vec<Win32_PerfFormattedData_GPUPerformanceCounters_GPUAdapterMemory> =
self.wmi_con.query()?;
Ok(results.iter().map(|result| result.dedicated_usage).sum())
}
pub fn gpu_usage(&self) -> Result<HashMap<String, u32>> {
#[derive(Deserialize, Debug)]
#[allow(non_camel_case_types)]
struct Win32_PerfFormattedData_GPUPerformanceCounters_GPUEngine {
#[serde(rename = "Name")]
name: String,
#[serde(rename = "UtilizationPercentage")]
usage: u32,
}
let results: Vec<Win32_PerfFormattedData_GPUPerformanceCounters_GPUEngine> =
self.wmi_con.query()?;
let mut data = HashMap::default();
for result in results {
if let Some(eng_type) = result.name.split("_engtype_").skip(1).next() {
let entry = data.entry(eng_type.to_string()).or_default();
*entry += result.usage;
}
}
Ok(data)
}
pub fn disk_usage(&self) -> Result<Option<DiskStats>> {
#[derive(Deserialize, Debug)]
#[allow(non_camel_case_types)]
struct Win32_PerfRawData_Counters_FileSystemDiskActivity {
#[serde(rename = "Name")]
name: String,
#[serde(rename = "FileSystemBytesRead")]
read: u64,
#[serde(rename = "FileSystemBytesWritten")]
written: u64,
}
let results: Vec<Win32_PerfRawData_Counters_FileSystemDiskActivity> =
self.wmi_con.query()?;
for result in results {
if result.name == "_Total" {
return Ok(Some(DiskStats {
interface: "Total".to_string(),
bytes_sent: result.written,
bytes_received: result.read,
}));
}
}
Ok(None)
}
}