Skip to content

Commit 8a560fa

Browse files
committed
simplify implementation
Signed-off-by: Jean Mertz <[email protected]>
1 parent e830395 commit 8a560fa

File tree

2 files changed

+55
-83
lines changed

2 files changed

+55
-83
lines changed

aw-query/src/datatype.rs

+39-49
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::str::FromStr as _;
55
use super::functions;
66
use super::QueryError;
77
use aw_models::Event;
8-
use aw_transform::classify::{KeyValueRule, LogicalOperator, LogicalRule, RegexRule, Rule};
8+
use aw_transform::classify::{LogicalOperator, LogicalRule, RegexRule, Rule};
99

1010
use serde::{Serialize, Serializer};
1111
use serde_json::value::Value;
@@ -301,61 +301,42 @@ impl TryFrom<&DataType> for Rule {
301301

302302
match rtype.as_str() {
303303
"none" => Ok(Self::None),
304-
"or" | "and" => {
305-
let Some(rules) = obj.get("rules") else {
306-
return Err(QueryError::InvalidFunctionParameters(format!(
307-
"{} rule is missing the 'rules' field",
308-
rtype
309-
)));
310-
};
311-
312-
let rules = match rules {
313-
DataType::List(rules) => rules
314-
.iter()
315-
.map(Rule::try_from)
316-
.collect::<Result<Vec<_>, _>>()?,
317-
_ => {
318-
return Err(QueryError::InvalidFunctionParameters(format!(
319-
"the rules field of the {} rule is not a list",
320-
rtype
321-
)))
322-
}
323-
};
324-
325-
let operator = LogicalOperator::from_str(rtype)
326-
.map_err(QueryError::InvalidFunctionParameters)?;
327-
328-
Ok(Rule::Logical(LogicalRule::new(rules, operator)))
329-
}
304+
"or" | "and" => parse_logical_rule(obj, rtype),
330305
"regex" => parse_regex_rule(obj),
331-
"keyvalue" => {
332-
let Some(rules) = obj.get("rules") else {
333-
return Err(QueryError::InvalidFunctionParameters(
334-
"keyval rule is missing the 'rules' field".to_string(),
335-
));
336-
};
337-
338-
let rules = match rules {
339-
DataType::Dict(rules) => rules
340-
.iter()
341-
.map(|(k, v)| Rule::try_from(v).map(|v| (k.to_owned(), v)))
342-
.collect::<Result<HashMap<_, _>, _>>()?,
343-
_ => {
344-
return Err(QueryError::InvalidFunctionParameters(
345-
"the rules field of the keyval rule is not a dict".to_string(),
346-
))
347-
}
348-
};
349-
350-
Ok(Rule::KeyValue(KeyValueRule::new(rules)))
351-
}
352306
_ => Err(QueryError::InvalidFunctionParameters(format!(
353307
"Unknown rule type '{rtype}'"
354308
))),
355309
}
356310
}
357311
}
358312

