diff --git a/keep-ui/app/workflows/builder/builder.tsx b/keep-ui/app/workflows/builder/builder.tsx index e2400c65c..d217e5386 100644 --- a/keep-ui/app/workflows/builder/builder.tsx +++ b/keep-ui/app/workflows/builder/builder.tsx @@ -322,7 +322,7 @@ function Builder({ icon={CheckCircleIcon} color="teal" > - Alert can be generated successfully + Workflow can be generated successfully ); }; diff --git a/keep/api/tasks/process_event_task.py b/keep/api/tasks/process_event_task.py index 4f7ee3f1f..53a064dcc 100644 --- a/keep/api/tasks/process_event_task.py +++ b/keep/api/tasks/process_event_task.py @@ -496,7 +496,7 @@ def process_event( api_key_name: str | None, trace_id: str | None, # so we can track the job from the request to the digest event: ( - AlertDto | list[AlertDto] | IncidentDto | list[IncidentDto] | dict + AlertDto | list[AlertDto] | IncidentDto | list[IncidentDto] | dict | None ), # the event to process, either plain (generic) or from a specific provider notify_client: bool = True, timestamp_forced: datetime.datetime | None = None, @@ -547,6 +547,11 @@ def process_event( "This is a subscription notification message from AWS - skipping processing" ) return + elif event is None: + logger.info( + "Provider returned None (failed silently), skipping processing" + ) + return # In case when provider_type is not set if isinstance(event, dict): diff --git a/keep/providers/base/base_provider.py b/keep/providers/base/base_provider.py index ebb92685c..493c29001 100644 --- a/keep/providers/base/base_provider.py +++ b/keep/providers/base/base_provider.py @@ -24,12 +24,7 @@ get_enrichments, is_linked_provider, ) -from keep.api.models.alert import ( - AlertDto, - AlertSeverity, - AlertStatus, - IncidentDto, -) +from keep.api.models.alert import AlertDto, AlertSeverity, AlertStatus, IncidentDto from keep.api.models.db.alert import AlertActionType from keep.api.models.db.topology import TopologyServiceInDto from keep.api.utils.enrichment_helpers import parse_and_enrich_deleted_and_assignees @@ -324,7 +319,7 @@ def format_alert( tenant_id: str | None, provider_type: str | None, provider_id: str | None, - ) -> AlertDto | list[AlertDto]: + ) -> AlertDto | list[AlertDto] | None: logger = logging.getLogger(__name__) provider_instance: BaseProvider | None = None @@ -355,6 +350,11 @@ def format_alert( ) logger.debug("Formatting alert") formatted_alert = cls._format_alert(event, provider_instance) + if formatted_alert is None: + logger.debug( + "Provider returned None, which means it decided not to format the alert" + ) + return None logger.debug("Alert formatted") # after the provider calculated the default fingerprint # check if there is a custom deduplication rule and apply @@ -785,4 +785,4 @@ def setup_incident_webhook( Raises: NotImplementedError: _description_ """ - raise NotImplementedError("setup_webhook() method not implemented") \ No newline at end of file + raise NotImplementedError("setup_webhook() method not implemented") diff --git a/keep/providers/pagerduty_provider/pagerduty_provider.py b/keep/providers/pagerduty_provider/pagerduty_provider.py index f31f0c75a..fd8318278 100644 --- a/keep/providers/pagerduty_provider/pagerduty_provider.py +++ b/keep/providers/pagerduty_provider/pagerduty_provider.py @@ -281,6 +281,16 @@ def validate_scopes(self): headers = self.__get_headers() scopes = {} for scope in self.PROVIDER_SCOPES: + + # If the provider is installed using a routing key, we skip scopes validation for now. + if self.authentication_config.routing_key: + if scope.name == "incidents_read": + # This is because incidents_read is mandatory and will not let the provider install otherwise + scopes[scope.name] = True + else: + scopes[scope.name] = "Skipped due to routing key" + continue + try: # Todo: how to check validity for write scopes? if scope.name.startswith("incidents"): @@ -351,11 +361,19 @@ def _send_alert(self, title: str, body: str, dedup: str | None = None): url = "https://events.pagerduty.com/v2/enqueue" - result = requests.post(url, json=self._build_alert(title, body, dedup)) + payload = self._build_alert(title, body, dedup) + result = requests.post(url, json=payload) + result.raise_for_status() - self.logger.debug("Alert status: %s", result.status_code) - self.logger.debug("Alert response: %s", result.text) - return result.text + self.logger.info( + "Sent alert to PagerDuty", + extra={ + "status_code": result.status_code, + "response_text": result.text, + "routing_key": self.authentication_config.routing_key, + }, + ) + return result.json() def _trigger_incident( self, @@ -403,6 +421,11 @@ def setup_incident_webhook( setup_alerts: bool = True, ): self.logger.info("Setting up Pagerduty webhook") + + if self.authentication_config.routing_key: + self.logger.info("Skipping webhook setup due to routing key") + return + headers = self.__get_headers() request = requests.get(self.SUBSCRIPTION_API_URL, headers=headers) if not request.ok: @@ -534,6 +557,11 @@ def _format_alert( def _format_alert_old(event: dict) -> AlertDto: actual_event = event.get("event", {}) data = actual_event.get("data", {}) + + event_type = data.get("type", "incident") + if event_type != "incident": + return None + url = data.pop("self", data.pop("html_url", None)) # format status and severity to Keep format status = PagerdutyProvider.ALERT_STATUS_MAP.get(data.pop("status", "firing")) @@ -648,6 +676,10 @@ def __get_all_services(self, business_services: bool = False): return all_services def pull_topology(self) -> list[TopologyServiceInDto]: + # Skipping topology pulling when we're installed with routing_key + if self.authentication_config.routing_key: + return [] + all_services = self.__get_all_services() all_business_services = self.__get_all_services(business_services=True) service_metadata = {} @@ -701,6 +733,10 @@ def pull_topology(self) -> list[TopologyServiceInDto]: return list(service_topology.values()) def _get_incidents(self) -> list[IncidentDto]: + # Skipping incidents pulling when we're installed with routing_key + if self.authentication_config.routing_key: + return [] + raw_incidents = self.__get_all_incidents_or_alerts() incidents = [] for incident in raw_incidents: diff --git a/pyproject.toml b/pyproject.toml index 31159eeab..390c1f11e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "keep" -version = "0.28.7" +version = "0.28.8" description = "Alerting. for developers, by developers." authors = ["Keep Alerting LTD"] readme = "README.md"