From 8856e7e0dffb526d769905416e5bbd19e82bec49 Mon Sep 17 00:00:00 2001 From: Tal Date: Thu, 14 Nov 2024 10:16:38 +0200 Subject: [PATCH] fix(pd): dedup, severity and event_type derieved from event context (#2480) --- keep/contextmanager/contextmanager.py | 3 +- .../pagerduty_provider/pagerduty_provider.py | 60 +++++++++++++++---- pyproject.toml | 2 +- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/keep/contextmanager/contextmanager.py b/keep/contextmanager/contextmanager.py index 59ca134bc..2dad2563b 100644 --- a/keep/contextmanager/contextmanager.py +++ b/keep/contextmanager/contextmanager.py @@ -6,6 +6,7 @@ from keep.api.core.db import get_last_workflow_execution_by_workflow_id, get_session from keep.api.logging import WorkflowLoggerAdapter +from keep.api.models.alert import AlertDto class ContextManager: @@ -21,7 +22,7 @@ def __init__(self, tenant_id, workflow_id=None, workflow_execution_id=None): self.steps_context_size = 0 self.providers_context = {} self.actions_context = {} - self.event_context = {} + self.event_context: AlertDto = {} self.incident_context = {} self.foreach_context = { "value": None, diff --git a/keep/providers/pagerduty_provider/pagerduty_provider.py b/keep/providers/pagerduty_provider/pagerduty_provider.py index eac09653d..5e9ea7e2a 100644 --- a/keep/providers/pagerduty_provider/pagerduty_provider.py +++ b/keep/providers/pagerduty_provider/pagerduty_provider.py @@ -111,11 +111,17 @@ class PagerdutyProvider(BaseTopologyProvider, BaseIncidentProvider): "triggered": AlertStatus.FIRING, "resolved": AlertStatus.RESOLVED, } + ALERT_STATUS_TO_EVENT_TYPE_MAP = { + AlertStatus.FIRING.value: "trigger", + AlertStatus.RESOLVED.value: "resolve", + AlertStatus.ACKNOWLEDGED.value: "acknowledge", + } INCIDENT_STATUS_MAP = { "triggered": IncidentStatus.FIRING, "acknowledged": IncidentStatus.ACKNOWLEDGED, "resolved": IncidentStatus.RESOLVED, } + BASE_OAUTH_URL = "https://identity.pagerduty.com" PAGERDUTY_CLIENT_ID = os.environ.get("PAGERDUTY_CLIENT_ID") PAGERDUTY_CLIENT_SECRET = os.environ.get("PAGERDUTY_CLIENT_SECRET") @@ -322,8 +328,10 @@ def _build_alert( self, title: str, alert_body: str, - dedup: str, - event_type: typing.Literal["trigger", "acknowledge", "resolve"] = "trigger", + dedup: str | None = None, + severity: typing.Literal["critical", "error", "warning", "info"] | None = None, + event_type: typing.Literal["trigger", "acknowledge", "resolve"] | None = None, + source: str = "custom_event", ) -> typing.Dict[str, typing.Any]: """ Builds the payload for an event alert. @@ -337,14 +345,37 @@ def _build_alert( Returns: Dictionary of alert body for JSON serialization """ + if not severity: + # this is the default severity + severity = "critical" + # try to get it automatically from the context (if there's an alert, for example) + if self.context_manager.event_context: + severity = self.context_manager.event_context.severity + + if not event_type: + event_type = "trigger" + # try to get it automatically from the context (if there's an alert, for example) + if self.context_manager.event_context: + status = self.context_manager.event_context.status + event_type = PagerdutyProvider.ALERT_STATUS_TO_EVENT_TYPE_MAP.get( + status, "trigger" + ) + + if not dedup: + # If no dedup is given, use epoch timestamp + dedup = str(datetime.datetime.now().timestamp()) + # Try to get it from the context (if there's an alert, for example) + if self.context_manager.event_context: + dedup = self.context_manager.event_context.fingerprint + return { "routing_key": self.authentication_config.routing_key, "event_action": event_type, "dedup_key": dedup, "payload": { "summary": title, - "source": "custom_event", - "severity": "critical", + "source": source, + "severity": severity, "custom_details": { "alert_body": alert_body, }, @@ -356,7 +387,9 @@ def _send_alert( title: str, body: str, dedup: str | None = None, - event_type: typing.Literal["trigger", "acknowledge", "resolve"] = "trigger", + severity: typing.Literal["critical", "error", "warning", "info"] | None = None, + event_type: typing.Literal["trigger", "acknowledge", "resolve"] | None = None, + source: str = "custom_event", ): """ Sends PagerDuty Alert @@ -367,13 +400,9 @@ def _send_alert( dedup: Any string, max 255, characters used to deduplicate alerts event_type: The type of event to send to PagerDuty """ - # If no dedup is given, use epoch timestamp - if dedup is None: - dedup = str(datetime.datetime.now().timestamp()) - url = "https://events.pagerduty.com/v2/enqueue" - payload = self._build_alert(title, body, dedup, event_type) + payload = self._build_alert(title, body, dedup, severity, event_type, source) result = requests.post(url, json=payload) result.raise_for_status() @@ -508,7 +537,9 @@ def _notify( service_id: str = "", requester: str = "", incident_id: str = "", - event_type: typing.Literal["trigger", "acknowledge", "resolve"] = "trigger", + event_type: typing.Literal["trigger", "acknowledge", "resolve"] | None = None, + severity: typing.Literal["critical", "error", "warning", "info"] | None = None, + source: str = "custom_event", **kwargs: dict, ): """ @@ -521,7 +552,12 @@ def _notify( """ if self.authentication_config.routing_key: return self._send_alert( - title, alert_body, dedup=dedup, event_type=event_type + title, + alert_body, + dedup=dedup, + event_type=event_type, + source=source, + severity=severity, ) else: return self._trigger_incident( diff --git a/pyproject.toml b/pyproject.toml index 12520a94b..79267d83d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "keep" -version = "0.28.9" +version = "0.28.10" description = "Alerting. for developers, by developers." authors = ["Keep Alerting LTD"] readme = "README.md"