Skip to content

Commit 4cc0f7a

Browse files
deepsource fix
1 parent 805e9bc commit 4cc0f7a

1 file changed

Lines changed: 73 additions & 70 deletions

File tree

src/alerts/mod.rs

Lines changed: 73 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,65 @@ fn ensure_schedulable_in_oss(alert: &dyn AlertTrait) -> Result<(), AlertError> {
103103
Ok(())
104104
}
105105

106+
async fn parse_alert_config(alert_bytes: &[u8], tenant: &Option<String>) -> Option<AlertConfig> {
107+
let json_value: JsonValue = match serde_json::from_slice(alert_bytes) {
108+
Ok(val) => val,
109+
Err(e) => {
110+
error!("Failed to parse alert JSON: {e}");
111+
return None;
112+
}
113+
};
114+
115+
match json_value["version"].as_str() {
116+
Some("v1") => migrate_v1_alert(&json_value, tenant, "Failed to migrate v1 alert").await,
117+
Some(_) if json_value["query"].is_null() || json_value.get("stream").is_some() => {
118+
migrate_v1_alert(&json_value, tenant, "Failed to migrate v1 alert").await
119+
}
120+
Some(_) => match serde_json::from_value::<AlertConfig>(json_value) {
121+
Ok(alert) => Some(alert),
122+
Err(e) => {
123+
error!("Failed to parse v2 alert: {e}");
124+
None
125+
}
126+
},
127+
None => {
128+
warn!("Found alert without version field, assuming v1 and migrating");
129+
migrate_v1_alert(
130+
&json_value,
131+
tenant,
132+
"Failed to migrate alert without version",
133+
)
134+
.await
135+
}
136+
}
137+
}
138+
139+
async fn migrate_v1_alert(
140+
json_value: &JsonValue,
141+
tenant: &Option<String>,
142+
error_context: &str,
143+
) -> Option<AlertConfig> {
144+
match AlertConfig::migrate_from_v1(json_value, tenant).await {
145+
Ok(migrated) => Some(migrated),
146+
Err(e) => {
147+
error!("{error_context}: {e}");
148+
None
149+
}
150+
}
151+
}
152+
153+
fn alert_from_config_oss(alert: AlertConfig) -> anyhow::Result<Box<dyn AlertTrait>> {
154+
match &alert.alert_type {
155+
AlertType::Threshold => Ok(Box::new(ThresholdAlert::from(alert)) as Box<dyn AlertTrait>),
156+
AlertType::Anomaly(_) => Err(anyhow::Error::msg(
157+
AlertError::NotPresentInOSS("anomaly").to_string(),
158+
)),
159+
AlertType::Forecast(_) => Err(anyhow::Error::msg(
160+
AlertError::NotPresentInOSS("forecast").to_string(),
161+
)),
162+
}
163+
}
164+
106165
pub fn create_default_alerts_manager() -> Alerts {
107166
let (tx, rx) = mpsc::channel::<AlertTask>(1000);
108167
let alerts = Alerts {
@@ -1107,81 +1166,14 @@ impl AlertManagerTrait for Alerts {
11071166
&Some(tenant_id.clone())
11081167
};
11091168
for alert_bytes in raw_bytes {
1110-
// First, try to parse as JSON Value to check version
1111-
let json_value: JsonValue = match serde_json::from_slice(&alert_bytes) {
1112-
Ok(val) => val,
1113-
Err(e) => {
1114-
error!("Failed to parse alert JSON: {e}");
1115-
continue;
1116-
}
1117-
};
1118-
1119-
// Check version and handle migration
1120-
let mut alert = if let Some(version_str) = json_value["version"].as_str() {
1121-
if version_str == "v1"
1122-
|| json_value["query"].is_null()
1123-
|| json_value.get("stream").is_some()
1124-
{
1125-
// This is a v1 alert that needs migration
1126-
match AlertConfig::migrate_from_v1(&json_value, tenant).await {
1127-
Ok(migrated) => migrated,
1128-
Err(e) => {
1129-
error!("Failed to migrate v1 alert: {e}");
1130-
continue;
1131-
}
1132-
}
1133-
} else {
1134-
// Try to parse as v2
1135-
match serde_json::from_value::<AlertConfig>(json_value) {
1136-
Ok(alert) => alert,
1137-
Err(e) => {
1138-
error!("Failed to parse v2 alert: {e}");
1139-
continue;
1140-
}
1141-
}
1142-
}
1143-
} else {
1144-
// No version field, assume v1 and migrate
1145-
warn!("Found alert without version field, assuming v1 and migrating");
1146-
match AlertConfig::migrate_from_v1(&json_value, tenant).await {
1147-
Ok(migrated) => migrated,
1148-
Err(e) => {
1149-
error!("Failed to migrate alert without version: {e}");
1150-
continue;
1151-
}
1152-
}
1169+
let Some(mut alert) = parse_alert_config(&alert_bytes, tenant).await else {
1170+
continue;
11531171
};
11541172

11551173
// ensure that alert config's tenant is correctly set
11561174
alert.tenant_id.clone_from(tenant);
11571175

1158-
let alert: Box<dyn AlertTrait> = match &alert.alert_type {
1159-
AlertType::Threshold => {
1160-
let alert = ThresholdAlert::from(alert);
1161-
if let Err(e) = alert.validate_oss_query_type() {
1162-
warn!(
1163-
"Skipping unsupported alert task for alert {}: {e}",
1164-
alert.id
1165-
);
1166-
map.entry(tenant_id.clone())
1167-
.or_default()
1168-
.insert(alert.id, Box::new(alert) as Box<dyn AlertTrait>);
1169-
continue;
1170-
}
1171-
1172-
Box::new(alert) as Box<dyn AlertTrait>
1173-
}
1174-
AlertType::Anomaly(_) => {
1175-
return Err(anyhow::Error::msg(
1176-
AlertError::NotPresentInOSS("anomaly").to_string(),
1177-
));
1178-
}
1179-
AlertType::Forecast(_) => {
1180-
return Err(anyhow::Error::msg(
1181-
AlertError::NotPresentInOSS("forecast").to_string(),
1182-
));
1183-
}
1184-
};
1176+
let alert = alert_from_config_oss(alert)?;
11851177

11861178
// Create alert task iff alert's state is not paused
11871179
if alert.get_state().eq(&AlertState::Disabled) {
@@ -1191,6 +1183,17 @@ impl AlertManagerTrait for Alerts {
11911183
continue;
11921184
}
11931185

1186+
if let Err(e) = ensure_schedulable_in_oss(alert.as_ref()) {
1187+
warn!(
1188+
"Skipping unsupported alert task for alert {}: {e}",
1189+
alert.get_id()
1190+
);
1191+
map.entry(tenant_id.clone())
1192+
.or_default()
1193+
.insert(*alert.get_id(), alert);
1194+
continue;
1195+
}
1196+
11941197
match self.sender.send(AlertTask::Create(alert.clone_box())).await {
11951198
Ok(_) => {}
11961199
Err(e) => {

0 commit comments

Comments
 (0)