Skip to content

Commit

Permalink
Performance and code improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
x0a1b committed Jun 28, 2020
1 parent 53f6376 commit 21e9e86
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 20 deletions.
63 changes: 63 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ edition = "2018"
[dependencies]
regex = "1"
structopt = "0.3.15"
notify = "4.0.12"
notify = "4.0.12"
parking_lot = "0.11"
8 changes: 4 additions & 4 deletions example_filters
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ Each line of the filters file is an expression that starts with ~, =, !=, or !~
The matches will be done in the order they appear and if anything matches it's piped to stdout right away

Any line that starts with `!~` implies does not match regex, e.g:
!~"time": \d+.\d{0,2}
!~\sfizzbuzz\n

Any line that starts with ~ implies match regex, e.g:
~"time": \d+.\d{3,}
~\s(fizz|buzz)\n

Any line that starts with `!=` implies does not contain text, e.g:
!=INFO
!=fizzbuzz

Any line that starts with `=` implies contain text, e.g:
="total-duration"
= buzz

Everything else is ignored, as you can see from plain text.
2 changes: 1 addition & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::path::PathBuf;

use structopt::StructOpt;

#[derive(Debug, StructOpt)]
#[derive(Debug, StructOpt, Clone)]
#[structopt(name = "drep", about = "Hot load regex log filter")]
pub struct CliOpts {
/// Activate debug mode
Expand Down
60 changes: 46 additions & 14 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::io;
use std::io::Write;
use std::sync::{Arc, Mutex};
use std::sync::Arc;
use std::sync::mpsc::channel;
use std::thread;
use std::time::Duration;

use notify::{RecursiveMode, Watcher, watcher};
use notify::{DebouncedEvent, RecursiveMode, Watcher, watcher};
use parking_lot::Mutex;
use structopt::StructOpt;

use cli::CliOpts;
Expand All @@ -16,41 +17,72 @@ mod errors;
mod cli;


fn is_update_event(ev: &DebouncedEvent) -> bool {
match ev {
DebouncedEvent::Write(_)
| DebouncedEvent::Create(_)
| DebouncedEvent::Remove(_)
| DebouncedEvent::Rename(_, _)
| DebouncedEvent::Chmod(_) => true,
_ => false
}
}

fn load_filters(path: &str, stderr: &mut io::Stderr) -> Vec<Filter> {
match Filter::load(path) {
Ok(res) => res,
Err(e) => {
writeln!(stderr, "Error loading filters {}, defaulting to empty filters", e).unwrap();
Vec::new()
}
}
}

fn watch_and_reload_filters(filters: Arc<Mutex<Vec<Filter>>>, path: &str) {
let mut stderr = io::stderr();
let (tx, rx) = channel();
let mut watcher = watcher(tx, Duration::from_secs(5)).unwrap();
let mut watcher = watcher(tx, Duration::from_millis(100)).unwrap();

watcher.watch(&path, RecursiveMode::Recursive).unwrap();
watcher.watch(&path, RecursiveMode::NonRecursive).unwrap();

loop {
let mut expressions: Vec<Filter> = Vec::new();
match rx.recv() {
Ok(_) => expressions = Filter::load(path).unwrap_or(expressions),
Ok(ev) => {
if is_update_event(&ev) {
let expressions = load_filters(path, &mut stderr);
let mut curr_filters = filters.lock();
*curr_filters = expressions;
}
}
Err(e) => writeln!(stderr, "Error: {}", e).unwrap()
}

let mut curr_filters = filters.lock().unwrap();
*curr_filters = expressions
}
}

fn watch_config(filters: &Arc<Mutex<Vec<Filter>>>, path: &str) {
let watch_filters = filters.clone();
let watch_path = path.to_owned();
let watch_path = String::from(path);
thread::spawn(move || {
watch_and_reload_filters(watch_filters, watch_path.as_str());
});
}

fn process_line(writer: &mut dyn io::Write, input: &mut String, filters: &Mutex<Vec<Filter>>) {
let filter_items = filters.lock().unwrap();
#[inline]
fn is_match(filters: &Mutex<Vec<Filter>>, input: &mut String) -> bool {
let filter_items = filters.lock();
for filter in filter_items.iter() {
if filter.is_match(input.as_str()) {
writer.write(input.as_bytes()).unwrap();
return;
return true;
}
}

return false;
}

fn process_line(writer: &mut dyn io::Write, input: &mut String, filters: &Mutex<Vec<Filter>>) {
if is_match(filters, input) {
writer.write(input.as_bytes()).unwrap();
}
}

fn main() {
Expand Down

0 comments on commit 21e9e86

Please sign in to comment.