Skip to content

Commit

Permalink
Optimize the filter
Browse files Browse the repository at this point in the history
  • Loading branch information
borney committed Jun 2, 2023
1 parent 32fa623 commit 68c3214
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 111 deletions.
22 changes: 5 additions & 17 deletions src/filter/buffer_filter.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
use crate::filter::Filter;
use crate::log::Log;
use async_trait::async_trait;
use std::sync::Arc;

pub(crate) struct BufferFilter {
filter: Option<Arc<dyn Filter>>,
buffers: Vec<String>,
all: bool,
}

impl BufferFilter {
#[allow(dead_code)]
pub(crate) fn new(buffers: Vec<String>, filter: Option<Arc<dyn Filter>>) -> Self {
pub(crate) fn new(buffers: Vec<String>) -> Self {
let mut s = Self {
buffers,
filter,
all: false,
};

Expand All @@ -26,26 +23,17 @@ impl BufferFilter {

#[async_trait]
impl Filter for BufferFilter {
async fn filter(&self, mut log: Log) -> Option<Log> {
if let Some(f) = &self.filter {
let f = Arc::clone(f);
if let Some(r) = f.filter(log).await {
log = r;
} else {
return None;
}
}

async fn filter(&self, log: &Log) -> bool {
if self.all {
return Some(log);
return false;
}

for b in &self.buffers {
if b == &log.buffer {
return Some(log);
return false;
}
}

None
true
}
}
24 changes: 5 additions & 19 deletions src/filter/level_filter.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,28 @@
use crate::filter::Filter;
use crate::log::{Level, Log};
use async_trait::async_trait;
use std::sync::Arc;

pub(crate) struct LevelFilter {
filter: Option<Arc<dyn Filter>>,
level: Level,
}

impl LevelFilter {
#[allow(dead_code)]
pub(crate) fn new(level: Level, filter: Option<Arc<dyn Filter>>) -> Self {
Self { level, filter }
pub(crate) fn new(level: Level) -> Self {
Self { level }
}
}

#[async_trait]
impl Filter for LevelFilter {
async fn filter(&self, mut log: Log) -> Option<Log> {
if let Some(f) = &self.filter {
let f = Arc::clone(f);
if let Some(r) = f.filter(log).await {
log = r;
} else {
return None;
}
}

async fn filter(&self, log: &Log) -> bool {
use std::str::FromStr;

if let Ok(level) = Level::from_str(&log.level) {
if level >= self.level {
Some(log)
} else {
None
return false;
}
} else {
None
}
true
}
}
6 changes: 1 addition & 5 deletions src/filter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,11 @@ pub(crate) use tag_filter::TagFilter;
use crate::log::Log;

use async_trait::async_trait;
use std::sync::Arc;

#[allow(dead_code)]
pub(crate) type ArcFilter = Arc<dyn Filter>;

///
/// Filter trait used to filter log
///
#[async_trait]
pub trait Filter: Send + Sync {
async fn filter(&self, log: Log) -> Option<Log>;
async fn filter(&self, log: &Log) -> bool;
}
24 changes: 6 additions & 18 deletions src/filter/pid_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,19 @@ use crate::log::Log;
use async_trait::async_trait;
use dashmap::DashSet;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use tokio::io::AsyncBufReadExt;
use tokio::process::{Child, Command};

pub(crate) struct PidFilter {
filter: Option<Arc<dyn Filter>>,
process: DashSet<String>,
pids: DashSet<String>,
first_filter: AtomicBool,
}

impl PidFilter {
#[allow(dead_code)]
pub(crate) fn new(process: Vec<String>, filter: Option<Arc<dyn Filter>>) -> Self {
pub(crate) fn new(process: Vec<String>) -> Self {
Self {
filter,
process: DashSet::from_iter(process.into_iter()),
pids: DashSet::new(),
first_filter: AtomicBool::new(true),
Expand All @@ -36,18 +33,9 @@ impl PidFilter {

#[async_trait]
impl Filter for PidFilter {
async fn filter(&self, mut log: Log) -> Option<Log> {
if let Some(f) = &self.filter {
let f = Arc::clone(f);
if let Some(r) = f.filter(log).await {
log = r;
} else {
return None;
}
}

async fn filter(&self, log: &Log) -> bool {
if self.process.is_empty() {
return Some(log);
return false;
}

if self.first_filter.load(Ordering::Acquire) && self.pids.is_empty() {
Expand Down Expand Up @@ -102,15 +90,15 @@ impl Filter for PidFilter {
_ => {}
}

let mut r = None;
let mut r = true;

if self.pids.contains(&log.pid) {
r = Some(log);
r = false;
} else {
for p in self.pids.iter() {
let ptr = p.key().as_str();
if log.is_events() && log.message.contains(ptr) {
r = Some(log);
r = false;
break;
}
}
Expand Down
25 changes: 5 additions & 20 deletions src/filter/revert_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@ use crate::filter::Filter;
use crate::log::Log;
use async_trait::async_trait;
use regex::{Error, Regex, RegexBuilder};
use std::sync::Arc;

pub(crate) struct RevertFilter {
filter: Option<Arc<dyn Filter>>,
revert: String,
re: Result<Regex, Error>,
}

impl RevertFilter {
#[allow(dead_code)]
pub(crate) fn new(revert: String, ignore: bool, filter: Option<Arc<dyn Filter>>) -> Self {
pub(crate) fn new(revert: String, ignore: bool) -> Self {
Self {
filter,
revert: revert.clone(),
re: RegexBuilder::new(&revert).case_insensitive(ignore).build(),
}
Expand All @@ -23,28 +20,16 @@ impl RevertFilter {

#[async_trait]
impl Filter for RevertFilter {
async fn filter(&self, mut log: Log) -> Option<Log> {
if let Some(f) = &self.filter {
let f = Arc::clone(f);
if let Some(r) = f.filter(log).await {
log = r;
} else {
return None;
}
}

async fn filter(&self, log: &Log) -> bool {
if self.revert.is_empty() {
return Some(log);
return false;
}

if let Ok(re) = &self.re {
if re.is_match(&log.tag) || re.is_match(&log.message) {
None
} else {
Some(log)
return true;
}
} else {
Some(log)
}
false
}
}
24 changes: 6 additions & 18 deletions src/filter/tag_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,16 @@ use crate::log::Log;
use anyhow::Result;
use async_trait::async_trait;
use regex::{Error, Regex, RegexBuilder};
use std::sync::Arc;

pub(crate) struct TagFilter {
filter: Option<Arc<dyn Filter>>,
tag: String,
re: Result<Regex, Error>,
}

impl TagFilter {
#[allow(dead_code)]
pub(crate) fn new(tag: String, ignore: bool, filter: Option<Arc<dyn Filter>>) -> Self {
pub(crate) fn new(tag: String, ignore: bool) -> Self {
Self {
filter,
tag: tag.clone(),
re: RegexBuilder::new(&tag).case_insensitive(ignore).build(),
}
Expand All @@ -24,28 +21,19 @@ impl TagFilter {

#[async_trait]
impl Filter for TagFilter {
async fn filter(&self, mut log: Log) -> Option<Log> {
if let Some(f) = &self.filter {
let f = Arc::clone(f);
if let Some(r) = f.filter(log).await {
log = r;
} else {
return None;
}
}

async fn filter(&self, log: &Log) -> bool {
if self.tag.is_empty() {
return Some(log);
return false;
}

if let Ok(re) = &self.re {
if re.is_match(&log.tag) || re.is_match(&log.message) {
Some(log)
false
} else {
None
true
}
} else {
Some(log)
false
}
}
}
36 changes: 22 additions & 14 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use crate::cli::Cli;
use crate::filter::{ArcFilter, BufferFilter, LevelFilter, PidFilter, RevertFilter, TagFilter};
use crate::filter::{BufferFilter, Filter, LevelFilter, PidFilter, RevertFilter, TagFilter};
use crate::sink::{FileSink, Sink, TerminalSink};
use crate::source::{ADBSource, Source};
use anyhow::Result;
use futures::StreamExt;
use std::sync::Arc;
use tokio::process::{Child, Command};

mod cli;
Expand Down Expand Up @@ -38,23 +37,26 @@ async fn main() {
}

async fn fetch(cli: Cli) {
let source = Arc::new(ADBSource::new(if cli.device.is_empty() {
let source = ADBSource::new(if cli.device.is_empty() {
None
} else {
Some(cli.device)
}));
});

let filter: ArcFilter = Arc::new(PidFilter::new(cli.process, None));
let filter: ArcFilter = Arc::new(BufferFilter::new(cli.buffers, Some(filter)));
let filter: ArcFilter = Arc::new(LevelFilter::new(cli.level, Some(filter)));
let filter: ArcFilter = Arc::new(TagFilter::new(cli.tag, cli.ignore, Some(filter)));
let filter: ArcFilter = Arc::new(RevertFilter::new(cli.revert, cli.ignore, Some(filter)));
let filters: Vec<Box<dyn Filter>> = vec![
Box::new(PidFilter::new(cli.process)),
Box::new(BufferFilter::new(cli.buffers)),
Box::new(LevelFilter::new(cli.level)),
Box::new(TagFilter::new(cli.tag, cli.ignore)),
Box::new(RevertFilter::new(cli.revert, cli.ignore)),
];

let mut sinks: Vec<Arc<dyn Sink>> = Vec::new();
sinks.push(Arc::new(TerminalSink::new(cli.color, cli.tag_width)));
let mut sinks: Vec<Box<dyn Sink>> = Vec::new();

sinks.push(Box::new(TerminalSink::new(cli.color, cli.tag_width)));
if let Some(file) = cli.output {
if let Ok(file) = FileSink::new(file).await {
sinks.push(Arc::new(file));
sinks.push(Box::new(file));
}
}

Expand All @@ -63,9 +65,15 @@ async fn fetch(cli: Cli) {
while let Some(r) = logs.next().await {
match r {
Ok(log) => {
let l = { filter.filter(log).await };
let mut is_filter = false;
for filter in &filters {
if filter.filter(&log).await {
is_filter = true;
break;
}
}

if let Some(log) = l {
if !is_filter {
for sink in &sinks {
sink.write(log.clone()).await;
}
Expand Down

0 comments on commit 68c3214

Please sign in to comment.