19
19
use actix_web:: http:: header:: ContentType ;
20
20
use arrow_schema:: { DataType , Schema } ;
21
21
use async_trait:: async_trait;
22
- use chrono:: Utc ;
22
+ use chrono:: { DateTime , Utc } ;
23
23
use datafusion:: logical_expr:: { LogicalPlan , Projection } ;
24
24
use datafusion:: sql:: sqlparser:: parser:: ParserError ;
25
25
use derive_more:: FromStrError ;
@@ -197,6 +197,14 @@ pub enum AlertType {
197
197
Threshold ,
198
198
}
199
199
200
+ impl Display for AlertType {
201
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
202
+ match self {
203
+ AlertType :: Threshold => write ! ( f, "Threshold" ) ,
204
+ }
205
+ }
206
+ }
207
+
200
208
#[ derive( Debug , serde:: Serialize , serde:: Deserialize , Clone ) ]
201
209
#[ serde( rename_all = "camelCase" ) ]
202
210
pub enum AlertOperator {
@@ -528,6 +536,7 @@ pub struct AlertRequest {
528
536
pub threshold_config : ThresholdConfig ,
529
537
pub eval_config : EvalConfig ,
530
538
pub targets : Vec < Ulid > ,
539
+ pub tags : Option < Vec < String > > ,
531
540
}
532
541
533
542
impl AlertRequest {
@@ -547,6 +556,8 @@ impl AlertRequest {
547
556
eval_config : self . eval_config ,
548
557
targets : self . targets ,
549
558
state : AlertState :: default ( ) ,
559
+ created : Utc :: now ( ) ,
560
+ tags : self . tags ,
550
561
} ;
551
562
Ok ( config)
552
563
}
@@ -568,6 +579,8 @@ pub struct AlertConfig {
568
579
// for new alerts, state should be resolved
569
580
#[ serde( default ) ]
570
581
pub state : AlertState ,
582
+ pub created : DateTime < Utc > ,
583
+ pub tags : Option < Vec < String > > ,
571
584
}
572
585
573
586
impl AlertConfig {
@@ -597,6 +610,8 @@ impl AlertConfig {
597
610
eval_config,
598
611
targets,
599
612
state,
613
+ created : Utc :: now ( ) ,
614
+ tags : None ,
600
615
} ;
601
616
602
617
// Save the migrated alert back to storage
@@ -1183,6 +1198,45 @@ impl AlertConfig {
1183
1198
}
1184
1199
Ok ( ( ) )
1185
1200
}
1201
+
1202
+ /// create a summary of the dashboard
1203
+ /// used for listing dashboards
1204
+ pub fn to_summary ( & self ) -> serde_json:: Map < String , serde_json:: Value > {
1205
+ let mut map = serde_json:: Map :: new ( ) ;
1206
+
1207
+ map. insert (
1208
+ "title" . to_string ( ) ,
1209
+ serde_json:: Value :: String ( self . title . clone ( ) ) ,
1210
+ ) ;
1211
+
1212
+ map. insert (
1213
+ "created" . to_string ( ) ,
1214
+ serde_json:: Value :: String ( self . created . to_string ( ) ) ,
1215
+ ) ;
1216
+
1217
+ map. insert (
1218
+ "alertType" . to_string ( ) ,
1219
+ serde_json:: Value :: String ( self . alert_type . to_string ( ) ) ,
1220
+ ) ;
1221
+
1222
+ map. insert (
1223
+ "id" . to_string ( ) ,
1224
+ serde_json:: Value :: String ( self . id . to_string ( ) ) ,
1225
+ ) ;
1226
+
1227
+ if let Some ( tags) = & self . tags {
1228
+ map. insert (
1229
+ "tags" . to_string ( ) ,
1230
+ serde_json:: Value :: Array (
1231
+ tags. iter ( )
1232
+ . map ( |tag| serde_json:: Value :: String ( tag. clone ( ) ) )
1233
+ . collect ( ) ,
1234
+ ) ,
1235
+ ) ;
1236
+ }
1237
+
1238
+ map
1239
+ }
1186
1240
}
1187
1241
1188
1242
#[ derive( Debug , thiserror:: Error ) ]
@@ -1221,6 +1275,8 @@ pub enum AlertError {
1221
1275
ParserError ( #[ from] ParserError ) ,
1222
1276
#[ error( "Invalid alert query" ) ]
1223
1277
InvalidAlertQuery ,
1278
+ #[ error( "Invalid query parameter" ) ]
1279
+ InvalidQueryParameter ,
1224
1280
}
1225
1281
1226
1282
impl actix_web:: ResponseError for AlertError {
@@ -1243,6 +1299,7 @@ impl actix_web::ResponseError for AlertError {
1243
1299
Self :: TargetInUse => StatusCode :: CONFLICT ,
1244
1300
Self :: ParserError ( _) => StatusCode :: BAD_REQUEST ,
1245
1301
Self :: InvalidAlertQuery => StatusCode :: BAD_REQUEST ,
1302
+ Self :: InvalidQueryParameter => StatusCode :: BAD_REQUEST ,
1246
1303
}
1247
1304
}
1248
1305
@@ -1350,6 +1407,7 @@ impl Alerts {
1350
1407
pub async fn list_alerts_for_user (
1351
1408
& self ,
1352
1409
session : SessionKey ,
1410
+ tags : Vec < String > ,
1353
1411
) -> Result < Vec < AlertConfig > , AlertError > {
1354
1412
let mut alerts: Vec < AlertConfig > = Vec :: new ( ) ;
1355
1413
for ( _, alert) in self . alerts . read ( ) . await . iter ( ) {
@@ -1358,6 +1416,17 @@ impl Alerts {
1358
1416
alerts. push ( alert. to_owned ( ) ) ;
1359
1417
}
1360
1418
}
1419
+ if tags. is_empty ( ) {
1420
+ return Ok ( alerts) ;
1421
+ }
1422
+ // filter alerts based on tags
1423
+ alerts. retain ( |alert| {
1424
+ if let Some ( alert_tags) = & alert. tags {
1425
+ alert_tags. iter ( ) . any ( |tag| tags. contains ( tag) )
1426
+ } else {
1427
+ false
1428
+ }
1429
+ } ) ;
1361
1430
1362
1431
Ok ( alerts)
1363
1432
}
@@ -1456,6 +1525,20 @@ impl Alerts {
1456
1525
1457
1526
Ok ( ( ) )
1458
1527
}
1528
+
1529
+ /// List tags from all alerts
1530
+ /// This function returns a list of unique tags from all alerts
1531
+ pub async fn list_tags ( & self ) -> Vec < String > {
1532
+ let alerts = self . alerts . read ( ) . await ;
1533
+ let mut tags = alerts
1534
+ . iter ( )
1535
+ . filter_map ( |( _, alert) | alert. tags . as_ref ( ) )
1536
+ . flat_map ( |t| t. iter ( ) . cloned ( ) )
1537
+ . collect :: < Vec < String > > ( ) ;
1538
+ tags. sort ( ) ;
1539
+ tags. dedup ( ) ;
1540
+ tags
1541
+ }
1459
1542
}
1460
1543
1461
1544
#[ derive( Debug , Serialize ) ]
0 commit comments