rnetmon/src/main.rs

195 lines
5.6 KiB
Rust
Raw Normal View History

2019-02-14 07:21:22 +00:00
#![feature(unrestricted_attribute_tokens)]
#![feature(custom_attribute)]
#![feature(try_from)]
mod filter;
2019-01-30 15:26:05 +00:00
mod message;
mod monitor;
2019-02-14 07:21:22 +00:00
mod monitors;
2019-01-30 15:26:05 +00:00
mod output;
2019-02-14 07:21:22 +00:00
mod outputs;
2019-01-30 15:26:05 +00:00
2019-01-31 10:01:47 +00:00
extern crate getopts;
2019-02-14 07:21:22 +00:00
extern crate globset;
extern crate log;
2019-01-31 10:01:47 +00:00
extern crate serde_yaml;
2019-02-14 07:21:22 +00:00
extern crate simplelog;
2019-01-31 10:01:47 +00:00
2019-02-14 07:21:22 +00:00
use getopts::Options;
use serde::Deserialize;
use std::collections::HashMap;
2019-01-31 10:01:47 +00:00
use std::env;
use std::fs::File;
use std::io::prelude::*;
2019-01-30 22:11:51 +00:00
use std::sync::mpsc;
2019-02-17 22:50:18 +00:00
use std::sync::{Arc, Barrier};
2019-01-31 10:01:47 +00:00
use std::thread;
2019-01-30 15:26:05 +00:00
2019-02-14 07:21:22 +00:00
use crate::filter::*;
2019-01-31 10:01:47 +00:00
use crate::message::*;
2019-02-14 07:21:22 +00:00
#[derive(Debug, Deserialize)]
pub struct AppConfig {
pub monitors: Vec<HashMap<String, serde_yaml::Value>>,
pub outputs: Vec<HashMap<String, serde_yaml::Value>>,
}
2019-01-31 10:01:47 +00:00
2019-01-30 15:26:05 +00:00
fn main() {
2019-01-31 10:01:47 +00:00
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");
2019-02-14 07:21:22 +00:00
opts.optflag("v", "verbose", "Switch to DEBUG output");
opts.optflag("q", "quiet", "Switch to WARNING output");
2019-01-31 10:01:47 +00:00
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;
}
2019-02-14 07:21:22 +00:00
let level;
if matches.opt_present("v") && matches.opt_present("q") {
panic!("-v and -q are mutually exclusive");
}
if matches.opt_present("v") {
level = simplelog::LevelFilter::Debug;
} else if matches.opt_present("q") {
level = simplelog::LevelFilter::Warn;
} else {
level = simplelog::LevelFilter::Info;
}
simplelog::TermLogger::init(
level,
simplelog::Config {
2019-02-17 22:50:18 +00:00
time: None,
2019-02-14 07:21:22 +00:00
level: Some(simplelog::Level::Error),
target: Some(simplelog::Level::Info),
location: Some(simplelog::Level::Debug),
time_format: None,
},
)
.unwrap();
2019-01-31 10:01:47 +00:00
// Parse config
2019-01-31 16:13:58 +00:00
let config_path = matches.opt_str("c").unwrap_or("./config.yaml".to_owned());
2019-02-05 07:10:55 +00:00
2019-01-31 10:01:47 +00:00
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");
2019-02-14 07:21:22 +00:00
let config: AppConfig =
2019-01-31 10:01:47 +00:00
serde_yaml::from_str(&config_content).expect("Invalid config file content");
2019-02-17 22:50:18 +00:00
let thread_count = config.monitors.len() + config.outputs.len();
let barrier = Arc::new(Barrier::new(thread_count + 1));
2019-01-31 10:01:47 +00:00
// Monitors -> dispatcher channel
2019-01-30 22:11:51 +00:00
let (mon_sender, mon_receiver) = mpsc::channel();
2019-01-31 10:01:47 +00:00
// Instantiate monitor threads and structs
2019-02-17 22:50:18 +00:00
let mut mon_threads = vec![];
2019-02-23 17:45:43 +00:00
for mon_node in config.monitors {
let mon_type = mon_node
2019-02-14 07:21:22 +00:00
.get("type")
.expect("Missing `type` key for monitor")
2019-01-31 10:01:47 +00:00
.as_str()
2019-02-14 07:21:22 +00:00
.expect("Key `type` for monitor is not a string")
.to_owned();
2019-02-23 17:45:43 +00:00
let mon_config = mon_node
.get("config")
.unwrap_or(&serde_yaml::Mapping::new().into())
.clone();
2019-01-31 10:01:47 +00:00
2019-01-30 22:11:51 +00:00
let snd = mon_sender.clone();
2019-02-17 22:50:18 +00:00
let bar = barrier.clone();
2019-02-14 07:21:22 +00:00
2019-02-17 22:50:18 +00:00
mon_threads.push(thread::spawn(move || {
2019-02-14 07:21:22 +00:00
log::info!("+> monitor: {}", mon_type);
2019-02-23 17:45:43 +00:00
match monitors::factory(&mon_type, mon_config) {
Ok(mut mon) => {
2019-02-17 22:50:18 +00:00
bar.wait();
2019-02-23 17:45:43 +00:00
loop {
mon.run(&snd);
}
}
2019-02-14 07:21:22 +00:00
Err(e) => log::error!("Cannot instantiate monitor {}: {}", mon_type, e),
}
2019-02-17 22:50:18 +00:00
}));
2019-01-30 22:11:51 +00:00
}
2019-01-30 15:26:05 +00:00
2019-01-31 10:01:47 +00:00
// Instantiate output threads and structs
2019-01-30 22:11:51 +00:00
let mut output_senders: Vec<mpsc::Sender<Message>> = vec![];
2019-02-17 22:50:18 +00:00
let mut output_threads = vec![];
2019-02-23 17:45:43 +00:00
for out_node in config.outputs {
let out_type = out_node
2019-02-14 07:21:22 +00:00
.get("type")
.expect("Missing `type` key for output")
2019-01-31 10:01:47 +00:00
.as_str()
2019-02-14 07:21:22 +00:00
.expect("Key `type` for output is not a string")
.to_owned();
2019-02-23 17:45:43 +00:00
let out_config = out_node
.get("config")
.unwrap_or(&serde_yaml::Mapping::new().into())
.clone();
let out_filter = out_node
.get("filter")
.unwrap_or(&serde_yaml::Mapping::new().into())
.clone();
2019-01-31 10:01:47 +00:00
2019-01-30 22:11:51 +00:00
let (out_sender, out_receiver) = mpsc::channel();
output_senders.push(out_sender);
2019-01-30 15:26:05 +00:00
2019-02-23 17:45:43 +00:00
let filter = Filter::new(&out_filter);
2019-02-17 22:50:18 +00:00
let bar = barrier.clone();
2019-02-14 07:21:22 +00:00
2019-02-17 22:50:18 +00:00
output_threads.push(thread::spawn(move || {
2019-02-14 07:21:22 +00:00
log::info!("+> output: {}", out_type);
2019-02-23 17:45:43 +00:00
match outputs::factory(&out_type, out_config) {
Ok(mut output) => {
2019-02-17 22:50:18 +00:00
bar.wait();
2019-02-23 17:45:43 +00:00
loop {
let message = out_receiver.recv().unwrap();
if filter.is_message_allowed(&message) {
output.process_message(message);
}
2019-02-14 07:21:22 +00:00
}
2019-02-23 17:45:43 +00:00
}
2019-02-14 07:21:22 +00:00
Err(e) => log::error!("Cannot instantiate output {}: {}", out_type, e),
}
2019-02-17 22:50:18 +00:00
}));
2019-01-30 22:11:51 +00:00
}
let output_senders = output_senders;
2019-01-30 15:26:05 +00:00
2019-02-17 22:50:18 +00:00
// Start all the threads
barrier.wait();
log::info!("Started rnetmon");
for t in &mon_threads {
t.thread().unpark();
}
for t in &output_threads {
t.thread().unpark();
}
2019-01-30 22:11:51 +00:00
// Dispatch messages
loop {
let message = mon_receiver.recv().unwrap();
for out in &output_senders {
out.send(message.clone()).unwrap();
}
}
2019-01-30 15:26:05 +00:00
}