mirror of
https://codeberg.org/icewind/palantir.git
synced 2026-06-03 18:24:08 +02:00
prepare for windows impl
This commit is contained in:
parent
f363cac81d
commit
d12b70d11e
16 changed files with 550 additions and 279 deletions
119
Cargo.lock
generated
119
Cargo.lock
generated
|
|
@ -165,6 +165,12 @@ dependencies = [
|
||||||
"tracing-error",
|
"tracing-error",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
version = "0.2.7"
|
version = "0.2.7"
|
||||||
|
|
@ -174,6 +180,49 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"memoffset 0.8.0",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
|
@ -280,6 +329,12 @@ version = "0.15.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
|
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.32"
|
version = "0.8.32"
|
||||||
|
|
@ -699,6 +754,15 @@ dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mime"
|
name = "mime"
|
||||||
version = "0.3.17"
|
version = "0.3.17"
|
||||||
|
|
@ -773,7 +837,7 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"memoffset",
|
"memoffset 0.6.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -788,6 +852,15 @@ dependencies = [
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ntapi"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu-ansi-term"
|
name = "nu-ansi-term"
|
||||||
version = "0.46.0"
|
version = "0.46.0"
|
||||||
|
|
@ -877,6 +950,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
"sysconf",
|
"sysconf",
|
||||||
|
"sysinfo",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|
@ -976,6 +1050,28 @@ dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
|
|
@ -1018,6 +1114,12 @@ version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.160"
|
version = "1.0.160"
|
||||||
|
|
@ -1186,6 +1288,21 @@ dependencies = [
|
||||||
"winapi 0.2.8",
|
"winapi 0.2.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sysinfo"
|
||||||
|
version = "0.29.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02f1dc6930a439cc5d154221b5387d153f8183529b07c19aca24ea31e0a167e1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"ntapi",
|
||||||
|
"once_cell",
|
||||||
|
"rayon",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.40"
|
version = "1.0.40"
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ 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 }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
iai = "0.1.1"
|
iai = "0.1.1"
|
||||||
|
|
|
||||||
69
flake.lock
generated
69
flake.lock
generated
|
|
@ -1,5 +1,23 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681202837,
|
||||||
|
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"naersk": {
|
"naersk": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
|
|
@ -33,14 +51,16 @@
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1682669017,
|
"lastModified": 1684280442,
|
||||||
"narHash": "sha256-Vi+p4y3wnl0/4gcwTdmCO398kKlDaUrNROtf3GOD2NY=",
|
"narHash": "sha256-nC1/kfh6tpMQSLQalbNTNnireIlxvLLugrjZdasNh+I=",
|
||||||
"path": "/nix/store/wm2cdd01f8jqbxpw817nv5j3sw6p93g8-source",
|
"owner": "NixOS",
|
||||||
"rev": "7449971a3ecf857b4a554cf79b1d9dcc1a4647d8",
|
"repo": "nixpkgs",
|
||||||
"type": "path"
|
"rev": "6c591e7adc514090a77209f56c9d0c551ab8530d",
|
||||||
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"id": "nixpkgs",
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-22.11",
|
||||||
"type": "indirect"
|
"type": "indirect"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -48,9 +68,31 @@
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"naersk": "naersk",
|
"naersk": "naersk",
|
||||||
"nixpkgs": "nixpkgs_2",
|
"nixpkgs": "nixpkgs_2",
|
||||||
|
"rust-overlay": "rust-overlay",
|
||||||
"utils": "utils"
|
"utils": "utils"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"rust-overlay": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1684290028,
|
||||||
|
"narHash": "sha256-IWWfoF5aU8wzxJ6ixuW+3KRlppYvmhUP5v6owWiXJMQ=",
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"rev": "ded1f327ff2bdf0eb4bbb945865441ac636c423e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"systems": {
|
"systems": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1681028828,
|
"lastModified": 1681028828,
|
||||||
|
|
@ -66,9 +108,24 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"systems_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"utils": {
|
"utils": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems"
|
"systems": "systems_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1681202837,
|
"lastModified": 1681202837,
|
||||||
|
|
|
||||||
33
flake.nix
33
flake.nix
|
|
@ -1,7 +1,10 @@
|
||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
|
nixpkgs.url = "nixpkgs/nixos-22.11";
|
||||||
utils.url = "github:numtide/flake-utils";
|
utils.url = "github:numtide/flake-utils";
|
||||||
naersk.url = "github:nix-community/naersk";
|
naersk.url = "github:nix-community/naersk";
|
||||||
|
rust-overlay.url = "github:oxalica/rust-overlay";
|
||||||
|
rust-overlay.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = {
|
outputs = {
|
||||||
|
|
@ -9,9 +12,24 @@
|
||||||
nixpkgs,
|
nixpkgs,
|
||||||
utils,
|
utils,
|
||||||
naersk,
|
naersk,
|
||||||
|
rust-overlay,
|
||||||
}:
|
}:
|
||||||
utils.lib.eachDefaultSystem (system: let
|
utils.lib.eachDefaultSystem (system: let
|
||||||
pkgs = nixpkgs.legacyPackages."${system}";
|
overlays = [ (import rust-overlay) ];
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system overlays;
|
||||||
|
};
|
||||||
|
|
||||||
|
pkgs-cross-mingw = import nixpkgs {
|
||||||
|
crossSystem = {
|
||||||
|
config = "x86_64-w64-mingw32";
|
||||||
|
};
|
||||||
|
inherit system overlays;
|
||||||
|
};
|
||||||
|
mingw_w64_cc = pkgs-cross-mingw.stdenv.cc;
|
||||||
|
mingw_w64 = pkgs-cross-mingw.windows.mingw_w64;
|
||||||
|
windows = pkgs-cross-mingw.windows;
|
||||||
|
|
||||||
naersk-lib = naersk.lib."${system}";
|
naersk-lib = naersk.lib."${system}";
|
||||||
in rec {
|
in rec {
|
||||||
# `nix build`
|
# `nix build`
|
||||||
|
|
@ -34,7 +52,18 @@
|
||||||
|
|
||||||
# `nix develop`
|
# `nix develop`
|
||||||
devShell = pkgs.mkShell {
|
devShell = pkgs.mkShell {
|
||||||
nativeBuildInputs = with pkgs; [cargo bacon];
|
nativeBuildInputs = with pkgs; [
|
||||||
|
(rust-bin.stable.latest.default.override {
|
||||||
|
targets = [ "x86_64-pc-windows-gnu" ];
|
||||||
|
})
|
||||||
|
bacon
|
||||||
|
mingw_w64_cc
|
||||||
|
];
|
||||||
|
depsBuildBuild = [ pkgs.wine64 ];
|
||||||
|
# buildInputs = [ windows.pthreads ];
|
||||||
|
|
||||||
|
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = "${mingw_w64_cc.targetPrefix}cc";
|
||||||
|
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUNNER = "wine64";
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
// {
|
// {
|
||||||
|
|
|
||||||
131
src/data.rs
Normal file
131
src/data.rs
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
use crate::SensorData;
|
||||||
|
use std::array::IntoIter;
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct Temperatures {
|
||||||
|
pub cpu: f32,
|
||||||
|
pub gpu: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoIterator for Temperatures {
|
||||||
|
type Item = (&'static str, f32);
|
||||||
|
type IntoIter = IntoIter<Self::Item, 2>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
[("cpu", self.cpu), ("gpu", self.gpu)].into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SensorData for Temperatures {
|
||||||
|
fn write<W: Write>(&self, mut w: W, hostname: &str) {
|
||||||
|
for (label, temp) in self.clone() {
|
||||||
|
if temp != 0.0 {
|
||||||
|
writeln!(
|
||||||
|
&mut w,
|
||||||
|
"temperature{{host=\"{}\", sensor=\"{}\"}} {:.1}",
|
||||||
|
hostname, label, temp
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct Memory {
|
||||||
|
pub total: u64,
|
||||||
|
pub free: u64,
|
||||||
|
pub available: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SensorData for Memory {
|
||||||
|
fn write<W: Write>(&self, mut w: W, hostname: &str) {
|
||||||
|
writeln!(
|
||||||
|
&mut w,
|
||||||
|
"memory_total{{host=\"{}\"}} {}",
|
||||||
|
hostname, self.total
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
writeln!(
|
||||||
|
&mut w,
|
||||||
|
"memory_available{{host=\"{}\"}} {}",
|
||||||
|
hostname, self.available
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
writeln!(&mut w, "memory_free{{host=\"{}\"}} {}", hostname, self.free).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct GpuMemory {
|
||||||
|
pub total: u64,
|
||||||
|
pub free: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SensorData for GpuMemory {
|
||||||
|
fn write<W: Write>(&self, mut w: W, hostname: &str) {
|
||||||
|
writeln!(
|
||||||
|
&mut w,
|
||||||
|
"gpu_memory_total{{host=\"{}\"}} {}",
|
||||||
|
hostname, self.total
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
writeln!(
|
||||||
|
&mut w,
|
||||||
|
"gpu_memory_free{{host=\"{}\"}} {}",
|
||||||
|
hostname, self.free
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CpuTime(pub f32);
|
||||||
|
|
||||||
|
impl SensorData for CpuTime {
|
||||||
|
fn write<W: Write>(&self, mut w: W, hostname: &str) {
|
||||||
|
writeln!(w, "cpu_time{{host=\"{}\"}} {:.3}", hostname, self.0).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct NetStats {
|
||||||
|
pub interface: String,
|
||||||
|
pub bytes_sent: u64,
|
||||||
|
pub bytes_received: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SensorData for NetStats {
|
||||||
|
fn write<W: Write>(&self, mut w: W, hostname: &str) {
|
||||||
|
if self.bytes_received > 0 || self.bytes_sent > 0 {
|
||||||
|
writeln!(
|
||||||
|
&mut w,
|
||||||
|
"net_sent{{host=\"{}\", network=\"{}\"}} {}",
|
||||||
|
hostname, self.interface, self.bytes_sent
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
writeln!(
|
||||||
|
&mut w,
|
||||||
|
"net_received{{host=\"{}\", network=\"{}\"}} {}",
|
||||||
|
hostname, self.interface, self.bytes_received
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GpuUsage {
|
||||||
|
pub system: &'static str,
|
||||||
|
pub usage: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GpuUsage {
|
||||||
|
pub fn write<W: Write>(&self, mut w: W, hostname: &str) {
|
||||||
|
writeln!(
|
||||||
|
&mut w,
|
||||||
|
r#"gpu_usage{{host="{}", system="{}"}} {:.3}"#,
|
||||||
|
hostname, self.system, self.usage,
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
129
src/lib.rs
129
src/lib.rs
|
|
@ -1,27 +1,28 @@
|
||||||
pub mod disk;
|
|
||||||
pub mod docker;
|
|
||||||
pub mod gpu;
|
|
||||||
pub mod hwmon;
|
|
||||||
pub mod power;
|
|
||||||
pub mod sensors;
|
|
||||||
|
|
||||||
use crate::disk::zfs::pools;
|
|
||||||
use crate::disk::*;
|
|
||||||
use crate::sensors::*;
|
|
||||||
use std::ffi::NulError;
|
use std::ffi::NulError;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::io;
|
|
||||||
use std::num::{ParseFloatError, ParseIntError};
|
use std::num::{ParseFloatError, ParseIntError};
|
||||||
use std::str::Utf8Error;
|
use std::str::Utf8Error;
|
||||||
use std::sync::Mutex;
|
use std::string::FromUtf8Error;
|
||||||
use sysconf::SysconfError;
|
|
||||||
|
pub mod data;
|
||||||
|
pub mod docker;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sysinfo"))]
|
||||||
|
mod linux;
|
||||||
|
#[cfg(feature = "sysinfo")]
|
||||||
|
mod sys;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sysinfo"))]
|
||||||
|
pub use linux::{get_metrics, Sensors};
|
||||||
|
#[cfg(feature = "sysinfo")]
|
||||||
|
pub use sys::{get_metrics, Sensors};
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Io(#[from] io::Error),
|
Io(#[from] std::io::Error),
|
||||||
#[error("Unsupported sysconf")]
|
#[error("{0}")]
|
||||||
Sysconf(SysconfError),
|
Other(String),
|
||||||
#[error("Non UTF8 hostname")]
|
#[error("Non UTF8 hostname")]
|
||||||
InvalidHostName,
|
InvalidHostName,
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|
@ -36,98 +37,14 @@ pub enum Error {
|
||||||
StatVfs,
|
StatVfs,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SysconfError> for Error {
|
impl From<FromUtf8Error> for Error {
|
||||||
fn from(value: SysconfError) -> Self {
|
fn from(err: FromUtf8Error) -> Self {
|
||||||
Error::Sysconf(value)
|
Self::InvalidStringData(err.utf8_error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||||
|
|
||||||
pub struct Sensors {
|
|
||||||
pub hostname: String,
|
|
||||||
cpu: Mutex<CpuTimeSource>,
|
|
||||||
temp: Mutex<TemperatureSource>,
|
|
||||||
net: Mutex<NetworkSource>,
|
|
||||||
mem: Mutex<MemorySource>,
|
|
||||||
disk_stats: Mutex<DiskStatSource>,
|
|
||||||
disk_usage: Mutex<DiskUsageSource>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Sensors {
|
|
||||||
pub fn new() -> Result<Sensors> {
|
|
||||||
Ok(Sensors {
|
|
||||||
hostname: hostname()?,
|
|
||||||
cpu: Mutex::new(CpuTimeSource::new()?),
|
|
||||||
temp: Mutex::new(TemperatureSource::new()?),
|
|
||||||
net: Mutex::new(NetworkSource::new()?),
|
|
||||||
mem: Mutex::new(MemorySource::new()?),
|
|
||||||
disk_stats: Mutex::new(DiskStatSource::new()?),
|
|
||||||
disk_usage: Mutex::new(DiskUsageSource::new()?),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_metrics(sensors: &Sensors) -> Result<String> {
|
|
||||||
let hostname = &sensors.hostname;
|
|
||||||
let mut disk_source = sensors.disk_stats.lock().unwrap();
|
|
||||||
let mut disk_usage_source = sensors.disk_usage.lock().unwrap();
|
|
||||||
let disks = disk_source.read()?;
|
|
||||||
let disk_usage = disk_usage_source.read()?;
|
|
||||||
let cpu = sensors.cpu.lock().unwrap().read()?;
|
|
||||||
let memory = sensors.mem.lock().unwrap().read()?;
|
|
||||||
let temperatures = sensors.temp.lock().unwrap().read()?;
|
|
||||||
let mut net = sensors.net.lock().unwrap();
|
|
||||||
let networks = net.read()?;
|
|
||||||
let pools = pools();
|
|
||||||
let mut result = String::with_capacity(256);
|
|
||||||
|
|
||||||
cpu.write(&mut result, &hostname);
|
|
||||||
memory.write(&mut result, &hostname);
|
|
||||||
|
|
||||||
for pool in pools {
|
|
||||||
writeln!(
|
|
||||||
&mut result,
|
|
||||||
"zfs_pool_size{{host=\"{}\", pool=\"{}\"}} {}",
|
|
||||||
hostname, pool.name, pool.size
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
writeln!(
|
|
||||||
&mut result,
|
|
||||||
"zfs_pool_free{{host=\"{}\", pool=\"{}\"}} {}",
|
|
||||||
hostname, pool.name, pool.free
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
for network in networks {
|
|
||||||
if let Ok(network) = network {
|
|
||||||
network.write(&mut result, &hostname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for disk in disks {
|
|
||||||
if let Ok(disk) = disk {
|
|
||||||
disk.write(&mut result, hostname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for disk in disk_usage {
|
|
||||||
if let Ok(disk) = disk {
|
|
||||||
disk.write(&mut result, hostname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (label, temp) in temperatures {
|
|
||||||
if temp != 0.0 {
|
|
||||||
writeln!(
|
|
||||||
&mut result,
|
|
||||||
"temperature{{host=\"{}\", sensor=\"{}\"}} {:.1}",
|
|
||||||
hostname, label, temp
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait SensorData {
|
pub trait SensorData {
|
||||||
/// Write sensor data in prometheus compatible format
|
/// Write sensor data in prometheus compatible format
|
||||||
fn write<W: Write>(&self, w: W, hostname: &str);
|
fn write<W: Write>(&self, w: W, hostname: &str);
|
||||||
|
|
@ -147,3 +64,9 @@ pub trait MultiSensorSource {
|
||||||
|
|
||||||
fn read(&mut self) -> Result<Self::Iter<'_>>;
|
fn read(&mut self) -> Result<Self::Iter<'_>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hostname() -> Result<String> {
|
||||||
|
hostname::get()?
|
||||||
|
.into_string()
|
||||||
|
.map_err(|_| Error::InvalidHostName)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::disk::DiskUsage;
|
use crate::linux::disk::DiskUsage;
|
||||||
use color_eyre::Result;
|
use crate::Result;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::fs::read_to_string;
|
use std::fs::read_to_string;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::hwmon::FileSource;
|
use crate::data::{GpuMemory, GpuUsage};
|
||||||
use crate::sensors::Memory;
|
use crate::linux::hwmon::FileSource;
|
||||||
use std::fmt::Write;
|
|
||||||
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};
|
||||||
|
|
@ -10,61 +9,23 @@ use std::time::{Duration, Instant};
|
||||||
|
|
||||||
pub mod nvidia;
|
pub mod nvidia;
|
||||||
|
|
||||||
pub fn gpu_metrics<W: Write>(mut out: W, hostname: &str) {
|
|
||||||
if let Some(memory) = memory() {
|
|
||||||
writeln!(
|
|
||||||
&mut out,
|
|
||||||
"gpu_memory_total{{host=\"{}\"}} {}",
|
|
||||||
hostname, memory.total
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
writeln!(
|
|
||||||
&mut out,
|
|
||||||
"gpu_memory_free{{host=\"{}\"}} {}",
|
|
||||||
hostname, memory.free
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
for usage in utilization() {
|
|
||||||
usage.write(&mut out, hostname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_num<T: FromStr>(path: &str) -> Option<T> {
|
fn read_num<T: FromStr>(path: &str) -> Option<T> {
|
||||||
read_to_string(path).ok()?.trim().parse().ok()
|
read_to_string(path).ok()?.trim().parse().ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn memory() -> Option<Memory> {
|
pub fn memory() -> Option<GpuMemory> {
|
||||||
if let Some(nv_mem) = nvidia::memory() {
|
if let Some(nv_mem) = nvidia::memory() {
|
||||||
return Some(nv_mem);
|
return Some(nv_mem);
|
||||||
}
|
}
|
||||||
// 1 gpu should be enough for everyone
|
// 1 gpu should be enough for everyone
|
||||||
let used = read_num::<u64>("/sys/class/drm/card0/device/mem_info_vram_used")?;
|
let used = read_num::<u64>("/sys/class/drm/card0/device/mem_info_vram_used")?;
|
||||||
let total = read_num("/sys/class/drm/card0/device/mem_info_vram_total")?;
|
let total = read_num("/sys/class/drm/card0/device/mem_info_vram_total")?;
|
||||||
Some(Memory {
|
Some(GpuMemory {
|
||||||
total,
|
total,
|
||||||
free: total - used,
|
free: total - used,
|
||||||
available: total - used,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GpuUsage {
|
|
||||||
pub system: &'static str,
|
|
||||||
pub usage: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GpuUsage {
|
|
||||||
pub fn write<W: Write>(&self, mut w: W, hostname: &str) {
|
|
||||||
writeln!(
|
|
||||||
&mut w,
|
|
||||||
r#"gpu_usage{{host="{}", system="{}"}} {:.3}"#,
|
|
||||||
hostname, self.system, self.usage,
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn utilization() -> impl Iterator<Item = GpuUsage> {
|
pub fn utilization() -> impl Iterator<Item = GpuUsage> {
|
||||||
let nv_usage = nvidia::utilization();
|
let nv_usage = nvidia::utilization();
|
||||||
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::gpu::GpuUsage;
|
use crate::data::{GpuMemory, GpuUsage};
|
||||||
use crate::sensors::Memory;
|
|
||||||
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;
|
||||||
|
|
@ -22,12 +21,11 @@ pub fn power() -> Option<u64> {
|
||||||
.map(|mj| mj * 1_000)
|
.map(|mj| mj * 1_000)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn memory() -> Option<Memory> {
|
pub fn memory() -> Option<GpuMemory> {
|
||||||
let mem = device()?.memory_info().ok()?;
|
let mem = device()?.memory_info().ok()?;
|
||||||
Some(Memory {
|
Some(GpuMemory {
|
||||||
total: mem.total,
|
total: mem.total,
|
||||||
free: mem.free,
|
free: mem.free,
|
||||||
available: mem.free,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
123
src/linux/mod.rs
Normal file
123
src/linux/mod.rs
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
pub mod disk;
|
||||||
|
pub mod gpu;
|
||||||
|
pub mod hwmon;
|
||||||
|
pub mod power;
|
||||||
|
pub mod sensors;
|
||||||
|
|
||||||
|
use self::disk::zfs::pools;
|
||||||
|
use self::disk::*;
|
||||||
|
use self::sensors::*;
|
||||||
|
use crate::linux::disk::zfs::arcstats;
|
||||||
|
use crate::linux::gpu::{update_gpu_power, utilization};
|
||||||
|
use crate::linux::power::power_usage;
|
||||||
|
use crate::{hostname, Error, MultiSensorSource, Result, SensorData, SensorSource};
|
||||||
|
use std::fmt::Write;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use sysconf::SysconfError;
|
||||||
|
|
||||||
|
impl From<SysconfError> for Error {
|
||||||
|
fn from(_: SysconfError) -> Self {
|
||||||
|
Error::Other("Unsupported sysconf".into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Sensors {
|
||||||
|
pub hostname: String,
|
||||||
|
cpu: Mutex<CpuTimeSource>,
|
||||||
|
temp: Mutex<TemperatureSource>,
|
||||||
|
net: Mutex<NetworkSource>,
|
||||||
|
mem: Mutex<MemorySource>,
|
||||||
|
disk_stats: Mutex<DiskStatSource>,
|
||||||
|
disk_usage: Mutex<DiskUsageSource>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sensors {
|
||||||
|
pub fn new() -> Result<Sensors> {
|
||||||
|
std::thread::spawn(update_gpu_power);
|
||||||
|
|
||||||
|
Ok(Sensors {
|
||||||
|
hostname: hostname()?,
|
||||||
|
cpu: Mutex::new(CpuTimeSource::new()?),
|
||||||
|
temp: Mutex::new(TemperatureSource::new()?),
|
||||||
|
net: Mutex::new(NetworkSource::new()?),
|
||||||
|
mem: Mutex::new(MemorySource::new()?),
|
||||||
|
disk_stats: Mutex::new(DiskStatSource::new()?),
|
||||||
|
disk_usage: Mutex::new(DiskUsageSource::new()?),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_metrics(sensors: &Sensors) -> Result<String> {
|
||||||
|
let hostname = &sensors.hostname;
|
||||||
|
let mut disk_source = sensors.disk_stats.lock().unwrap();
|
||||||
|
let mut disk_usage_source = sensors.disk_usage.lock().unwrap();
|
||||||
|
let disks = disk_source.read()?;
|
||||||
|
let disk_usage = disk_usage_source.read()?;
|
||||||
|
let cpu = sensors.cpu.lock().unwrap().read()?;
|
||||||
|
let memory = sensors.mem.lock().unwrap().read()?;
|
||||||
|
let temperatures = sensors.temp.lock().unwrap().read()?;
|
||||||
|
let mut net = sensors.net.lock().unwrap();
|
||||||
|
let networks = net.read()?;
|
||||||
|
let pools = pools();
|
||||||
|
let mut result = String::with_capacity(256);
|
||||||
|
|
||||||
|
cpu.write(&mut result, &hostname);
|
||||||
|
memory.write(&mut result, &hostname);
|
||||||
|
|
||||||
|
for pool in pools {
|
||||||
|
writeln!(
|
||||||
|
&mut result,
|
||||||
|
"zfs_pool_size{{host=\"{}\", pool=\"{}\"}} {}",
|
||||||
|
hostname, pool.name, pool.size
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
writeln!(
|
||||||
|
&mut result,
|
||||||
|
"zfs_pool_free{{host=\"{}\", pool=\"{}\"}} {}",
|
||||||
|
hostname, pool.name, pool.free
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
for network in networks {
|
||||||
|
if let Ok(network) = network {
|
||||||
|
network.write(&mut result, &hostname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for disk in disks {
|
||||||
|
if let Ok(disk) = disk {
|
||||||
|
disk.write(&mut result, hostname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for disk in disk_usage {
|
||||||
|
if let Ok(disk) = disk {
|
||||||
|
disk.write(&mut result, hostname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (label, temp) in temperatures {
|
||||||
|
if temp != 0.0 {
|
||||||
|
writeln!(
|
||||||
|
&mut result,
|
||||||
|
"temperature{{host=\"{}\", sensor=\"{}\"}} {:.1}",
|
||||||
|
hostname, label, temp
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(power) = power_usage()? {
|
||||||
|
power.write(&mut result, &sensors.hostname);
|
||||||
|
}
|
||||||
|
if let Some(arc) = arcstats()? {
|
||||||
|
arc.write(&mut result, &sensors.hostname);
|
||||||
|
}
|
||||||
|
if let Some(memory) = gpu::memory() {
|
||||||
|
memory.write(&mut result, &sensors.hostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
for usage in utilization() {
|
||||||
|
usage.write(&mut result, &sensors.hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::gpu::gpu_power;
|
use crate::linux::gpu::gpu_power;
|
||||||
use color_eyre::{Report, Result};
|
use crate::{Error, Result};
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::fs::{read_dir, read_to_string};
|
use std::fs::{read_dir, read_to_string};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
@ -63,7 +63,7 @@ pub fn power_usage() -> Result<Option<PowerUsage>> {
|
||||||
if package
|
if package
|
||||||
.file_name()
|
.file_name()
|
||||||
.to_str()
|
.to_str()
|
||||||
.ok_or_else(|| Report::msg("Invalid name"))?
|
.ok_or_else(|| Error::Other("Invalid name".into()))?
|
||||||
.starts_with("intel-rapl")
|
.starts_with("intel-rapl")
|
||||||
{
|
{
|
||||||
let mut package_path = package.path();
|
let mut package_path = package.path();
|
||||||
|
|
@ -86,7 +86,7 @@ pub fn power_usage() -> Result<Option<PowerUsage>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
usage.gpu_uj = gpu_power();
|
usage.gpu_uj = gpu_power();
|
||||||
if let Some(nvidia_power) = crate::gpu::nvidia::power() {
|
if let Some(nvidia_power) = crate::linux::gpu::nvidia::power() {
|
||||||
usage.gpu_uj = nvidia_power;
|
usage.gpu_uj = nvidia_power;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,67 +1,11 @@
|
||||||
use crate::hwmon::{Device, FileSource};
|
use crate::data::{CpuTime, Memory, NetStats, Temperatures};
|
||||||
use crate::{Error, MultiSensorSource, Result, SensorData, SensorSource};
|
use crate::linux::hwmon::{Device, FileSource};
|
||||||
use std::array::IntoIter;
|
use crate::{Error, MultiSensorSource, Result, SensorSource};
|
||||||
use std::fmt::Write;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::{BufRead, BufReader, ErrorKind, Read, Seek};
|
use std::io::{BufRead, BufReader, ErrorKind, Read, Seek};
|
||||||
use sysconf::{sysconf, SysconfVariable};
|
use sysconf::{sysconf, SysconfVariable};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
|
||||||
pub struct Temperatures {
|
|
||||||
cpu: f32,
|
|
||||||
gpu: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoIterator for Temperatures {
|
|
||||||
type Item = (&'static str, f32);
|
|
||||||
type IntoIter = IntoIter<Self::Item, 2>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
[("cpu", self.cpu), ("gpu", self.gpu)].into_iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SensorData for Temperatures {
|
|
||||||
fn write<W: Write>(&self, mut w: W, hostname: &str) {
|
|
||||||
for (label, temp) in self.clone() {
|
|
||||||
if temp != 0.0 {
|
|
||||||
writeln!(
|
|
||||||
&mut w,
|
|
||||||
"temperature{{host=\"{}\", sensor=\"{}\"}} {:.1}",
|
|
||||||
hostname, label, temp
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
|
||||||
pub struct Memory {
|
|
||||||
pub total: u64,
|
|
||||||
pub free: u64,
|
|
||||||
pub available: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SensorData for Memory {
|
|
||||||
fn write<W: Write>(&self, mut w: W, hostname: &str) {
|
|
||||||
writeln!(
|
|
||||||
&mut w,
|
|
||||||
"memory_total{{host=\"{}\"}} {}",
|
|
||||||
hostname, self.total
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
writeln!(
|
|
||||||
&mut w,
|
|
||||||
"memory_available{{host=\"{}\"}} {}",
|
|
||||||
hostname, self.available
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
writeln!(&mut w, "memory_free{{host=\"{}\"}} {}", hostname, self.free).ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TemperatureSource {
|
pub struct TemperatureSource {
|
||||||
cpu_sensors: Vec<FileSource>,
|
cpu_sensors: Vec<FileSource>,
|
||||||
gpu_sensors: Vec<FileSource>,
|
gpu_sensors: Vec<FileSource>,
|
||||||
|
|
@ -117,10 +61,16 @@ impl SensorSource for TemperatureSource {
|
||||||
type Data = Temperatures;
|
type Data = Temperatures;
|
||||||
|
|
||||||
fn read(&mut self) -> Result<Self::Data> {
|
fn read(&mut self) -> Result<Self::Data> {
|
||||||
Ok(Temperatures {
|
let mut result = Temperatures {
|
||||||
cpu: average_sensors(&mut self.cpu_sensors) / 1000.0,
|
cpu: average_sensors(&mut self.cpu_sensors) / 1000.0,
|
||||||
gpu: average_sensors(&mut self.gpu_sensors) / 1000.0,
|
gpu: average_sensors(&mut self.gpu_sensors) / 1000.0,
|
||||||
})
|
};
|
||||||
|
|
||||||
|
if let Some(gpu) = super::gpu::nvidia::temperature() {
|
||||||
|
result.gpu = gpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,14 +115,6 @@ impl SensorSource for MemorySource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CpuTime(f32);
|
|
||||||
|
|
||||||
impl SensorData for CpuTime {
|
|
||||||
fn write<W: Write>(&self, mut w: W, hostname: &str) {
|
|
||||||
writeln!(w, "cpu_time{{host=\"{}\"}} {:.3}", hostname, self.0).ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CpuTimeSource {
|
pub struct CpuTimeSource {
|
||||||
source: BufReader<File>,
|
source: BufReader<File>,
|
||||||
buff: Vec<u8>,
|
buff: Vec<u8>,
|
||||||
|
|
@ -216,32 +158,6 @@ impl SensorSource for CpuTimeSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
|
||||||
pub struct NetStats {
|
|
||||||
pub interface: String,
|
|
||||||
pub bytes_sent: u64,
|
|
||||||
pub bytes_received: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SensorData for NetStats {
|
|
||||||
fn write<W: Write>(&self, mut w: W, hostname: &str) {
|
|
||||||
if self.bytes_received > 0 || self.bytes_sent > 0 {
|
|
||||||
writeln!(
|
|
||||||
&mut w,
|
|
||||||
"net_sent{{host=\"{}\", network=\"{}\"}} {}",
|
|
||||||
hostname, self.interface, self.bytes_sent
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
writeln!(
|
|
||||||
&mut w,
|
|
||||||
"net_received{{host=\"{}\", network=\"{}\"}} {}",
|
|
||||||
hostname, self.interface, self.bytes_received
|
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct NetworkSource {
|
pub struct NetworkSource {
|
||||||
source: File,
|
source: File,
|
||||||
buff: String,
|
buff: String,
|
||||||
|
|
@ -326,9 +242,3 @@ impl<'a> Iterator for NetworkStatParser<'a> {
|
||||||
Some(NetworkSource::parse_line(line))
|
Some(NetworkSource::parse_line(line))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hostname() -> Result<String> {
|
|
||||||
hostname::get()?
|
|
||||||
.into_string()
|
|
||||||
.map_err(|_| Error::InvalidHostName)
|
|
||||||
}
|
|
||||||
12
src/main.rs
12
src/main.rs
|
|
@ -3,10 +3,7 @@ use color_eyre::{Report, Result};
|
||||||
use futures_util::pin_mut;
|
use futures_util::pin_mut;
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
use libmdns::Responder;
|
use libmdns::Responder;
|
||||||
use palantir::disk::zfs::arcstats;
|
|
||||||
use palantir::docker::{get_docker, stat, Container};
|
use palantir::docker::{get_docker, stat, Container};
|
||||||
use palantir::gpu::{gpu_metrics, update_gpu_power};
|
|
||||||
use palantir::power::power_usage;
|
|
||||||
use palantir::{get_metrics, Sensors};
|
use palantir::{get_metrics, Sensors};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
@ -39,13 +36,6 @@ async fn serve_inner(docker: Option<Docker>, sensors: &Sensors) -> Result<String
|
||||||
container.write(&mut metrics, &sensors.hostname);
|
container.write(&mut metrics, &sensors.hostname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(power) = power_usage()? {
|
|
||||||
power.write(&mut metrics, &sensors.hostname);
|
|
||||||
}
|
|
||||||
if let Some(arc) = arcstats()? {
|
|
||||||
arc.write(&mut metrics, &sensors.hostname);
|
|
||||||
}
|
|
||||||
gpu_metrics(&mut metrics, &sensors.hostname);
|
|
||||||
|
|
||||||
Ok(metrics)
|
Ok(metrics)
|
||||||
}
|
}
|
||||||
|
|
@ -86,8 +76,6 @@ async fn main() -> Result<()> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::thread::spawn(update_gpu_power);
|
|
||||||
|
|
||||||
let metrics = warp::path!("metrics")
|
let metrics = warp::path!("metrics")
|
||||||
.and(docker)
|
.and(docker)
|
||||||
.and(sensors)
|
.and(sensors)
|
||||||
|
|
|
||||||
33
src/sys/mod.rs
Normal file
33
src/sys/mod.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
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)
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue