arc stats

This commit is contained in:
Robin Appelman 2021-04-04 14:10:01 +02:00
commit 78893bdaed
3 changed files with 90 additions and 3 deletions

View file

@ -5,6 +5,7 @@ use futures_util::StreamExt;
use palantir::docker::{get_docker, stat, Container}; use palantir::docker::{get_docker, stat, Container};
use palantir::get_metrics; use palantir::get_metrics;
use palantir::power::power_usage; use palantir::power::power_usage;
use palantir::zfs::arcstats;
use warp::reject::Reject; use warp::reject::Reject;
use warp::{Filter, Rejection}; use warp::{Filter, Rejection};
@ -34,6 +35,9 @@ async fn serve_inner(docker: Option<Docker>) -> Result<String> {
if let Some(power) = power_usage()? { if let Some(power) = power_usage()? {
power.write(&mut metrics, &hostname); power.write(&mut metrics, &hostname);
} }
if let Some(arc) = arcstats()? {
arc.write(&mut metrics, &hostname);
}
Ok(metrics) Ok(metrics)
} }

View file

@ -32,6 +32,7 @@ impl PowerUsage {
} }
} }
} }
pub fn power_usage() -> Result<Option<PowerUsage>> { pub fn power_usage() -> Result<Option<PowerUsage>> {
if !CAN_READ.load(Ordering::Relaxed) { if !CAN_READ.load(Ordering::Relaxed) {
return Ok(None); return Ok(None);

View file

@ -1,9 +1,12 @@
use crate::sensors::DiskUsage; use crate::sensors::DiskUsage;
use color_eyre::Result; use color_eyre::Result;
use std::fmt::Write;
use std::fs::read_to_string;
use std::process::Command; use std::process::Command;
use std::str::FromStr;
pub fn pools() -> impl Iterator<Item = DiskUsage> { pub fn pools() -> impl Iterator<Item = DiskUsage> {
OutputParser { ZPoolOutputParser {
str: zpool_command().unwrap_or_default(), str: zpool_command().unwrap_or_default(),
pos: 0, pos: 0,
} }
@ -28,12 +31,12 @@ fn parse_line(line: &str) -> Option<DiskUsage> {
Some(DiskUsage { name, size, free }) Some(DiskUsage { name, size, free })
} }
struct OutputParser { struct ZPoolOutputParser {
str: String, str: String,
pos: usize, pos: usize,
} }
impl Iterator for OutputParser { impl Iterator for ZPoolOutputParser {
type Item = DiskUsage; type Item = DiskUsage;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@ -54,3 +57,82 @@ impl Iterator for OutputParser {
line.and_then(parse_line) line.and_then(parse_line)
} }
} }
#[derive(Debug, Default)]
pub struct ArcStats {
hits: u64,
misses: u64,
prefetch: u64,
size: u64,
}
impl ArcStats {
pub fn write<W: Write>(&self, mut w: W, hostname: &str) {
writeln!(
&mut w,
"zfs_arc_hits{{host=\"{}\"}} {}",
hostname, self.hits
)
.ok();
writeln!(
&mut w,
"zfs_arc_misses{{host=\"{}\"}} {}",
hostname, self.misses
)
.ok();
writeln!(
&mut w,
"zfs_arc_size{{host=\"{}\"}} {}",
hostname, self.size
)
.ok();
writeln!(
&mut w,
"zfs_arc_prefetch{{host=\"{}\"}} {}",
hostname, self.prefetch
)
.ok();
}
}
pub fn arcstats() -> Result<Option<ArcStats>> {
let content = match read_to_string("/proc/spl/kstat/zfs/arcstats") {
Ok(c) => c,
Err(_) => return Ok(None),
};
let mut stats = ArcStats::default();
for line in content.lines().skip(2) {
let mut parts = line.split_ascii_whitespace();
if let (Some(name), _, Some(Ok(value))) =
(parts.next(), parts.next(), parts.next().map(u64::from_str))
{
match name {
"demand_data_hits" => stats.hits += value,
"demand_metadata_hits" => stats.hits += value,
"prefetch_data_hits" => {
stats.hits += value;
stats.prefetch += value;
}
"prefetch_metadata_hits" => {
stats.hits += value;
stats.prefetch += value;
}
"demand_data_misses" => stats.misses += value,
"demand_metadata_misses" => stats.misses += value,
"prefetch_data_misses" => {
stats.misses += value;
stats.prefetch += value;
}
"prefetch_metadata_misses" => {
stats.misses += value;
stats.prefetch += value;
}
"size" => stats.size = value,
_ => {}
}
}
}
Ok(Some(stats))
}