diff --git a/keep/api/core/db.py b/keep/api/core/db.py index 1b18a0c47..6976faa3a 100644 --- a/keep/api/core/db.py +++ b/keep/api/core/db.py @@ -3191,21 +3191,38 @@ def get_incident_alerts_and_links_by_incident_id( tenant_id: str, incident_id: UUID | str, limit: Optional[int] = None, - offset: Optional[int] = None, + offset: Optional[int] = 0, session: Optional[Session] = None, include_unlinked: bool = False, ) -> tuple[List[tuple[Alert, AlertToIncident]], int]: with existed_or_new_session(session) as session: + + last_fingerprints_subquery = ( + session.query(Alert.fingerprint, func.max(Alert.timestamp).label("max_timestamp")) + .join(AlertToIncident, AlertToIncident.alert_id == Alert.id) + .filter( + AlertToIncident.tenant_id == tenant_id, + AlertToIncident.incident_id == incident_id, + ) + .group_by(Alert.fingerprint) + .subquery() + ) + query = ( session.query( Alert, AlertToIncident, ) + .select_from(last_fingerprints_subquery) + .outerjoin(Alert, and_( + last_fingerprints_subquery.c.fingerprint == Alert.fingerprint, + last_fingerprints_subquery.c.max_timestamp == Alert.timestamp, + + )) .join(AlertToIncident, AlertToIncident.alert_id == Alert.id) - .join(Incident, AlertToIncident.incident_id == Incident.id) .filter( AlertToIncident.tenant_id == tenant_id, - Incident.id == incident_id, + AlertToIncident.incident_id == incident_id, ) .order_by(col(Alert.timestamp).desc()) ) @@ -3216,8 +3233,10 @@ def get_incident_alerts_and_links_by_incident_id( total_count = query.count() - if limit and offset: - query = query.limit(limit).offset(offset) + if limit: + query = query.limit(limit) + if offset: + query = query.offset(offset) return query.all(), total_count diff --git a/keep/api/tasks/process_event_task.py b/keep/api/tasks/process_event_task.py index 9347fe49b..2e97a3ad5 100644 --- a/keep/api/tasks/process_event_task.py +++ b/keep/api/tasks/process_event_task.py @@ -320,7 +320,7 @@ def __handle_formatted_events( for key, value in enriched_formatted_event.dict().items(): if isinstance(value, dict): for nested_key in value.keys(): - fields.append(f"{key}_{nested_key}") + fields.append(f"{key}.{nested_key}") else: fields.append(key) diff --git a/keep/providers/base/base_provider.py b/keep/providers/base/base_provider.py index 0233b5837..9d2056636 100644 --- a/keep/providers/base/base_provider.py +++ b/keep/providers/base/base_provider.py @@ -395,10 +395,17 @@ def get_alert_fingerprint(alert: AlertDto, fingerprint_fields: list = []) -> str fingerprint = hashlib.sha256() event_dict = alert.dict() for fingerprint_field in fingerprint_fields: - fingerprint_field_value = event_dict.get(fingerprint_field, None) + keys = fingerprint_field.split(".") + fingerprint_field_value = event_dict + for key in keys: + if isinstance(fingerprint_field_value, dict): + fingerprint_field_value = fingerprint_field_value.get(key, None) + else: + fingerprint_field_value = None + break if isinstance(fingerprint_field_value, (list, dict)): fingerprint_field_value = json.dumps(fingerprint_field_value) - if fingerprint_field_value: + if fingerprint_field_value is not None: fingerprint.update(str(fingerprint_field_value).encode()) return fingerprint.hexdigest() diff --git a/tests/test_incidents.py b/tests/test_incidents.py index 984da9473..3a2bfec8c 100644 --- a/tests/test_incidents.py +++ b/tests/test_incidents.py @@ -127,7 +127,7 @@ def test_add_remove_alert_to_incidents(db_session, setup_stress_alerts_no_elasti incident_id=incident.id, tenant_id=incident.tenant_id, include_unlinked=True - )[0]) == 120 + )[0]) == 100 incident = get_incident_by_id(SINGLE_TENANT_UUID, incident.id) diff --git a/tests/test_rules_engine.py b/tests/test_rules_engine.py index 7c032feeb..5abf1f5a9 100644 --- a/tests/test_rules_engine.py +++ b/tests/test_rules_engine.py @@ -385,6 +385,7 @@ def test_incident_resolution_on_all(db_session, create_alert): ) assert alert_count == 2 + # Same fingerprint create_alert( f"Something went wrong", AlertStatus.RESOLVED, @@ -409,7 +410,8 @@ def test_incident_resolution_on_all(db_session, create_alert): limit=10, offset=0, ) - assert alert_count == 3 + # Still 2 alerts, since 2 unique fingerprints + assert alert_count == 2 assert incident.status == IncidentStatus.FIRING.value create_alert( @@ -436,7 +438,7 @@ def test_incident_resolution_on_all(db_session, create_alert): limit=10, offset=0, ) - assert alert_count == 4 + assert alert_count == 2 assert incident.status == IncidentStatus.RESOLVED.value @@ -528,7 +530,7 @@ def test_incident_resolution_on_edge(db_session, create_alert, direction, second limit=10, offset=0, ) - assert alert_count == 3 + assert alert_count == 2 assert incident.status == IncidentStatus.FIRING.value create_alert( @@ -555,7 +557,7 @@ def test_incident_resolution_on_edge(db_session, create_alert, direction, second limit=10, offset=0, ) - assert alert_count == 4 + assert alert_count == 2 assert incident.status == IncidentStatus.RESOLVED.value # Next steps: