Skip to content

Commit

Permalink
zcache iostat should survive an agent restart (openzfs#96)
Browse files Browse the repository at this point in the history
  • Loading branch information
Don Brady authored Jan 21, 2022
1 parent 7b15686 commit 287ee6c
Show file tree
Hide file tree
Showing 15 changed files with 280 additions and 144 deletions.
3 changes: 2 additions & 1 deletion cmd/zfs_object_agent/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cmd/zfs_object_agent/util/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ roaring = "0.7.0"
rusoto_credential = "0.47.0"
serde = { version = "1.0.125", features = ["derive"] }
tokio = { version = "1.4", features = ["full"] }
uuid = {version = "0.8.2", features = ["v4", "serde"]}
1 change: 1 addition & 0 deletions cmd/zfs_object_agent/util/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod nicenum;
mod range_tree;
mod tunable;
mod vec_ext;
pub mod write_stdout;
mod zcache_devices;
pub mod zettacache_stats;

Expand Down
54 changes: 54 additions & 0 deletions cmd/zfs_object_agent/util/src/write_stdout.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*!
Alternative to `println!` macros suitable for use in commands.
The `println!` flavors of macros are good for debugging output but not suitable for
production code since they panic when their output is not fully consumed (i.e. write
to a stream that has closed).
The println replacement macros in this module will terminate the process if writing
to stdout/stderr returns an error (like `EPIPE`) rather than cause a panic.
!*/

/// Similar to `print!` macro, except it terminates the process on write errors (does not panic).
#[macro_export]
macro_rules! write_stdout {
($($arg:tt)*) => ({
use std::io::Write;
if let Err(_) = write!(std::io::stdout(), $($arg)*) {
std::process::exit(0)
}
})
}

/// Similar to `println!` macro, except it terminates the process on write errors (does not panic).
#[macro_export]
macro_rules! writeln_stdout {
($($arg:tt)*) => ({
use std::io::Write;
if let Err(_) = writeln!(std::io::stdout(), $($arg)*) {
std::process::exit(0)
}
})
}

/// Similar to `eprint!` macro, except it terminates the process on write errors (does not panic).
#[macro_export]
macro_rules! write_stderr {
($($arg:tt)*) => ({
use std::io::Write;
if let Err(_) = write!(std::io::stderr(), $($arg)*) {
std::process::exit(0)
}
})
}

/// Similar to `eprintln!` macro, except it terminates the process on write errors (does not panic).
#[macro_export]
macro_rules! writeln_stderr {
($($arg:tt)*) => ({
use std::io::Write;
if let Err(_) = writeln!(std::io::stderr(), $($arg)*) {
std::process::exit(0)
}
})
}
10 changes: 9 additions & 1 deletion cmd/zfs_object_agent/util/src/zettacache_stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use std::ops::{AddAssign, Sub};
use std::sync::atomic::Ordering::Relaxed;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::Duration;
use uuid::Uuid;

/// The zettacache disk I/O types that are collected and displayed for each disk.
#[derive(Debug, Enum, Copy, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -295,12 +296,14 @@ impl Sub<Self> for &DiskIoStats {
/// A snapshot of the I/O stats collected from the zettacache.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct IoStats {
pub cache_runtime_id: Uuid, // must match before timestamps & disk_stats can be compared
pub timestamp: Duration,
pub disk_stats: Vec<DiskIoStats>,
}

#[derive(Debug, Default, Serialize)]
#[derive(Debug, Serialize)]
pub struct IoStatsRef<'a> {
pub cache_runtime_id: Uuid,
pub timestamp: Duration,
pub disk_stats: Vec<&'a DiskIoStats>,
}
Expand All @@ -313,6 +316,7 @@ impl Sub<Self> for &IoStats {
if other.disk_stats.is_empty() {
return self.clone();
}
assert_eq!(self.cache_runtime_id, other.cache_runtime_id);

let mut difference = IoStats {
timestamp: self.timestamp - other.timestamp,
Expand Down Expand Up @@ -383,13 +387,15 @@ impl Display for CacheStatCounter {
/// A snapshot of the cache stats collected from the zettacache.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct CacheStats {
pub cache_runtime_id: Uuid, // must match before timestamp & stats can be compared
pub timestamp: Duration,
pub stats: EnumMap<CacheStatCounter, StatCount>,
}

impl CacheStats {
pub fn new() -> CacheStats {
CacheStats {
cache_runtime_id: Default::default(),
timestamp: Duration::default(),
stats: Default::default(),
}
Expand All @@ -416,6 +422,8 @@ impl Sub<&Self> for &CacheStats {

/// Subtract two CacheStats. Used to create the net values between two samples.
fn sub(self, other: &Self) -> CacheStats {
assert_eq!(self.cache_runtime_id, other.cache_runtime_id);

let mut difference = CacheStats {
timestamp: self.timestamp - other.timestamp,
..Default::default()
Expand Down
5 changes: 3 additions & 2 deletions cmd/zfs_object_agent/zcache/src/clear_hit_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::subcommand::ZcacheSubCommand;
use anyhow::Result;
use async_trait::async_trait;
use clap::SubCommand;
use util::writeln_stdout;

static NAME: &str = "clear_hit_data";
pub struct ClearHitData;
Expand All @@ -22,10 +23,10 @@ impl ZcacheSubCommand for ClearHitData {
let response = remote.call(NAME, None).await;
match response {
Ok(_) => {
println!("Hits-by-size data cleared");
writeln_stdout!("Hits-by-size data cleared");
}
Err(RemoteError::ResultError(_)) => {
println!("No cache found, so no hits-by-size data present");
writeln_stdout!("No cache found, so no hits-by-size data present");
}
Err(RemoteError::Other(e)) => return Err(e),
}
Expand Down
Loading

0 comments on commit 287ee6c

Please sign in to comment.