18
18
19
19
use arrow_array:: { Float64Array , Int64Array , RecordBatch } ;
20
20
use datafusion:: {
21
- common:: tree_node:: TreeNode ,
22
- functions_aggregate:: {
21
+ common:: tree_node:: TreeNode , functions_aggregate:: {
23
22
count:: count,
24
23
expr_fn:: avg,
25
24
min_max:: { max, min} ,
26
25
sum:: sum,
27
- } ,
28
- prelude:: { col, lit, DataFrame , Expr } ,
26
+ } , logical_expr:: { BinaryExpr , Operator } , prelude:: { col, lit, DataFrame , Expr }
29
27
} ;
30
28
use tracing:: trace;
31
29
32
30
use crate :: {
33
- alerts:: AggregateCondition ,
31
+ alerts:: LogicalOperator ,
34
32
parseable:: PARSEABLE ,
35
33
query:: { TableScanVisitor , QUERY_SESSION } ,
36
34
rbac:: {
@@ -42,8 +40,7 @@ use crate::{
42
40
} ;
43
41
44
42
use super :: {
45
- AggregateConfig , AggregateOperation , AggregateResult , Aggregations , AlertConfig , AlertError ,
46
- AlertOperator , AlertState , ConditionConfig , Conditions , ALERTS ,
43
+ AggregateConfig , AggregateFunction , AggregateResult , Aggregates , AlertConfig , AlertError , AlertOperator , AlertState , ConditionConfig , Conditions , WhereConfigOperator , ALERTS
47
44
} ;
48
45
49
46
async fn get_tables_from_query ( query : & str ) -> Result < TableScanVisitor , AlertError > {
@@ -104,18 +101,16 @@ pub async fn evaluate_alert(alert: &AlertConfig) -> Result<(), AlertError> {
104
101
let query = prepare_query ( alert) . await ?;
105
102
let select_query = format ! ( "SELECT * FROM {}" , alert. stream) ;
106
103
let base_df = execute_base_query ( & query, & select_query) . await ?;
107
- let agg_results = evaluate_aggregates ( & alert. aggregate_config , & base_df) . await ?;
108
- let final_res = calculate_final_result ( & alert. aggregate_config , & agg_results) ;
104
+ let agg_results = evaluate_aggregates ( & alert. aggregates , & base_df) . await ?;
105
+ let final_res = calculate_final_result ( & alert. aggregates , & agg_results) ;
109
106
110
107
update_alert_state ( alert, final_res, & agg_results) . await ?;
111
108
Ok ( ( ) )
112
109
}
113
110
114
111
async fn prepare_query ( alert : & AlertConfig ) -> Result < crate :: query:: Query , AlertError > {
115
- let ( start_time, end_time) = match & alert. eval_type {
116
- super :: EvalConfig :: RollingWindow ( rolling_window) => {
117
- ( & rolling_window. eval_start , & rolling_window. eval_end )
118
- }
112
+ let ( start_time, end_time) = match & alert. eval_config {
113
+ super :: EvalConfig :: RollingWindow ( rolling_window) => ( & rolling_window. eval_start , "now" ) ,
119
114
} ;
120
115
121
116
let session_state = QUERY_SESSION . state ( ) ;
@@ -148,15 +143,15 @@ async fn execute_base_query(
148
143
}
149
144
150
145
async fn evaluate_aggregates (
151
- agg_config : & Aggregations ,
146
+ agg_config : & Aggregates ,
152
147
base_df : & DataFrame ,
153
148
) -> Result < Vec < AggregateResult > , AlertError > {
154
149
let agg_filter_exprs = get_exprs ( agg_config) ;
155
150
let mut results = Vec :: new ( ) ;
156
151
157
152
let conditions = match & agg_config. operator {
158
- Some ( _) => & agg_config. aggregate_conditions [ 0 ..2 ] ,
159
- None => & agg_config. aggregate_conditions [ 0 ..1 ] ,
153
+ Some ( _) => & agg_config. aggregate_config [ 0 ..2 ] ,
154
+ None => & agg_config. aggregate_config [ 0 ..1 ] ,
160
155
} ;
161
156
162
157
for ( ( agg_expr, filter) , agg) in agg_filter_exprs. into_iter ( ) . zip ( conditions) {
@@ -188,7 +183,7 @@ async fn evaluate_single_aggregate(
188
183
let result = evaluate_condition ( & agg. operator , final_value, agg. value ) ;
189
184
190
185
let message = if result {
191
- agg. condition_config
186
+ agg. conditions
192
187
. as_ref ( )
193
188
. map ( |config| config. generate_filter_message ( ) )
194
189
. or ( Some ( String :: default ( ) ) )
@@ -208,18 +203,18 @@ fn evaluate_condition(operator: &AlertOperator, actual: f64, expected: f64) -> b
208
203
match operator {
209
204
AlertOperator :: GreaterThan => actual > expected,
210
205
AlertOperator :: LessThan => actual < expected,
211
- AlertOperator :: EqualTo => actual == expected,
212
- AlertOperator :: NotEqualTo => actual != expected,
213
- AlertOperator :: GreaterThanEqualTo => actual >= expected,
214
- AlertOperator :: LessThanEqualTo => actual <= expected,
206
+ AlertOperator :: Equal => actual == expected,
207
+ AlertOperator :: NotEqual => actual != expected,
208
+ AlertOperator :: GreaterThanOrEqual => actual >= expected,
209
+ AlertOperator :: LessThanOrEqual => actual <= expected,
215
210
_ => unreachable ! ( ) ,
216
211
}
217
212
}
218
213
219
- fn calculate_final_result ( agg_config : & Aggregations , results : & [ AggregateResult ] ) -> bool {
214
+ fn calculate_final_result ( agg_config : & Aggregates , results : & [ AggregateResult ] ) -> bool {
220
215
match & agg_config. operator {
221
- Some ( AggregateCondition :: And ) => results. iter ( ) . all ( |r| r. result ) ,
222
- Some ( AggregateCondition :: Or ) => results. iter ( ) . any ( |r| r. result ) ,
216
+ Some ( LogicalOperator :: And ) => results. iter ( ) . all ( |r| r. result ) ,
217
+ Some ( LogicalOperator :: Or ) => results. iter ( ) . any ( |r| r. result ) ,
223
218
None => results. first ( ) . is_some_and ( |r| r. result ) ,
224
219
}
225
220
}
@@ -252,7 +247,7 @@ fn format_alert_message(agg_results: &[AggregateResult]) -> String {
252
247
if let Some ( msg) = & result. message {
253
248
message. extend ( [ format ! (
254
249
"|{}({}) WHERE ({}) {} {} (ActualValue: {})|" ,
255
- result. config. agg ,
250
+ result. config. aggregate_function ,
256
251
result. config. column,
257
252
msg,
258
253
result. config. operator,
@@ -262,7 +257,7 @@ fn format_alert_message(agg_results: &[AggregateResult]) -> String {
262
257
} else {
263
258
message. extend ( [ format ! (
264
259
"|{}({}) {} {} (ActualValue: {})" ,
265
- result. config. agg ,
260
+ result. config. aggregate_function ,
266
261
result. config. column,
267
262
result. config. operator,
268
263
result. config. value,
@@ -307,17 +302,17 @@ fn get_final_value(aggregated_rows: Vec<RecordBatch>) -> f64 {
307
302
/// returns a tuple of (aggregate expressions, filter expressions)
308
303
///
309
304
/// It calls get_filter_expr() to get filter expressions
310
- fn get_exprs ( aggregate_config : & Aggregations ) -> Vec < ( Expr , Option < Expr > ) > {
305
+ fn get_exprs ( aggregate_config : & Aggregates ) -> Vec < ( Expr , Option < Expr > ) > {
311
306
let mut agg_expr = Vec :: new ( ) ;
312
307
313
308
match & aggregate_config. operator {
314
309
Some ( op) => match op {
315
- AggregateCondition :: And | AggregateCondition :: Or => {
316
- let agg1 = & aggregate_config. aggregate_conditions [ 0 ] ;
317
- let agg2 = & aggregate_config. aggregate_conditions [ 1 ] ;
310
+ LogicalOperator :: And | LogicalOperator :: Or => {
311
+ let agg1 = & aggregate_config. aggregate_config [ 0 ] ;
312
+ let agg2 = & aggregate_config. aggregate_config [ 1 ] ;
318
313
319
314
for agg in [ agg1, agg2] {
320
- let filter_expr = if let Some ( where_clause) = & agg. condition_config {
315
+ let filter_expr = if let Some ( where_clause) = & agg. conditions {
321
316
let fe = get_filter_expr ( where_clause) ;
322
317
323
318
trace ! ( "filter_expr-\n {fe:?}" ) ;
@@ -333,9 +328,9 @@ fn get_exprs(aggregate_config: &Aggregations) -> Vec<(Expr, Option<Expr>)> {
333
328
}
334
329
} ,
335
330
None => {
336
- let agg = & aggregate_config. aggregate_conditions [ 0 ] ;
331
+ let agg = & aggregate_config. aggregate_config [ 0 ] ;
337
332
338
- let filter_expr = if let Some ( where_clause) = & agg. condition_config {
333
+ let filter_expr = if let Some ( where_clause) = & agg. conditions {
339
334
let fe = get_filter_expr ( where_clause) ;
340
335
341
336
trace ! ( "filter_expr-\n {fe:?}" ) ;
@@ -355,23 +350,23 @@ fn get_exprs(aggregate_config: &Aggregations) -> Vec<(Expr, Option<Expr>)> {
355
350
fn get_filter_expr ( where_clause : & Conditions ) -> Expr {
356
351
match & where_clause. operator {
357
352
Some ( op) => match op {
358
- AggregateCondition :: And => {
353
+ LogicalOperator :: And => {
359
354
let mut expr = Expr :: Literal ( datafusion:: scalar:: ScalarValue :: Boolean ( Some ( true ) ) ) ;
360
355
361
- let expr1 = & where_clause. conditions [ 0 ] ;
362
- let expr2 = & where_clause. conditions [ 1 ] ;
356
+ let expr1 = & where_clause. condition_config [ 0 ] ;
357
+ let expr2 = & where_clause. condition_config [ 1 ] ;
363
358
364
359
for e in [ expr1, expr2] {
365
360
let ex = match_alert_operator ( e) ;
366
361
expr = expr. and ( ex) ;
367
362
}
368
363
expr
369
364
}
370
- AggregateCondition :: Or => {
365
+ LogicalOperator :: Or => {
371
366
let mut expr = Expr :: Literal ( datafusion:: scalar:: ScalarValue :: Boolean ( Some ( false ) ) ) ;
372
367
373
- let expr1 = & where_clause. conditions [ 0 ] ;
374
- let expr2 = & where_clause. conditions [ 1 ] ;
368
+ let expr1 = & where_clause. condition_config [ 0 ] ;
369
+ let expr2 = & where_clause. condition_config [ 1 ] ;
375
370
376
371
for e in [ expr1, expr2] {
377
372
let ex = match_alert_operator ( e) ;
@@ -381,30 +376,70 @@ fn get_filter_expr(where_clause: &Conditions) -> Expr {
381
376
}
382
377
} ,
383
378
None => {
384
- let expr = & where_clause. conditions [ 0 ] ;
379
+ let expr = & where_clause. condition_config [ 0 ] ;
385
380
match_alert_operator ( expr)
386
381
}
387
382
}
388
383
}
389
384
390
385
fn match_alert_operator ( expr : & ConditionConfig ) -> Expr {
391
386
match expr. operator {
392
- AlertOperator :: GreaterThan => col ( & expr. column ) . gt ( lit ( & expr. value ) ) ,
393
- AlertOperator :: LessThan => col ( & expr. column ) . lt ( lit ( & expr. value ) ) ,
394
- AlertOperator :: EqualTo => col ( & expr. column ) . eq ( lit ( & expr. value ) ) ,
395
- AlertOperator :: NotEqualTo => col ( & expr. column ) . not_eq ( lit ( & expr. value ) ) ,
396
- AlertOperator :: GreaterThanEqualTo => col ( & expr. column ) . gt_eq ( lit ( & expr. value ) ) ,
397
- AlertOperator :: LessThanEqualTo => col ( & expr. column ) . lt_eq ( lit ( & expr. value ) ) ,
398
- AlertOperator :: Like => col ( & expr. column ) . like ( lit ( & expr. value ) ) ,
399
- AlertOperator :: NotLike => col ( & expr. column ) . not_like ( lit ( & expr. value ) ) ,
387
+ WhereConfigOperator :: Equal => col ( & expr. column ) . eq ( lit ( & expr. value ) ) ,
388
+ WhereConfigOperator :: NotEqual => col ( & expr. column ) . not_eq ( lit ( & expr. value ) ) ,
389
+ WhereConfigOperator :: LessThan => col ( & expr. column ) . lt ( lit ( & expr. value ) ) ,
390
+ WhereConfigOperator :: GreaterThan => col ( & expr. column ) . gt ( lit ( & expr. value ) ) ,
391
+ WhereConfigOperator :: LessThanOrEqual => col ( & expr. column ) . lt_eq ( lit ( & expr. value ) ) ,
392
+ WhereConfigOperator :: GreaterThanOrEqual => col ( & expr. column ) . gt_eq ( lit ( & expr. value ) ) ,
393
+ WhereConfigOperator :: IsNull => col ( & expr. column ) . is_null ( ) ,
394
+ WhereConfigOperator :: IsNotNull => col ( & expr. column ) . is_not_null ( ) ,
395
+ WhereConfigOperator :: ILike => col ( & expr. column ) . ilike ( lit ( & expr. value ) ) ,
396
+ WhereConfigOperator :: Contains => col ( & expr. column ) . like ( lit ( & expr. value ) ) ,
397
+ WhereConfigOperator :: BeginsWith => {
398
+ Expr :: BinaryExpr (
399
+ BinaryExpr :: new (
400
+ Box :: new ( col ( & expr. column ) ) ,
401
+ Operator :: RegexIMatch ,
402
+ Box :: new ( lit ( format ! ( "^{}" , expr. value) ) )
403
+ )
404
+ )
405
+ } ,
406
+ WhereConfigOperator :: EndsWith => {
407
+ Expr :: BinaryExpr (
408
+ BinaryExpr :: new (
409
+ Box :: new ( col ( & expr. column ) ) ,
410
+ Operator :: RegexIMatch ,
411
+ Box :: new ( lit ( format ! ( "{}$" , expr. value) ) )
412
+ )
413
+ )
414
+ } ,
415
+ WhereConfigOperator :: DoesNotContain => col ( & expr. column ) . not_ilike ( lit ( & expr. value ) ) ,
416
+ WhereConfigOperator :: DoesNotBeginWith => {
417
+ Expr :: BinaryExpr (
418
+ BinaryExpr :: new (
419
+ Box :: new ( col ( & expr. column ) ) ,
420
+ Operator :: RegexNotIMatch ,
421
+ Box :: new ( lit ( format ! ( "^{}" , expr. value) ) )
422
+ )
423
+ )
424
+ } ,
425
+ WhereConfigOperator :: DoesNotEndWith => {
426
+ Expr :: BinaryExpr (
427
+ BinaryExpr :: new (
428
+ Box :: new ( col ( & expr. column ) ) ,
429
+ Operator :: RegexNotIMatch ,
430
+ Box :: new ( lit ( format ! ( "{}$" , expr. value) ) )
431
+ )
432
+ )
433
+ } ,
400
434
}
401
435
}
436
+
402
437
fn match_aggregate_operation ( agg : & AggregateConfig ) -> Expr {
403
- match agg. agg {
404
- AggregateOperation :: Avg => avg ( col ( & agg. column ) ) ,
405
- AggregateOperation :: Count => count ( col ( & agg. column ) ) ,
406
- AggregateOperation :: Min => min ( col ( & agg. column ) ) ,
407
- AggregateOperation :: Max => max ( col ( & agg. column ) ) ,
408
- AggregateOperation :: Sum => sum ( col ( & agg. column ) ) ,
438
+ match agg. aggregate_function {
439
+ AggregateFunction :: Avg => avg ( col ( & agg. column ) ) ,
440
+ AggregateFunction :: Count => count ( col ( & agg. column ) ) ,
441
+ AggregateFunction :: Min => min ( col ( & agg. column ) ) ,
442
+ AggregateFunction :: Max => max ( col ( & agg. column ) ) ,
443
+ AggregateFunction :: Sum => sum ( col ( & agg. column ) ) ,
409
444
}
410
445
}
0 commit comments