Skip to content

Commit

Permalink
feat: add support for --condition
Browse files Browse the repository at this point in the history
  • Loading branch information
maximeborges authored and dekobon committed Nov 29, 2022
1 parent 52aadff commit c7aa27e
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 6 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ httpstatus = "0.1"
flate2 = "1.0"
colored = "1.9"
pager = "0.15"
quick-js = "0.4"

[dev-dependencies]
bytes = "0.4"
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ Bunyan Viewer supports the following features:

Bunyan Viewer does not yet support the following:
* Runtime log snooping via DTrace (`-p` flag)
* Conditional filtering (`-c, --condition` flag)

## Installation

Expand Down
42 changes: 42 additions & 0 deletions src/condition_filter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use core::fmt;

use quick_js::Context;

pub struct ConditionFilter {
context: Context,
condition: String,
}

impl ConditionFilter {
pub fn new<S>(condition: S) -> Self
where
S: Into<String>,
{
Self {
context: Context::new().unwrap(),
condition: condition.into(),
}
}
pub fn filter(&self, line: &str) -> bool {
self.context
.eval_as::<bool>(
format!("(function (){{return ({})}}).call({line})", self.condition).as_str(),
)
.unwrap()
}
}

impl fmt::Debug for ConditionFilter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ConditionFilter [`{}`]", self.condition)
}
}

impl Clone for ConditionFilter {
fn clone(&self) -> Self {
Self {
context: Context::new().unwrap(),
condition: self.condition.clone(),
}
}
}
14 changes: 10 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extern crate serde_json;

#[macro_use]
mod macros;
mod condition_filter;
mod date_deserializer;
mod divider_writer;
mod errors;
Expand All @@ -18,6 +19,8 @@ mod inspect_logger;
use crate::errors::LogLevelParseError;
use crate::inspect_logger::write_inspect_line;

pub use crate::condition_filter::ConditionFilter;

use std::borrow::Cow;
use std::fmt;
use std::io::{BufRead, Write};
Expand Down Expand Up @@ -213,6 +216,7 @@ pub struct LoggerOutputConfig {
pub is_strict: bool,
pub is_debug: bool,
pub level: Option<u16>,
pub condition_filter: Option<ConditionFilter>,
pub display_local_time: bool,
pub format: LogFormat,
}
Expand Down Expand Up @@ -330,10 +334,12 @@ where
serde_json::from_str(&trimmed);
match json_result {
Ok(log) => {
let write_log = if let Some(output_level) = output_config.level {
output_level <= log.level
} else {
true
let write_log = match output_config.level {
Some(output_level) => output_level <= log.level,
None => true,
} && match &output_config.condition_filter {
Some(condition_filter) => condition_filter.filter(line.as_str()),
None => true,
};

if write_log {
Expand Down
19 changes: 18 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ extern crate bunyan_view;
extern crate flate2;
extern crate pager;

use bunyan_view::{LogFormat, LogLevel, LoggerOutputConfig};
use bunyan_view::{ConditionFilter, LogFormat, LogLevel, LoggerOutputConfig};
use clap::{App, AppSettings, Arg, ArgMatches};
use flate2::read::GzDecoder;
use pager::Pager;
Expand Down Expand Up @@ -41,6 +41,20 @@ You can specify level *names* or the internal numeric values.")
.short("l")
.takes_value(true)
.required(false))
.arg(Arg::with_name("condition")
.help(r#"Run each log message through the condition and only show those that return truish.
E.g.:
-c 'this.pid == 123'
-c 'this.level == DEBUG'
-c 'this.msg.indexOf("boom") != -1'
"CONDITION" must be (somewhat) legal JS code.
`this` holds the log record.
The TRACE, DEBUG, ... FATAL values are defined to help with comparing `this.level`.
"#)
.long("condition")
.short("c")
.takes_value(true)
.required(false))
.arg(Arg::with_name("pager")
.help("Pipe output into `less` (or $PAGER if set), if stdout is a TTY. This overrides $BUNYAN_NO_PAGER.")
.long("pager")
Expand Down Expand Up @@ -109,6 +123,8 @@ You can specify level *names* or the internal numeric values.")
None => None,
};

let condition_filter = matches.value_of("condition").map(ConditionFilter::new);

let format = match matches.value_of("output") {
Some(output_string) => match output_string.to_ascii_lowercase().as_ref() {
"bunyan" => LogFormat::Json(0),
Expand Down Expand Up @@ -139,6 +155,7 @@ You can specify level *names* or the internal numeric values.")
is_strict: matches.is_present("strict"),
is_debug: matches.is_present("debug"),
level,
condition_filter,
display_local_time: matches.is_present("time-local"),
format,
};
Expand Down
1 change: 1 addition & 0 deletions tests/corpus_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ fn assert_equals_to_file(filename: &str, expected_filename: &str, format: LogFor
is_debug: false,
is_strict: false,
level: None,
condition_filter: None,
display_local_time: false,
format,
};
Expand Down

0 comments on commit c7aa27e

Please sign in to comment.