125 lines
3.5 KiB
Rust
125 lines
3.5 KiB
Rust
mod config;
|
|
mod message;
|
|
mod monitor;
|
|
mod output;
|
|
mod plugins;
|
|
|
|
extern crate getopts;
|
|
extern crate serde_derive;
|
|
extern crate serde_yaml;
|
|
|
|
use std::env;
|
|
use std::fs::File;
|
|
use std::io::prelude::*;
|
|
use std::sync::mpsc;
|
|
use std::thread;
|
|
|
|
use getopts::Options;
|
|
|
|
use crate::config::*;
|
|
use crate::message::*;
|
|
use crate::monitor::*;
|
|
use crate::output::*;
|
|
|
|
fn monitor_factory(name: &str, config: &HashMap<String, serde_yaml::Value>) -> Box<Monitor + Send> {
|
|
match name {
|
|
"tester" => Box::new(plugins::monitor::tester::Tester::new(&config)),
|
|
"wifi_availability" => Box::new(
|
|
plugins::monitor::wifi_availability::WifiAvailability::new(&config),
|
|
),
|
|
_ => panic!("Unknown monitor name: {}", name),
|
|
}
|
|
}
|
|
|
|
fn output_factory(name: &str, config: &HashMap<String, serde_yaml::Value>) -> Box<Output + Send> {
|
|
match name {
|
|
"stdout" => Box::new(plugins::output::stdout::Stdout::new(&config)),
|
|
_ => panic!("Unknown monitor name: {}", name),
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let args: Vec<String> = env::args().collect();
|
|
|
|
// Parse command line args
|
|
let mut opts = Options::new();
|
|
opts.optopt(
|
|
"c",
|
|
"config",
|
|
"Path to config.yaml. Default: ./config.yaml",
|
|
"config.yaml",
|
|
);
|
|
opts.optflag("h", "help", "print this help menu");
|
|
|
|
let matches = match opts.parse(&args[1..]) {
|
|
Ok(m) => m,
|
|
Err(f) => panic!(f.to_string()),
|
|
};
|
|
if matches.opt_present("h") {
|
|
let brief = format!("Usage: {} [options]", args[0]);
|
|
print!("{}", opts.usage(&brief));
|
|
return;
|
|
}
|
|
|
|
// Parse config
|
|
let config_path = matches.opt_str("c").unwrap_or("./config.yaml".to_owned());
|
|
let mut config_file = File::open(config_path).expect("Could not open configuration file");
|
|
let mut config_content = String::new();
|
|
config_file
|
|
.read_to_string(&mut config_content)
|
|
.expect("Could not read configuration file");
|
|
let config: Config =
|
|
serde_yaml::from_str(&config_content).expect("Invalid config file content");
|
|
|
|
// Monitors -> dispatcher channel
|
|
let (mon_sender, mon_receiver) = mpsc::channel();
|
|
|
|
// Instantiate monitor threads and structs
|
|
for mon_config in config.monitors {
|
|
let name = mon_config
|
|
.get("name")
|
|
.expect("Missing `name` key for monitor")
|
|
.as_str()
|
|
.expect("Key `name` for monitor is not a string");
|
|
|
|
println!("Loading monitor: {}", name);
|
|
|
|
let snd = mon_sender.clone();
|
|
let mut mon = monitor_factory(name, &mon_config);
|
|
thread::spawn(move || loop {
|
|
mon.run(&snd);
|
|
});
|
|
}
|
|
|
|
// Instantiate output threads and structs
|
|
let mut output_senders: Vec<mpsc::Sender<Message>> = vec![];
|
|
for out_config in config.outputs {
|
|
let name = out_config
|
|
.get("name")
|
|
.expect("Missing `name` key for monitor")
|
|
.as_str()
|
|
.expect("Key `name` for monitor is not a string");
|
|
|
|
println!("Loading output: {}", name);
|
|
|
|
let (out_sender, out_receiver) = mpsc::channel();
|
|
output_senders.push(out_sender);
|
|
|
|
let mut output = output_factory(name, &out_config);
|
|
|
|
thread::spawn(move || loop {
|
|
let message = out_receiver.recv().unwrap();
|
|
output.process_message(message);
|
|
});
|
|
}
|
|
let output_senders = output_senders;
|
|
|
|
// Dispatch messages
|
|
loop {
|
|
let message = mon_receiver.recv().unwrap();
|
|
for out in &output_senders {
|
|
out.send(message.clone()).unwrap();
|
|
}
|
|
}
|
|
}
|