@@ -8,6 +8,7 @@ use vector_lib::config::clone_input_definitions;
88use vector_lib:: configurable:: configurable_component;
99
1010use crate :: {
11+ conditions:: { AnyCondition , Condition } ,
1112 config:: { DataType , Input , OutputId , TransformConfig , TransformContext , TransformOutput } ,
1213 event:: Event ,
1314 schema,
@@ -24,6 +25,9 @@ pub struct DelayConfig {
2425 #[ serde_as( as = "serde_with::DurationSecondsWithFrac<f64>" ) ]
2526 #[ configurable( metadata( docs:: human_name = "Delay per event" , docs:: example = 0.2 ) ) ]
2627 delay_per_event : Duration ,
28+
29+ /// Delay only events matched by this condition.
30+ condition : Option < AnyCondition > ,
2731}
2832
2933impl_generate_config_from_default ! ( DelayConfig ) ;
@@ -32,7 +36,7 @@ impl_generate_config_from_default!(DelayConfig);
3236#[ typetag:: serde( name = "delay" ) ]
3337impl TransformConfig for DelayConfig {
3438 async fn build ( & self , context : & TransformContext ) -> crate :: Result < Transform > {
35- Ok ( Transform :: event_task ( Delay :: new ( self , context) ) )
39+ Ok ( Transform :: event_task ( Delay :: new ( self , context) ? ) )
3640 }
3741
3842 fn input ( & self ) -> Input {
@@ -55,14 +59,21 @@ impl TransformConfig for DelayConfig {
5559pub struct Delay {
5660 delay : Duration ,
5761 queue : DelayQueue < Event > ,
62+ condition : Condition ,
5863}
5964
6065impl Delay {
61- pub fn new ( config : & DelayConfig , _context : & TransformContext ) -> Self {
62- Self {
66+ pub fn new ( config : & DelayConfig , context : & TransformContext ) -> crate :: Result < Self > {
67+ Ok ( Self {
6368 delay : config. delay_per_event ,
6469 queue : DelayQueue :: new ( ) ,
65- }
70+ condition : config
71+ . condition
72+ . as_ref ( )
73+ . map ( |c| c. build ( & context. enrichment_tables , & context. metrics_storage ) )
74+ . transpose ( ) ?
75+ . unwrap_or ( Condition :: AlwaysPass ) ,
76+ } )
6677 }
6778}
6879
@@ -84,7 +95,12 @@ impl TaskTransform<Event> for Delay {
8495 done = true ;
8596 }
8697 Some ( event) => {
87- self . queue. insert( event, self . delay) ;
98+ let ( result, event) = self . condition. check( event) ;
99+ if result {
100+ self . queue. insert( event, self . delay) ;
101+ } else {
102+ yield event;
103+ }
88104 }
89105 }
90106 } ,
@@ -105,6 +121,7 @@ mod tests {
105121 use std:: task:: Poll ;
106122
107123 use futures:: SinkExt ;
124+ use vector_lib:: event:: TraceEvent ;
108125
109126 use super :: * ;
110127 use crate :: event:: LogEvent ;
@@ -123,14 +140,52 @@ delay_per_event = 0.2
123140 )
124141 . unwrap ( ) ;
125142
126- let delay = Transform :: event_task ( Delay :: new ( & config, & TransformContext :: default ( ) ) ) ;
143+ let delay =
144+ Transform :: event_task ( Delay :: new ( & config, & TransformContext :: default ( ) ) . unwrap ( ) ) ;
145+
146+ let delay = delay. into_task ( ) ;
147+
148+ let ( mut tx, rx) = futures:: channel:: mpsc:: channel ( 10 ) ;
149+ let mut out_stream = delay. transform_events ( Box :: pin ( rx) ) ;
150+
151+ tx. send ( LogEvent :: default ( ) . into ( ) ) . await . unwrap ( ) ;
152+
153+ // We should be pending, because we are now waiting for the delay
154+ assert_eq ! ( Poll :: Pending , futures:: poll!( out_stream. next( ) ) ) ;
155+
156+ // Wait long enough for delay to end
157+ tokio:: time:: sleep ( Duration :: from_secs_f64 ( 0.3 ) ) . await ;
158+
159+ if !matches ! ( futures:: poll!( out_stream. next( ) ) , Poll :: Ready ( Some ( _event) ) ) {
160+ panic ! ( "Unexpectedly received None or Pending in output stream" ) ;
161+ }
162+ }
163+
164+ #[ tokio:: test]
165+ async fn delay_events_condition ( ) {
166+ let config = toml:: from_str :: < DelayConfig > (
167+ r#"
168+ delay_per_event = 0.2
169+ condition.type = "is_log"
170+ "# ,
171+ )
172+ . unwrap ( ) ;
173+
174+ let delay =
175+ Transform :: event_task ( Delay :: new ( & config, & TransformContext :: default ( ) ) . unwrap ( ) ) ;
127176
128177 let delay = delay. into_task ( ) ;
129178
130179 let ( mut tx, rx) = futures:: channel:: mpsc:: channel ( 10 ) ;
131180 let mut out_stream = delay. transform_events ( Box :: pin ( rx) ) ;
132181
133182 tx. send ( LogEvent :: default ( ) . into ( ) ) . await . unwrap ( ) ;
183+ tx. send ( TraceEvent :: default ( ) . into ( ) ) . await . unwrap ( ) ;
184+
185+ let Poll :: Ready ( Some ( event) ) = futures:: poll!( out_stream. next( ) ) else {
186+ panic ! ( "Unexpectedly received None or Pending in output stream" ) ;
187+ } ;
188+ assert ! ( event. try_into_trace( ) . is_some( ) ) ;
134189
135190 // We should be pending, because we are now waiting for the delay
136191 assert_eq ! ( Poll :: Pending , futures:: poll!( out_stream. next( ) ) ) ;
0 commit comments