313+
fn parse_logical_rule(obj: &HashMap<String, DataType>, rtype: &String) -> Result<Rule, QueryError> {
314+
let Some(rules) = obj.get("rules") else {
315+
return Err(QueryError::InvalidFunctionParameters(format!(
316+
"{} rule is missing the 'rules' field",
317+
rtype
318+
)));
319+
};
320+
321+
let rules = match rules {
322+
DataType::List(rules) => rules
323+
.iter()
324+
.map(Rule::try_from)
325+
.collect::<Result<Vec<_>, _>>()?,
326+
_ => {
327+
return Err(QueryError::InvalidFunctionParameters(format!(
328+
"the rules field of the {} rule is not a list",
329+
rtype
330+
)))
331+
}
332+
};
333+
334+
let operator =
335+
LogicalOperator::from_str(rtype).map_err(QueryError::InvalidFunctionParameters)?;
336+
337+
Ok(Rule::Logical(LogicalRule::new(rules, operator)))
338+
}
339+
359340
fn parse_regex_rule(obj: &HashMap<String, DataType>) -> Result<Rule, QueryError> {
360341
let regex_val = match obj.get("regex") {
361342
Some(regex_val) => regex_val,
@@ -385,7 +366,16 @@ fn parse_regex_rule(obj: &HashMap<String, DataType>) -> Result<Rule, QueryError>
385366
))
386367
}
387368
};
388-
let regex_rule = match RegexRule::new(regex_str, *ignore_case) {
369+
let match_field = match obj.get("field") {
370+
Some(DataType::String(v)) => Some(v.to_owned()),
371+
None => None,
372+
_ => {
373+
return Err(QueryError::InvalidFunctionParameters(
374+
"the `field` field of the regex rule is not a string".to_string(),
375+
))
376+
}
377+
};
378+
let regex_rule = match RegexRule::new(regex_str, *ignore_case, match_field) {
389379
Ok(regex_rule) => regex_rule,
390380
Err(err) => {
391381
return Err(QueryError::RegexCompileError(format!(

aw-transform/src/classify.rs

+16-34
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{collections::HashMap, str::FromStr};
1+
use std::str::FromStr;
22

33
/// Transforms for classifying (tagging and categorizing) events.
44
///
@@ -10,7 +10,6 @@ pub enum Rule {
1010
None,
1111
Logical(LogicalRule),
1212
Regex(RegexRule),
13-
KeyValue(KeyValueRule),
1413
}
1514

1615
impl RuleTrait for Rule {
@@ -19,7 +18,6 @@ impl RuleTrait for Rule {
1918
Rule::None => false,
2019
Rule::Logical(rule) => rule.matches(event),
2120
Rule::Regex(rule) => rule.matches(event),
22-
Rule::KeyValue(rule) => rule.matches(event),
2321
}
2422
}
2523
}
@@ -30,10 +28,15 @@ trait RuleTrait {
3028

3129
pub struct RegexRule {
3230
regex: Regex,
31+
field: Option<String>,
3332
}
3433

3534
impl RegexRule {
36-
pub fn new(regex_str: &str, ignore_case: bool) -> Result<RegexRule, fancy_regex::Error> {
35+
pub fn new(
36+
regex_str: &str,
37+
ignore_case: bool,
38+
field: Option<String>,
39+
) -> Result<RegexRule, fancy_regex::Error> {
3740
// can't use `RegexBuilder::case_insensitive` because it's not supported by fancy_regex,
3841
// so we need to prefix with `(?i)` to make it case insensitive.
3942
let regex = if ignore_case {
@@ -43,7 +46,7 @@ impl RegexRule {
4346
Regex::new(regex_str)?
4447
};
4548

46-
Ok(RegexRule { regex })
49+
Ok(RegexRule { regex, field })
4750
}
4851
}
4952

@@ -56,40 +59,19 @@ impl RuleTrait for RegexRule {
5659
fn matches(&self, event: &Event) -> bool {
5760
event
5861
.data
59-
.values()
60-
.filter(|val| val.is_string())
61-
.any(|val| self.regex.is_match(val.as_str().unwrap()).unwrap())
62+
.iter()
63+
.filter(|(field, val)| {
64+
self.field.as_ref().map(|v| &v == field).unwrap_or(true) && val.is_string()
65+
})
66+
.any(|(_, val)| self.regex.is_match(val.as_str().unwrap()).unwrap())
6267
}
6368
}
6469

6570
impl From<Regex> for Rule {
6671
fn from(re: Regex) -> Self {
67-
Rule::Regex(RegexRule { regex: re })
68-
}
69-
}
70-
71-
pub struct KeyValueRule {
72-
rules: HashMap<String, Rule>,
73-
}
74-
75-
impl KeyValueRule {
76-
pub fn new(rules: HashMap<String, Rule>) -> Self {
77-
Self { rules }
78-
}
79-
}
80-
81-
impl RuleTrait for KeyValueRule {
82-
fn matches(&self, event: &Event) -> bool {
83-
self.rules.iter().all(|(key, rule)| {
84-
event
85-
.data
86-
.get(key)
87-
.filter(|_| {
88-
let mut ev = event.clone();
89-
ev.data.retain(|k, _| k == key);
90-
rule.matches(&ev)
91-
})
92-
.is_some()
72+
Rule::Regex(RegexRule {
73+
regex: re,
74+
field: None,
9375
})
9476
}
9577
}

0 commit comments

Comments
 (0)