Skip to content

Instantly share code, notes, and snippets.

@tene
Created February 21, 2017 01:24
Show Gist options
  • Save tene/ae6b2c26c22a31ac87a9bfa46b1b54e7 to your computer and use it in GitHub Desktop.
Save tene/ae6b2c26c22a31ac87a9bfa46b1b54e7 to your computer and use it in GitHub Desktop.
extern crate sparkline;
use sparkline::*;
use std::io::BufReader;
use std::io::BufRead;
use std::io::Write;
use std::net;
use std::env;
use std::error::Error;
use std::collections::HashMap;
fn gather_stats(addr: &str, stats: &mut HashMap<String, HashMap<String, Vec<i64>>>) -> Result<(),Box<Error>> {
let mut stream = BufReader::new(net::TcpStream::connect((addr,11211))?);
let skipmetrics = ["cas_badval", "cas_hits", "chunk_size",
"chunks_per_page", "evicted_time",
"free_chunks_end", "outofmemory",
"tailrepairs",
];
stream.get_mut().write(b"stats slabs\r\n")?;
stream.get_mut().write(b"stats items\r\n")?;
stream.get_mut().shutdown(net::Shutdown::Write)?;
for line in stream.lines().collect::<Result<Vec<String>,_>>()? {
if line.starts_with("END") {
continue
} else {
let words: Vec<&str> = line.split_whitespace().collect();
let key = words[1].to_owned().trim_left_matches("items:").to_string();
if skipmetrics.iter().any(|x| key.contains(x)) {
continue;
}
stats.entry("global".to_string()).or_insert_with(HashMap::new)
.entry(key.clone()).or_insert_with(Vec::new)
.push(words[2].parse::<i64>()?);
if key.starts_with(char::is_numeric) {
let key2 = key.split(':').nth(1).unwrap().to_owned();
stats.entry(addr.to_owned()).or_insert_with(HashMap::new)
.entry(key2).or_insert_with(Vec::new)
.push(words[2].parse::<i64>()?);
}
}
}
//Ok(buffer)
Ok(())
}
fn dump_stats(stats: &HashMap<String, Vec<i64>>) {
let sparky = select_sparkline(SparkThemeName::Colour);
let maxkeylength = stats.keys().max_by_key(|x| x.len()).unwrap().len();
let mut keys = stats.keys().collect::<Vec<&String>>();
keys.sort();
for name in keys.iter() {
let vals = stats.get(*name).unwrap();
let min = vals.iter().min().unwrap();
let max = vals.iter().max().unwrap();
print!("{1:<0$}:{2:>10}{3:>13}:", maxkeylength, name, min, max);
for num in vals {
let s : &String = sparky.spark(*min as f64, *max as f64, *num as f64);
print!("{}", s);
}
println!("");
}
}
fn main() {
let mut stats: HashMap<String, HashMap<String, Vec<i64>>> = HashMap::new();
for addr in env::args().skip(1) {
//println!("{:?}", addr);
gather_stats(&*addr, &mut stats).expect("Failed to fetch stats");
println!("----- {} -----", addr);
dump_stats(stats.get(&*addr).unwrap());
}
//println!("{:?}", stats);
println!("----- global -----");
dump_stats(stats.get("global").unwrap());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment