diff --git a/docs/snippets/providers/anthropic-snippet-autogenerated.mdx b/docs/snippets/providers/anthropic-snippet-autogenerated.mdx index 297b766ecc..d5a63f60b0 100644 --- a/docs/snippets/providers/anthropic-snippet-autogenerated.mdx +++ b/docs/snippets/providers/anthropic-snippet-autogenerated.mdx @@ -1,9 +1,11 @@ -{/* This snippet is automatically generated using scripts/docs_render_provider_snippets.py +{/* This snippet is automatically generated using scripts/docs_render_provider_snippets.py Do not edit it manually, as it will be overwritten */} ## Authentication This provider requires authentication. - **api_key**: Anthropic API Key (required: True, sensitive: True) +- **model**: Claude model to use (required: False, sensitive: False) +- **system_prompt**: System prompt that sets Claude's role for all requests in this provider. (required: False, sensitive: False) ## In workflows @@ -19,8 +21,9 @@ steps: config: "{{ provider.my_provider_name }}" with: prompt: {value} # The prompt to query the model with. - model: {value} # The model to query. + model: {value} # The model to query (overrides provider config). max_tokens: {value} # The maximum number of tokens to generate. + system_prompt: {value} # System prompt override for this call. structured_output_format: {value} # The structured output format to use. ``` diff --git a/docs/snippets/providers/prometheus-snippet-autogenerated.mdx b/docs/snippets/providers/prometheus-snippet-autogenerated.mdx index c574844c38..099e172e81 100644 --- a/docs/snippets/providers/prometheus-snippet-autogenerated.mdx +++ b/docs/snippets/providers/prometheus-snippet-autogenerated.mdx @@ -7,9 +7,10 @@ This provider requires authentication. - **username**: Prometheus username (required: False, sensitive: False) - **password**: Prometheus password (required: False, sensitive: True) - **verify**: Verify SSL certificates (required: False, sensitive: False) +- **thanos_compatible**: Enable Thanos compatibility mode (required: False, sensitive: False) Certain scopes may be required to perform specific actions or queries via the provider. Below is a summary of relevant scopes and their use cases: -- **connectivity**: Connectivity Test (mandatory) +- **connectivity**: Connectivity Test (mandatory) @@ -25,7 +26,7 @@ steps: provider: prometheus config: "{{ provider.my_provider_name }}" with: - query: {value} + query: {value} ``` diff --git a/keep/providers/prometheus_provider/prometheus_provider.py b/keep/providers/prometheus_provider/prometheus_provider.py index 7a9e2abf21..338c57d44d 100644 --- a/keep/providers/prometheus_provider/prometheus_provider.py +++ b/keep/providers/prometheus_provider/prometheus_provider.py @@ -49,6 +49,14 @@ class PrometheusProviderAuthConfig: }, default=True, ) + thanos_compatible: bool = dataclasses.field( + metadata={ + "description": "Enable Thanos compatibility mode", + "hint": "Set to true when connecting to a Thanos Querier — disables the /api/v1/alerts endpoint which Thanos does not support", + "sensitive": False, + }, + default=False, + ) class PrometheusProvider(BaseProvider, ProviderHealthMixin): @@ -112,7 +120,25 @@ def validate_config(self): def validate_scopes(self) -> dict[str, bool | str]: validated_scopes = {"connectivity": True} try: - self._get_alerts() + if self.authentication_config.thanos_compatible: + # Thanos doesn't support /api/v1/alerts; verify via /api/v1/rules instead + base_url = str(self.authentication_config.url).rstrip("/") + requests.get( + f"{base_url}/api/v1/rules", + params={"type": "alert"}, + auth=( + HTTPBasicAuth( + self.authentication_config.username, + self.authentication_config.password, + ) + if self.authentication_config.username + and self.authentication_config.password + else None + ), + verify=self.authentication_config.verify, + ).raise_for_status() + else: + self._get_alerts() except Exception as e: validated_scopes["connectivity"] = str(e) return validated_scopes @@ -156,15 +182,52 @@ def _get_alerts(self) -> list[AlertDto]: auth = HTTPBasicAuth( self.authentication_config.username, self.authentication_config.password ) - response = requests.get( - f"{self.authentication_config.url}/api/v1/alerts", - auth=auth, - verify=self.authentication_config.verify, - ) - response.raise_for_status() - if not response.ok: - return [] - alerts_data = response.json().get("data", {}) + + if self.authentication_config.thanos_compatible: + # Thanos Querier does not expose /api/v1/alerts (that endpoint only exists + # on Prometheus's rules evaluator). Use /api/v1/rules?type=alert instead — + # it is supported by Thanos and returns annotations, state, and activeAt. + import hashlib + import json as _json + + base_url = str(self.authentication_config.url).rstrip("/") + response = requests.get( + f"{base_url}/api/v1/rules", + params={"type": "alert"}, + auth=auth, + verify=self.authentication_config.verify, + ) + response.raise_for_status() + rule_groups = response.json().get("data", {}).get("groups", []) + alerts_data = {"alerts": []} + for group in rule_groups: + for rule in group.get("rules", []): + if rule.get("type") != "alerting": + continue + for alert in rule.get("alerts", []): + labels = alert.get("labels", {}) + fp_src = _json.dumps(labels, sort_keys=True) + fingerprint = hashlib.md5(fp_src.encode()).hexdigest() + alerts_data["alerts"].append( + { + "labels": labels, + "annotations": alert.get("annotations", {}), + "state": alert.get("state", "firing"), + "activeAt": alert.get("activeAt"), + "fingerprint": fingerprint, + } + ) + else: + response = requests.get( + f"{self.authentication_config.url}/api/v1/alerts", + auth=auth, + verify=self.authentication_config.verify, + ) + response.raise_for_status() + if not response.ok: + return [] + alerts_data = response.json().get("data", {}) + alert_dtos = self._format_alert(alerts_data) return alert_dtos