-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfilters.rs
124 lines (108 loc) · 3.04 KB
/
filters.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use chrono::NaiveDateTime;
use regex::{Regex, RegexBuilder};
use serde::{de::Visitor, Deserialize};
#[derive(Deserialize)]
pub enum StrFilter {
Equal(String),
Contains(String),
Match(Match),
InList(Vec<String>),
}
impl StrFilter {
pub fn check(&self, value: &str) -> bool {
match self {
StrFilter::Equal(s) => s == value,
StrFilter::Contains(s) => value.contains(s),
StrFilter::Match(m) => m.0.is_match(value),
StrFilter::InList(s) => s.iter().any(|x| x == value),
}
}
}
// performance is better with Box
pub struct Match(Box<Regex>);
impl<'de> Deserialize<'de> for Match {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_string(MatchVisitor {})
}
}
struct MatchVisitor {}
impl Visitor<'_> for MatchVisitor {
type Value = Match;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a regular expression")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
RegexBuilder::new(v)
.crlf(true)
.case_insensitive(true)
.dot_matches_new_line(true)
.build()
.map(|regex| Match(Box::new(regex)))
.map_err(serde::de::Error::custom)
}
}
#[derive(Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct PropFilter {
pub name: String,
pub filter: StrFilter,
}
impl PropFilter {
pub fn check(&self, props: &[(&str, tech_log_parser::LogStr<'_>)]) -> bool {
for (name, value) in props {
if name.eq_ignore_ascii_case(&self.name) && self.filter.check(&value.str()) {
return true;
}
}
false
}
}
#[derive(Deserialize)]
pub enum DataFilter {
GreaterOrEqual(NaiveDateTime),
LessOrEqual(NaiveDateTime),
}
impl DataFilter {
pub fn check(&self, value: &NaiveDateTime) -> bool {
match self {
DataFilter::GreaterOrEqual(date) => value >= date,
DataFilter::LessOrEqual(date) => value <= date,
}
}
}
#[derive(Deserialize)]
pub enum DurationFilter {
GreaterOrEqual(u128),
LessOrEqual(u128),
}
impl DurationFilter {
pub fn check(&self, value: &u128) -> bool {
match self {
DurationFilter::GreaterOrEqual(dur) => value >= dur,
DurationFilter::LessOrEqual(dur) => value <= dur,
}
}
}
#[derive(Deserialize)]
pub enum Filter {
Date(DataFilter),
Duration(DurationFilter),
Name(StrFilter),
Prop(PropFilter),
}
impl Filter {
pub fn check(&self, event: &tech_log_parser::Event) -> bool {
match self {
Filter::Date(filter) => filter.check(&event.date),
Filter::Duration(filter) => filter.check(&event.duration.as_micros()),
Filter::Name(filter) => filter.check(event.name),
Filter::Prop(filter) => filter.check(event.properties.as_slice()),
}
}
}