diff --git a/src/afterfact.rs b/src/afterfact.rs index 80f2188e0..d75c8ca9c 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -411,6 +411,7 @@ fn emit_csv( jsonl_output_flag, GEOIP_DB_PARSER.read().unwrap().is_some(), remove_duplicate_data_flag, + detect_info.is_condition, &[&detect_info.details_convert_map, &prev_details_convert_map], ); prev_message = result.1; @@ -425,6 +426,7 @@ fn emit_csv( jsonl_output_flag, GEOIP_DB_PARSER.read().unwrap().is_some(), remove_duplicate_data_flag, + detect_info.is_condition, &[&detect_info.details_convert_map, &prev_details_convert_map], ); prev_message = result.1; @@ -1431,6 +1433,7 @@ pub fn output_json_str( jsonl_output_flag: bool, is_included_geo_ip: bool, remove_duplicate_flag: bool, + is_condition: bool, details_infos: &[&HashMap>], ) -> (String, HashMap) { let mut target: Vec = vec![]; @@ -1538,23 +1541,71 @@ pub fn output_json_str( } Profile::Details(_) | Profile::AllFieldInfo(_) | Profile::ExtraFieldInfo(_) => { let mut output_stock: Vec = vec![]; - output_stock.push(format!(" \"{key}\": {{")); let details_key = match profile { Profile::Details(_) => "Details", Profile::AllFieldInfo(_) => "AllFieldInfo", Profile::ExtraFieldInfo(_) => "ExtraFieldInfo", _ => "", }; - // 個々の段階でDetails, AllFieldInfo, ExtraFieldInfoの要素はdetails_infosに格納されているのでunwrapする - let details_stocks = details_infos[0] + let mut details_target_stocks = vec![]; + for details_info in details_infos { + let details_target_stock = + details_info.get(&CompactString::from(format!("#{details_key}"))); + if let Some(tmp_stock) = details_target_stock { + details_target_stocks.extend(tmp_stock); + } + } + + if details_infos[0] .get(&CompactString::from(format!("#{details_key}"))) - .unwrap(); - for (idx, contents) in details_stocks.iter().enumerate() { + .is_none() + { + continue; + } + // aggregation conditionの場合は分解せずにそのまま出力する + if is_condition && details_key == "Details" { + if details_target_stocks.is_empty() { + output_stock.push(format!( + "{}", + _create_json_output_format( + &key, + "-", + key.starts_with('\"'), + false, + 4 + ) + )); + } else { + let joined_details_target_stock = + details_target_stocks.iter().join(" "); + let output_str_details_target_stock = + joined_details_target_stock.trim(); + output_stock.push(format!( + "{}", + _create_json_output_format( + &key, + output_str_details_target_stock, + key.starts_with('\"'), + output_str_details_target_stock.starts_with('\"'), + 4 + ) + )); + } + if jsonl_output_flag { + target.push(output_stock.join("")); + } else { + target.push(output_stock.join("\n")); + } + continue; + } else { + output_stock.push(format!(" \"{key}\": {{")); + }; + for (idx, contents) in details_target_stocks.iter().enumerate() { let (key, value) = contents.split_once(": ").unwrap_or_default(); let output_key = _convert_valid_json_str(&[key], false); let fmted_val = _convert_valid_json_str(&[value], false); - if idx != details_stocks.len() - 1 { + if idx != details_target_stocks.len() - 1 { output_stock.push(format!( "{},", _create_json_output_format( diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 8b576792a..745fdc66a 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -1150,7 +1150,7 @@ impl Detection { for alias in target_alias { let (search_data, _) = message::parse_message( record, - CompactString::from(alias), + &CompactString::from(alias), eventkey_alias, is_csv_output, &FieldDataMapKey::default(), diff --git a/src/detections/message.rs b/src/detections/message.rs index bc2e0b851..ed1e28856 100644 --- a/src/detections/message.rs +++ b/src/detections/message.rs @@ -129,7 +129,7 @@ pub fn insert( //ここの段階でdetailsの内容でaliasを置き換えた内容と各種、key,valueの組み合わせのmapを取得する let (removed_sp_parsed_detail, details_in_record) = parse_message( event_record, - output, + &output, eventkey_alias, is_json_timeline, field_data_map_key, @@ -186,6 +186,16 @@ pub fn insert( "#Details".into(), detect_info.detail.split(" ¦ ").map(|x| x.into()).collect(), ); + if is_agg { + if output != "-" { + record_details_info_map.insert("#Details".into(), vec![output.clone()]); + } else if detect_info.detail != "-" { + record_details_info_map + .insert("#Details".into(), vec![detect_info.detail.clone()]); + } else { + record_details_info_map.insert("#Details".into(), vec!["-".into()]); + } + } // メモリの節約のためにDetailsの中身を空にする detect_info.detail = CompactString::default(); } @@ -285,7 +295,7 @@ pub fn insert( if let Some(p) = profile_converter.get(key.as_str()) { let (parsed_message, _) = &parse_message( event_record, - CompactString::new(p.to_value()), + &CompactString::new(p.to_value()), eventkey_alias, is_json_timeline, field_data_map_key, @@ -304,7 +314,7 @@ pub fn insert( /// メッセージ内の%で囲まれた箇所をエイリアスとしてレコード情報を参照して置き換える関数 pub fn parse_message( event_record: &Value, - output: CompactString, + output: &CompactString, eventkey_alias: &EventKeyAliasConfig, json_timeline_flag: bool, field_data_map_key: &FieldDataMapKey, @@ -520,7 +530,7 @@ mod tests { assert_eq!( parse_message( &event_record, - CompactString::new("commandline:%CommandLine% computername:%ComputerName%"), + &CompactString::new("commandline:%CommandLine% computername:%ComputerName%"), &load_eventkey_alias( utils::check_setting_path( &CURRENT_EXE_PATH.to_path_buf(), @@ -557,7 +567,7 @@ mod tests { assert_eq!( parse_message( &event_record, - CompactString::new("alias:%NoAlias%"), + &CompactString::new("alias:%NoAlias%"), &load_eventkey_alias( utils::check_setting_path( &CURRENT_EXE_PATH.to_path_buf(), @@ -600,7 +610,7 @@ mod tests { assert_eq!( parse_message( &event_record, - CompactString::new("NoExistAlias:%NoAliasNoHit%"), + &CompactString::new("NoExistAlias:%NoAliasNoHit%"), &load_eventkey_alias( utils::check_setting_path( &CURRENT_EXE_PATH.to_path_buf(), @@ -642,7 +652,7 @@ mod tests { assert_eq!( parse_message( &event_record, - CompactString::new("commandline:%CommandLine% computername:%ComputerName%"), + &CompactString::new("commandline:%CommandLine% computername:%ComputerName%"), &load_eventkey_alias( utils::check_setting_path( &CURRENT_EXE_PATH.to_path_buf(), @@ -689,7 +699,7 @@ mod tests { assert_eq!( parse_message( &event_record, - CompactString::new("commandline:%CommandLine% data:%Data%"), + &CompactString::new("commandline:%CommandLine% data:%Data%"), &load_eventkey_alias( utils::check_setting_path( &CURRENT_EXE_PATH.to_path_buf(), @@ -736,7 +746,7 @@ mod tests { assert_eq!( parse_message( &event_record, - CompactString::new("commandline:%CommandLine% data:%Data[2]%"), + &CompactString::new("commandline:%CommandLine% data:%Data[2]%"), &load_eventkey_alias( utils::check_setting_path( &CURRENT_EXE_PATH.to_path_buf(), @@ -783,7 +793,7 @@ mod tests { assert_eq!( parse_message( &event_record, - CompactString::new("commandline:%CommandLine% data:%Data[0]%"), + &CompactString::new("commandline:%CommandLine% data:%Data[0]%"), &load_eventkey_alias( utils::check_setting_path( &CURRENT_EXE_PATH.to_path_buf(), diff --git a/src/timeline/search.rs b/src/timeline/search.rs index 893293c41..ae3300e2e 100644 --- a/src/timeline/search.rs +++ b/src/timeline/search.rs @@ -465,6 +465,7 @@ pub fn search_result_dsp_msg( jsonl_output, false, false, + false, &[&HashMap::default(), &HashMap::default()], );