Skip to content

Commit

Permalink
chore(dynamic alert thresholds) Delete alert data endpoint (#1162)
Browse files Browse the repository at this point in the history
Add a new endpoint to delete a previously stored alert
  • Loading branch information
ram-senth authored Sep 13, 2024
1 parent 84ed952 commit 8a4432a
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 1 deletion.
20 changes: 19 additions & 1 deletion src/seer/anomaly_detection/accessors.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
)
from seer.anomaly_detection.models.external import AnomalyDetectionConfig, TimeSeriesPoint
from seer.db import DbDynamicAlert, DbDynamicAlertTimeSeries, Session
from seer.exceptions import ClientError

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -49,6 +50,10 @@ def save_timepoint(
):
return NotImplemented

@abc.abstractmethod
def delete_alert_data(self, external_alert_id: int):
return NotImplemented


class DbAlertDataAccessor(AlertDataAccessor):

Expand Down Expand Up @@ -179,7 +184,7 @@ def save_timepoint(
.one_or_none()
)
if existing is None:
raise Exception(f"Alert with id {external_alert_id} not found")
raise ClientError(f"Alert with id {external_alert_id} not found")

new_record = DbDynamicAlertTimeSeries(
dynamic_alert_id=existing.id,
Expand All @@ -191,3 +196,16 @@ def save_timepoint(
)
session.add(new_record)
session.commit()

@sentry_sdk.trace
def delete_alert_data(self, external_alert_id: int):
with Session() as session:
existing = (
session.query(DbDynamicAlert)
.filter_by(external_alert_id=external_alert_id)
.one_or_none()
)
if existing is None:
raise ClientError(f"Alert with id {external_alert_id} not found")
session.delete(existing)
session.commit()
17 changes: 17 additions & 0 deletions src/seer/anomaly_detection/anomaly_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
AlertInSeer,
Anomaly,
AnomalyDetectionConfig,
DeleteAlertDataRequest,
DeleteAlertDataResponse,
DetectAnomaliesRequest,
DetectAnomaliesResponse,
StoreDataRequest,
Expand Down Expand Up @@ -233,6 +235,7 @@ def detect_anomalies(self, request: DetectAnomaliesRequest) -> DetectAnomaliesRe
sentry_sdk.set_tag("ad_mode", mode)

if isinstance(request.context, AlertInSeer):
sentry_sdk.set_tag("alert_id", request.context.id)
ts, anomalies = self._online_detect(request.context, request.config)
elif isinstance(request.context, TimeSeriesWithHistory):
ts, anomalies = self._combo_detect(request.context, request.config)
Expand Down Expand Up @@ -287,3 +290,17 @@ def store_data(
anomaly_algo_data={"window_size": anomalies.window_size},
)
return StoreDataResponse(success=True)

@inject
def delete_alert_data(
self, request: DeleteAlertDataRequest, alert_data_accessor: AlertDataAccessor = injected
) -> DeleteAlertDataResponse:
"""
Main entry point for deleting data related to an alert.
Parameters:
request: DeleteAlertDataRequest
Alert to clear
"""
alert_data_accessor.delete_alert_data(external_alert_id=request.alert.id)
return DeleteAlertDataResponse(success=True)
11 changes: 11 additions & 0 deletions src/seer/anomaly_detection/models/external.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,14 @@ class StoreDataRequest(BaseModel):
class StoreDataResponse(BaseModel):
success: bool
message: Optional[str] = Field(None)


class DeleteAlertDataRequest(BaseModel):
organization_id: int
project_id: int
alert: AlertInSeer


class DeleteAlertDataResponse(BaseModel):
success: bool
message: Optional[str] = Field(None)
18 changes: 18 additions & 0 deletions src/seer/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from sentry_sdk.integrations.logging import LoggingIntegration

from seer.anomaly_detection.models.external import (
DeleteAlertDataRequest,
DeleteAlertDataResponse,
DetectAnomaliesRequest,
DetectAnomaliesResponse,
StoreDataRequest,
Expand Down Expand Up @@ -265,13 +267,29 @@ def detect_anomalies_endpoint(data: DetectAnomaliesRequest) -> DetectAnomaliesRe
def store_data_endpoint(data: StoreDataRequest) -> StoreDataResponse:
sentry_sdk.set_tag("organization_id", data.organization_id)
sentry_sdk.set_tag("project_id", data.project_id)
sentry_sdk.set_tag("alert_id", data.alert.id)
try:
response = anomaly_detection().store_data(data)
except ClientError as e:
response = StoreDataResponse(success=False, message=str(e))
return response


@json_api(blueprint, "/v1/anomaly-detection/delete-alert-data")
@sentry_sdk.trace
def delete_alert__data_endpoint(
data: DeleteAlertDataRequest,
) -> DeleteAlertDataResponse:
sentry_sdk.set_tag("organization_id", data.organization_id)
sentry_sdk.set_tag("project_id", data.project_id)
sentry_sdk.set_tag("alert_id", data.alert.id)
try:
response = anomaly_detection().delete_alert_data(data)
except ClientError as e:
response = DeleteAlertDataResponse(success=False, message=str(e))
return response


@blueprint.route("/health/live", methods=["GET"])
def health_check():
from seer.inference_models import models_loading_status
Expand Down

0 comments on commit 8a4432a

Please sign in to comment.