Skip to content

Commit dbe338d

Browse files
committed
Add is_log and is_metric conditions
Signed-off-by: Ashley Jeffs <ash@jeffail.uk>
1 parent c9a4fcf commit dbe338d

File tree

8 files changed

+177
-15
lines changed

8 files changed

+177
-15
lines changed

.meta/_partials/_conditions.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
[<%= namespace %>.type]
22
type = "string"
33
required = true
4-
examples = ["check_fields"]
4+
examples = ["check_fields", "is_log", "is_metric"]
55
common = true
66
description = """\
7-
The type of the condition to execute. Currently only the `check_fields` type is \
8-
available.\
7+
The type of the condition to execute.\
98
"""
109

1110
[<%= namespace %>."`<field_name>`.eq"]
@@ -14,6 +13,7 @@ examples = [
1413
{ "message.eq" = "this is the content to match against" }
1514
]
1615
common = true
16+
relevant_when = {type = "check_fields"}
1717
description = """\
1818
Check whether a fields contents exactly matches the value specified.\
1919
"""
@@ -24,6 +24,7 @@ examples = [
2424
{ "method.neq" = "POST" }
2525
]
2626
common = true
27+
relevant_when = {type = "check_fields"}
2728
description = """\
2829
Check whether a fields contents does not match the value specified.\
2930
"""
@@ -34,6 +35,7 @@ examples = [
3435
{ "host.exists" = true }
3536
]
3637
common = true
38+
relevant_when = {type = "check_fields"}
3739
description = """\
3840
Check whether a field exists or does not exist, depending on the provided value\
3941
being `true` or `false` respectively.\

config/vector.spec.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1823,18 +1823,20 @@ end
18231823

18241824
[transforms.swimlanes.lanes]
18251825
[transforms.swimlanes.lanes.`<swimlane_id>`]
1826-
# The type of the condition to execute. Currently only the `check_fields` type
1827-
# is available.
1826+
# The type of the condition to execute.
18281827
#
18291828
# * required
18301829
# * type: string
18311830
type = "check_fields"
1831+
type = "is_log"
1832+
type = "is_metric"
18321833

18331834
# Check whether a fields contents exactly matches the value specified.
18341835
#
18351836
# * optional
18361837
# * no default
18371838
# * type: string
1839+
# * relevant when type = "check_fields"
18381840
"message.eq" = "this is the content to match against"
18391841

18401842
# Check whether a field exists or does not exist, depending on the provided
@@ -1843,13 +1845,15 @@ end
18431845
# * optional
18441846
# * no default
18451847
# * type: bool
1848+
# * relevant when type = "check_fields"
18461849
"host.exists" = true
18471850

18481851
# Check whether a fields contents does not match the value specified.
18491852
#
18501853
# * optional
18511854
# * no default
18521855
# * type: string
1856+
# * relevant when type = "check_fields"
18531857
"method.neq" = "POST"
18541858

18551859
# Accepts and outputs `log` events allowing you to tokenize a field's value by splitting on white space, ignoring special wrapping characters, and zip the tokens into ordered field names.

src/conditions/is_log.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
use crate::{
4+
conditions::{Condition, ConditionConfig, ConditionDescription},
5+
Event,
6+
};
7+
8+
//------------------------------------------------------------------------------
9+
10+
#[derive(Deserialize, Serialize, Debug, Default, Clone)]
11+
pub struct IsLogConfig {}
12+
13+
inventory::submit! {
14+
ConditionDescription::new::<IsLogConfig>("is_log")
15+
}
16+
17+
#[typetag::serde(name = "is_log")]
18+
impl ConditionConfig for IsLogConfig {
19+
fn build(&self) -> crate::Result<Box<dyn Condition>> {
20+
Ok(Box::new(IsLog {}))
21+
}
22+
}
23+
24+
//------------------------------------------------------------------------------
25+
26+
pub struct IsLog {}
27+
28+
impl Condition for IsLog {
29+
fn check(&self, e: &Event) -> bool {
30+
match e {
31+
Event::Log(_) => true,
32+
_ => false,
33+
}
34+
}
35+
36+
fn check_with_context(&self, e: &Event) -> Result<(), String> {
37+
if self.check(e) {
38+
Ok(())
39+
} else {
40+
Err("event is not a log type".to_string())
41+
}
42+
}
43+
}
44+
45+
//------------------------------------------------------------------------------
46+
47+
#[cfg(test)]
48+
mod test {
49+
use super::*;
50+
use crate::{
51+
event::metric::{Metric, MetricKind, MetricValue},
52+
Event,
53+
};
54+
55+
#[test]
56+
fn is_log_basic() {
57+
let cond = IsLogConfig {}.build().unwrap();
58+
59+
assert_eq!(cond.check(&Event::from("just a log")), true);
60+
assert_eq!(
61+
cond.check(&Event::from(Metric {
62+
name: "test metric".to_string(),
63+
timestamp: None,
64+
tags: None,
65+
kind: MetricKind::Incremental,
66+
value: MetricValue::Counter { value: 1.0 },
67+
})),
68+
false
69+
);
70+
}
71+
}

src/conditions/is_metric.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
use crate::{
4+
conditions::{Condition, ConditionConfig, ConditionDescription},
5+
Event,
6+
};
7+
8+
//------------------------------------------------------------------------------
9+
10+
#[derive(Deserialize, Serialize, Debug, Default, Clone)]
11+
pub struct IsMetricConfig {}
12+
13+
inventory::submit! {
14+
ConditionDescription::new::<IsMetricConfig>("is_metric")
15+
}
16+
17+
#[typetag::serde(name = "is_metric")]
18+
impl ConditionConfig for IsMetricConfig {
19+
fn build(&self) -> crate::Result<Box<dyn Condition>> {
20+
Ok(Box::new(IsMetric {}))
21+
}
22+
}
23+
24+
//------------------------------------------------------------------------------
25+
26+
pub struct IsMetric {}
27+
28+
impl Condition for IsMetric {
29+
fn check(&self, e: &Event) -> bool {
30+
match e {
31+
Event::Metric(_) => true,
32+
_ => false,
33+
}
34+
}
35+
36+
fn check_with_context(&self, e: &Event) -> Result<(), String> {
37+
if self.check(e) {
38+
Ok(())
39+
} else {
40+
Err("event is not a metric type".to_string())
41+
}
42+
}
43+
}
44+
45+
//------------------------------------------------------------------------------
46+
47+
#[cfg(test)]
48+
mod test {
49+
use super::*;
50+
use crate::{
51+
event::metric::{Metric, MetricKind, MetricValue},
52+
Event,
53+
};
54+
55+
#[test]
56+
fn is_metric_basic() {
57+
let cond = IsMetricConfig {}.build().unwrap();
58+
59+
assert_eq!(cond.check(&Event::from("just a log")), false);
60+
assert_eq!(
61+
cond.check(&Event::from(Metric {
62+
name: "test metric".to_string(),
63+
timestamp: None,
64+
tags: None,
65+
kind: MetricKind::Incremental,
66+
value: MetricValue::Counter { value: 1.0 },
67+
})),
68+
true
69+
);
70+
}
71+
}

src/conditions/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use crate::Event;
33
use inventory;
44

55
pub mod check_fields;
6+
pub mod is_log;
7+
pub mod is_metric;
68

79
pub trait Condition: Send + Sync {
810
fn check(&self, e: &Event) -> bool;

tests/behavior/transforms/swimlanes.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
[transforms.foo.lanes.second]
88
type = "check_fields"
99
"message.eq" = "test swimlane 2"
10+
[transforms.foo.lanes.third]
11+
type = "is_log"
1012

1113
[transforms.bar]
1214
inputs = ["foo.first"]
@@ -35,6 +37,11 @@
3537
"message.equals" = "test swimlane 1"
3638
"new_field.equals" = "new field added"
3739

40+
[[tests.outputs]]
41+
extract_from = "foo.third"
42+
[[tests.outputs.conditions]]
43+
"message.equals" = "test swimlane 1"
44+
3845
[[tests]]
3946
name = "swimlanes test 2"
4047
no_outputs_from = [ "foo.first", "bar" ]
@@ -48,3 +55,8 @@
4855
[[tests.outputs.conditions]]
4956
type = "check_fields"
5057
"message.equals" = "test swimlane 2"
58+
59+
[[tests.outputs]]
60+
extract_from = "foo.third"
61+
[[tests.outputs.conditions]]
62+
"message.equals" = "test swimlane 2"

website/docs/reference/tests.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ A table that defines a collection of conditions to check against the output of a
637637
groups={[]}
638638
name={"`<field_name>`.eq"}
639639
path={"outputs.conditions"}
640-
relevantWhen={null}
640+
relevantWhen={{"type":"check_fields"}}
641641
required={false}
642642
templateable={false}
643643
type={"string"}
@@ -660,7 +660,7 @@ Check whether a fields contents exactly matches the value specified.
660660
groups={[]}
661661
name={"`<field_name>`.exists"}
662662
path={"outputs.conditions"}
663-
relevantWhen={null}
663+
relevantWhen={{"type":"check_fields"}}
664664
required={false}
665665
templateable={false}
666666
type={"bool"}
@@ -683,7 +683,7 @@ Check whether a field exists or does not exist, depending on the provided valueb
683683
groups={[]}
684684
name={"`<field_name>`.neq"}
685685
path={"outputs.conditions"}
686-
relevantWhen={null}
686+
relevantWhen={{"type":"check_fields"}}
687687
required={false}
688688
templateable={false}
689689
type={"string"}
@@ -702,7 +702,7 @@ Check whether a fields contents does not match the value specified.
702702
common={true}
703703
defaultValue={null}
704704
enumValues={null}
705-
examples={["check_fields"]}
705+
examples={["check_fields","is_log","is_metric"]}
706706
groups={[]}
707707
name={"type"}
708708
path={"outputs.conditions"}
@@ -715,7 +715,7 @@ Check whether a fields contents does not match the value specified.
715715
716716
##### type
717717

718-
The type of the condition to execute. Currently only the `check_fields` type is available.
718+
The type of the condition to execute.
719719

720720

721721
</Field>

website/docs/reference/transforms/swimlanes.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ The identifier of a swimlane.
105105
groups={[]}
106106
name={"`<field_name>`.eq"}
107107
path={"lanes.`<swimlane_id>`"}
108-
relevantWhen={null}
108+
relevantWhen={{"type":"check_fields"}}
109109
required={false}
110110
templateable={false}
111111
type={"string"}
@@ -128,7 +128,7 @@ Check whether a fields contents exactly matches the value specified.
128128
groups={[]}
129129
name={"`<field_name>`.exists"}
130130
path={"lanes.`<swimlane_id>`"}
131-
relevantWhen={null}
131+
relevantWhen={{"type":"check_fields"}}
132132
required={false}
133133
templateable={false}
134134
type={"bool"}
@@ -151,7 +151,7 @@ Check whether a field exists or does not exist, depending on the provided valueb
151151
groups={[]}
152152
name={"`<field_name>`.neq"}
153153
path={"lanes.`<swimlane_id>`"}
154-
relevantWhen={null}
154+
relevantWhen={{"type":"check_fields"}}
155155
required={false}
156156
templateable={false}
157157
type={"string"}
@@ -170,7 +170,7 @@ Check whether a fields contents does not match the value specified.
170170
common={true}
171171
defaultValue={null}
172172
enumValues={null}
173-
examples={["check_fields"]}
173+
examples={["check_fields","is_log","is_metric"]}
174174
groups={[]}
175175
name={"type"}
176176
path={"lanes.`<swimlane_id>`"}
@@ -183,7 +183,7 @@ Check whether a fields contents does not match the value specified.
183183
184184
##### type
185185

186-
The type of the condition to execute. Currently only the `check_fields` type is available.
186+
The type of the condition to execute.
187187

188188

189189
</Field>

0 commit comments

Comments
 (0)