1#![allow(missing_docs)]
2use vector_lib::configurable::configurable_component;
3
4use crate::event::Event;
5
6mod datadog_search;
7pub(crate) mod is_log;
8pub(crate) mod is_metric;
9pub(crate) mod is_trace;
10mod vrl;
11
12pub use self::datadog_search::{DatadogSearchConfig, DatadogSearchRunner};
13pub use self::vrl::VrlConfig;
14use self::{
15 is_log::{check_is_log, check_is_log_with_context},
16 is_metric::{check_is_metric, check_is_metric_with_context},
17 is_trace::{check_is_trace, check_is_trace_with_context},
18 vrl::Vrl,
19};
20
21#[derive(Debug, Clone)]
22#[allow(clippy::large_enum_variant)]
23pub enum Condition {
24 IsLog,
26
27 IsMetric,
29
30 IsTrace,
32
33 Vrl(Vrl),
35
36 DatadogSearch(DatadogSearchRunner),
38
39 AlwaysPass,
43
44 AlwaysFail,
48}
49
50impl Condition {
51 #[allow(dead_code)]
55 pub fn check(&self, e: Event) -> (bool, Event) {
56 match self {
57 Condition::IsLog => check_is_log(e),
58 Condition::IsMetric => check_is_metric(e),
59 Condition::IsTrace => check_is_trace(e),
60 Condition::Vrl(x) => x.check(e),
61 Condition::DatadogSearch(x) => x.check(e),
62 Condition::AlwaysPass => (true, e),
63 Condition::AlwaysFail => (false, e),
64 }
65 }
66
67 pub(crate) fn check_with_context(&self, e: Event) -> (Result<(), String>, Event) {
72 match self {
73 Condition::IsLog => check_is_log_with_context(e),
74 Condition::IsMetric => check_is_metric_with_context(e),
75 Condition::IsTrace => check_is_trace_with_context(e),
76 Condition::Vrl(x) => x.check_with_context(e),
77 Condition::DatadogSearch(x) => x.check_with_context(e),
78 Condition::AlwaysPass => (Ok(()), e),
79 Condition::AlwaysFail => (Ok(()), e),
80 }
81 }
82}
83
84#[configurable_component]
96#[derive(Clone, Debug)]
97#[serde(tag = "type", rename_all = "snake_case")]
98pub enum ConditionConfig {
99 #[configurable(metadata(docs::hidden))]
101 IsLog,
102
103 #[configurable(metadata(docs::hidden))]
105 IsMetric,
106
107 #[configurable(metadata(docs::hidden))]
109 IsTrace,
110
111 Vrl(VrlConfig),
113
114 DatadogSearch(DatadogSearchConfig),
116}
117
118impl ConditionConfig {
119 pub fn build(
120 &self,
121 enrichment_tables: &vector_lib::enrichment::TableRegistry,
122 ) -> crate::Result<Condition> {
123 match self {
124 ConditionConfig::IsLog => Ok(Condition::IsLog),
125 ConditionConfig::IsMetric => Ok(Condition::IsMetric),
126 ConditionConfig::IsTrace => Ok(Condition::IsTrace),
127 ConditionConfig::Vrl(x) => x.build(enrichment_tables),
128 ConditionConfig::DatadogSearch(x) => x.build(enrichment_tables),
129 }
130 }
131}
132
133pub trait Conditional: std::fmt::Debug {
134 fn check(&self, event: Event) -> (bool, Event);
138
139 fn check_with_context(&self, e: Event) -> (Result<(), String>, Event) {
144 let (result, event) = self.check(e);
145 if result {
146 (Ok(()), event)
147 } else {
148 (Err("condition failed".into()), event)
149 }
150 }
151}
152
153pub trait ConditionalConfig: std::fmt::Debug + Send + Sync + dyn_clone::DynClone {
154 fn build(
155 &self,
156 enrichment_tables: &vector_lib::enrichment::TableRegistry,
157 ) -> crate::Result<Condition>;
158}
159
160dyn_clone::clone_trait_object!(ConditionalConfig);
161
162#[configurable_component]
181#[derive(Clone, Debug)]
182#[configurable(metadata(docs::type_override = "condition"))]
183#[serde(untagged)]
184pub enum AnyCondition {
185 String(String),
187
188 Map(ConditionConfig),
190}
191
192impl AnyCondition {
193 pub fn build(
194 &self,
195 enrichment_tables: &vector_lib::enrichment::TableRegistry,
196 ) -> crate::Result<Condition> {
197 match self {
198 AnyCondition::String(s) => {
199 let vrl_config = VrlConfig {
200 source: s.clone(),
201 runtime: Default::default(),
202 };
203 vrl_config.build(enrichment_tables)
204 }
205 AnyCondition::Map(m) => m.build(enrichment_tables),
206 }
207 }
208}
209
210impl From<ConditionConfig> for AnyCondition {
211 fn from(config: ConditionConfig) -> Self {
212 Self::Map(config)
213 }
214}
215
216#[cfg(test)]
217mod tests {
218 use indoc::indoc;
219 use serde::Deserialize;
220
221 use super::*;
222
223 #[derive(Deserialize, Debug)]
224 struct Test {
225 condition: AnyCondition,
226 }
227
228 #[test]
229 fn deserialize_anycondition_default() {
230 let conf: Test = toml::from_str(r#"condition = ".nork == false""#).unwrap();
231 assert_eq!(
232 r#"String(".nork == false")"#,
233 format!("{:?}", conf.condition)
234 )
235 }
236
237 #[test]
238 fn deserialize_anycondition_vrl() {
239 let conf: Test = toml::from_str(indoc! {r#"
240 condition.type = "vrl"
241 condition.source = '.nork == true'
242 "#})
243 .unwrap();
244
245 assert_eq!(
246 r#"Map(Vrl(VrlConfig { source: ".nork == true", runtime: Ast }))"#,
247 format!("{:?}", conf.condition)
248 )
249 }
250}