added JSONL output option #694
This commit is contained in:
@@ -213,8 +213,9 @@ fn emit_csv<W: std::io::Write>(
|
|||||||
let disp_wtr = BufferWriter::stdout(ColorChoice::Always);
|
let disp_wtr = BufferWriter::stdout(ColorChoice::Always);
|
||||||
let mut disp_wtr_buf = disp_wtr.buffer();
|
let mut disp_wtr_buf = disp_wtr.buffer();
|
||||||
let json_output_flag = configs::CONFIG.read().unwrap().args.json_timeline;
|
let json_output_flag = configs::CONFIG.read().unwrap().args.json_timeline;
|
||||||
|
let jsonl_output_flag = configs::CONFIG.read().unwrap().args.jsonl_timeline;
|
||||||
|
|
||||||
let mut wtr = if json_output_flag {
|
let mut wtr = if json_output_flag || jsonl_output_flag {
|
||||||
WriterBuilder::new()
|
WriterBuilder::new()
|
||||||
.delimiter(b'\n')
|
.delimiter(b'\n')
|
||||||
.double_quote(false)
|
.double_quote(false)
|
||||||
@@ -293,8 +294,9 @@ fn emit_csv<W: std::io::Write>(
|
|||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
} else if json_output_flag {
|
} else if json_output_flag {
|
||||||
|
// JSON output
|
||||||
wtr.write_field(" {")?;
|
wtr.write_field(" {")?;
|
||||||
wtr.write_field(&output_json_str(&detect_info.ext_field, &profile))?;
|
wtr.write_field(&output_json_str(&detect_info.ext_field, &profile, jsonl_output_flag))?;
|
||||||
if processed_message_cnt != message::MESSAGES._len() - 1
|
if processed_message_cnt != message::MESSAGES._len() - 1
|
||||||
|| info_idx != detect_infos.len() - 1
|
|| info_idx != detect_infos.len() - 1
|
||||||
{
|
{
|
||||||
@@ -302,6 +304,9 @@ fn emit_csv<W: std::io::Write>(
|
|||||||
} else {
|
} else {
|
||||||
wtr.write_field(" }")?;
|
wtr.write_field(" }")?;
|
||||||
}
|
}
|
||||||
|
} else if jsonl_output_flag {
|
||||||
|
// JSONL output format
|
||||||
|
wtr.write_field(format!("{{ {} }}", &output_json_str(&detect_info.ext_field, &profile, jsonl_output_flag)))?;
|
||||||
} else {
|
} else {
|
||||||
// csv output format
|
// csv output format
|
||||||
if plus_header {
|
if plus_header {
|
||||||
@@ -914,6 +919,7 @@ fn _convert_valid_json_str(input: &[&str], concat_flag: bool) -> String {
|
|||||||
fn output_json_str(
|
fn output_json_str(
|
||||||
ext_field: &LinkedHashMap<String, String>,
|
ext_field: &LinkedHashMap<String, String>,
|
||||||
profile: &LinkedHashMap<String, String>,
|
profile: &LinkedHashMap<String, String>,
|
||||||
|
jsonl_output_flag: bool,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut target: Vec<String> = vec![];
|
let mut target: Vec<String> = vec![];
|
||||||
for (k, v) in ext_field.iter() {
|
for (k, v) in ext_field.iter() {
|
||||||
@@ -921,8 +927,7 @@ fn output_json_str(
|
|||||||
let vec_data = _get_json_vec(output_value_fmt, v);
|
let vec_data = _get_json_vec(output_value_fmt, v);
|
||||||
if vec_data.is_empty() {
|
if vec_data.is_empty() {
|
||||||
let tmp_val: Vec<&str> = v.split(": ").collect();
|
let tmp_val: Vec<&str> = v.split(": ").collect();
|
||||||
let output_val =
|
let output_val = _convert_valid_json_str(&tmp_val, output_value_fmt.contains("%RecordInformation%"));
|
||||||
_convert_valid_json_str(&tmp_val, output_value_fmt.contains("%RecordInformation%"));
|
|
||||||
target.push(_create_json_output_format(
|
target.push(_create_json_output_format(
|
||||||
k,
|
k,
|
||||||
&output_val,
|
&output_val,
|
||||||
@@ -984,7 +989,9 @@ fn output_json_str(
|
|||||||
let output_tmp = format!("{}: {}", tmp, output_value_stock);
|
let output_tmp = format!("{}: {}", tmp, output_value_stock);
|
||||||
let output: Vec<&str> = output_tmp.split(": ").collect();
|
let output: Vec<&str> = output_tmp.split(": ").collect();
|
||||||
let key = _convert_valid_json_str(&[output[0]], false);
|
let key = _convert_valid_json_str(&[output[0]], false);
|
||||||
let fmted_val = _convert_valid_json_str(&output, false);
|
let fmted_val =
|
||||||
|
_convert_valid_json_str(&output, false)
|
||||||
|
;
|
||||||
target.push(_create_json_output_format(
|
target.push(_create_json_output_format(
|
||||||
&key,
|
&key,
|
||||||
&fmted_val,
|
&fmted_val,
|
||||||
@@ -999,7 +1006,9 @@ fn output_json_str(
|
|||||||
let output_tmp = format!("{}: {}", tmp, output_value_stock);
|
let output_tmp = format!("{}: {}", tmp, output_value_stock);
|
||||||
let output: Vec<&str> = output_tmp.split(": ").collect();
|
let output: Vec<&str> = output_tmp.split(": ").collect();
|
||||||
let key = _convert_valid_json_str(&[output[0]], false);
|
let key = _convert_valid_json_str(&[output[0]], false);
|
||||||
let fmted_val = _convert_valid_json_str(&output, false);
|
let fmted_val =
|
||||||
|
_convert_valid_json_str(&output, false)
|
||||||
|
;
|
||||||
target.push(_create_json_output_format(
|
target.push(_create_json_output_format(
|
||||||
&key,
|
&key,
|
||||||
&fmted_val,
|
&fmted_val,
|
||||||
@@ -1034,7 +1043,11 @@ fn output_json_str(
|
|||||||
}
|
}
|
||||||
value.push("\n ]".to_string());
|
value.push("\n ]".to_string());
|
||||||
|
|
||||||
let fmted_val = value.join("");
|
let fmted_val = if jsonl_output_flag {
|
||||||
|
value.iter().map(|x| x.replace('\n', "")).join("")
|
||||||
|
} else {
|
||||||
|
value.join("")
|
||||||
|
};
|
||||||
target.push(_create_json_output_format(
|
target.push(_create_json_output_format(
|
||||||
&key,
|
&key,
|
||||||
&fmted_val,
|
&fmted_val,
|
||||||
@@ -1043,7 +1056,13 @@ fn output_json_str(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if jsonl_output_flag {
|
||||||
|
// JSONL output
|
||||||
|
target.into_iter().map(|x| x.replace(" ", "")).join(",")
|
||||||
|
} else {
|
||||||
|
// JSON format output
|
||||||
target.join(",\n")
|
target.join(",\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -241,6 +241,10 @@ pub struct Config {
|
|||||||
#[clap(help_heading = Some("OUTPUT"), short = 'j', long = "json", requires = "output")]
|
#[clap(help_heading = Some("OUTPUT"), short = 'j', long = "json", requires = "output")]
|
||||||
pub json_timeline: bool,
|
pub json_timeline: bool,
|
||||||
|
|
||||||
|
/// Save the timeline in JSONL format (ex: -J -o results.jsonl)
|
||||||
|
#[clap(help_heading = Some("OUTPUT"), short = 'J', long = "jsonl", requires = "output")]
|
||||||
|
pub jsonl_timeline: bool,
|
||||||
|
|
||||||
/// Do not display result summary
|
/// Do not display result summary
|
||||||
#[clap(help_heading = Some("DISPLAY-SETTINGS"), long = "no-summary")]
|
#[clap(help_heading = Some("DISPLAY-SETTINGS"), long = "no-summary")]
|
||||||
pub no_summary: bool,
|
pub no_summary: bool,
|
||||||
|
|||||||
Reference in New Issue
Block a user