diff --git a/examples/workflows/create_alert_from_vm_metric.yml b/examples/workflows/create_alert_from_vm_metric.yml index e4eaaeaa4..e28ff9d02 100644 --- a/examples/workflows/create_alert_from_vm_metric.yml +++ b/examples/workflows/create_alert_from_vm_metric.yml @@ -15,22 +15,25 @@ workflow: actions: - name: create-alert - alias: - # assign the value of the query result to the alias `cpu` - # so we can use it anywhere in the action - cpu: "{{ steps.victoriametrics-step.results.data.result.0.value.1 }}" # only create an alert if the CPU usage is greater than 0.005 - if: "{{ aliases.cpu }} > 0.005 " + if: "{{ steps.victoriametrics-step.results.data.result.0.value.1 }} > 0.001 " provider: type: keep # create an alert with the following details with: name: "High CPU Usage" description: "CPU usage is high on the VM (created from VM metric)" - severity: '{{ aliases.cpu }} > 0.9 ? "critical" : {{ aliases.cpu }} > 0.7 ? "warning" : "info"' + severity: '{{ steps.victoriametrics-step.results.data.result.0.value.1 }} > 0.9 ? "critical" : {{ steps.victoriametrics-step.results.data.result.0.value.1 }} > 0.7 ? "warning" : "info"' labels: environment: production app: myapp service: api team: devops owner: alice + # optional: customize the fingerprint based on these fields + fingerprint_fields: + - environment + - app + - service + - team + - owner diff --git a/keep/providers/keep_provider/keep_provider.py b/keep/providers/keep_provider/keep_provider.py index ff45fcda2..df898d55e 100644 --- a/keep/providers/keep_provider/keep_provider.py +++ b/keep/providers/keep_provider/keep_provider.py @@ -1,21 +1,22 @@ """ Keep Provider is a class that allows to ingest/digest data from Keep. """ -import yaml + import logging -from html import unescape from datetime import datetime, timezone +from html import unescape +import yaml from keep.api.core.db import get_alerts_with_filters from keep.api.models.alert import AlertDto +from keep.api.tasks.process_event_task import process_event from keep.contextmanager.contextmanager import ContextManager from keep.exceptions.provider_exception import ProviderException from keep.providers.base.base_provider import BaseProvider from keep.providers.models.provider_config import ProviderConfig from keep.searchengine.searchengine import SearchEngine from keep.workflowmanager.workflowstore import WorkflowStore -from keep.api.tasks.process_event_task import process_event class KeepProvider(BaseProvider): @@ -127,49 +128,63 @@ def _notify(self, **kwargs): workflow_to_update_yaml = unescape(workflow_to_update_yaml) workflow_to_update_yaml = yaml.safe_load(workflow_to_update_yaml) - if 'workflow' in workflow_to_update_yaml: - workflow_to_update_yaml = workflow_to_update_yaml['workflow'] + if "workflow" in workflow_to_update_yaml: + workflow_to_update_yaml = workflow_to_update_yaml["workflow"] workflow = workflowstore.create_workflow( - tenant_id=self.context_manager.tenant_id, - created_by=f"workflow id: {self.context_manager.workflow_id}", - workflow=workflow_to_update_yaml + tenant_id=self.context_manager.tenant_id, + created_by=f"workflow id: {self.context_manager.workflow_id}", + workflow=workflow_to_update_yaml, ) except Exception as e: self.logger.exception( "Failed to create workflow", - extra={"tenant_id": context_manager.tenant_id, "workflow": workflow}, + extra={ + "tenant_id": context_manager.tenant_id, + "workflow": workflow, + }, ) raise ProviderException(f"Failed to create workflow: {e}") else: + fingerprint_fields = kwargs.get("fingerprint_fields", []) alert = AlertDto( - name=kwargs['name'], - status=kwargs.get('status'), - lastReceived=kwargs.get('lastReceived'), - environment=kwargs.get('environment', "undefined"), - duplicateReason=kwargs.get('duplicateReason'), - service=kwargs.get('service'), - message=kwargs.get('message'), - description=kwargs.get('description'), - severity=kwargs.get('severity'), + name=kwargs["name"], + status=kwargs.get("status"), + lastReceived=kwargs.get("lastReceived"), + environment=kwargs.get("environment", "undefined"), + duplicateReason=kwargs.get("duplicateReason"), + service=kwargs.get("service"), + message=kwargs.get("message"), + description=kwargs.get("description"), + severity=kwargs.get("severity"), pushed=True, - url=kwargs.get('url'), - labels=kwargs.get('labels'), - ticket_url=kwargs.get('ticket_url'), - fingerprint=kwargs.get('fingerprint'), + url=kwargs.get("url"), + labels=kwargs.get("labels"), + ticket_url=kwargs.get("ticket_url"), + fingerprint=kwargs.get("fingerprint"), ) + # if fingerprint_fields are provided, calculate fingerprint + if fingerprint_fields: + # calculate fingerprint + self.logger.info( + "Calculating fingerprint for alert", + extra={"fingerprint_fields": fingerprint_fields}, + ) + alert.fingerprint = self.get_alert_fingerprint( + alert, fingerprint_fields + ) + process_event( {}, self.context_manager.tenant_id, "keep", None, - kwargs.get('fingerprint'), + kwargs.get("fingerprint"), None, None, alert, ) - def validate_config(self): """ Validates required configuration for Keep provider. diff --git a/poetry.lock b/poetry.lock index eac7cef4d..c6e767002 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1287,24 +1287,6 @@ idna = ["idna (>=3.7)"] trio = ["trio (>=0.23)"] wmi = ["wmi (>=1.5.1)"] -[[package]] -name = "ecdsa" -version = "0.19.0" -description = "ECDSA cryptographic signature library (pure python)" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.6" -files = [ - {file = "ecdsa-0.19.0-py2.py3-none-any.whl", hash = "sha256:2cea9b88407fdac7bbeca0833b189e4c9c53f2ef1e1eaa29f6224dbc809b707a"}, - {file = "ecdsa-0.19.0.tar.gz", hash = "sha256:60eaad1199659900dd0af521ed462b793bbdf867432b3948e87416ae4caf6bf8"}, -] - -[package.dependencies] -six = ">=1.9.0" - -[package.extras] -gmpy = ["gmpy"] -gmpy2 = ["gmpy2"] - [[package]] name = "elastic-transport" version = "8.15.1" @@ -3007,7 +2989,7 @@ name = "ndg-httpsclient" version = "0.5.1" description = "Provides enhanced HTTPS support for httplib and urllib2 using PyOpenSSL" optional = false -python-versions = ">=2.7,<3.0.0 || >=3.4.0" +python-versions = ">=2.7,<3.0.dev0 || >=3.4.dev0" files = [ {file = "ndg_httpsclient-0.5.1-py2-none-any.whl", hash = "sha256:d2c7225f6a1c6cf698af4ebc962da70178a99bcde24ee6d1961c4f3338130d57"}, {file = "ndg_httpsclient-0.5.1-py3-none-any.whl", hash = "sha256:dd174c11d971b6244a891f7be2b32ca9853d3797a72edb34fa5d7b07d8fff7d4"}, @@ -4477,27 +4459,6 @@ files = [ {file = "python_http_client-3.3.7.tar.gz", hash = "sha256:bf841ee45262747e00dec7ee9971dfb8c7d83083f5713596488d67739170cea0"}, ] -[[package]] -name = "python-jose" -version = "3.3.0" -description = "JOSE implementation in Python" -optional = false -python-versions = "*" -files = [ - {file = "python-jose-3.3.0.tar.gz", hash = "sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a"}, - {file = "python_jose-3.3.0-py2.py3-none-any.whl", hash = "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a"}, -] - -[package.dependencies] -ecdsa = "!=0.15" -pyasn1 = "*" -rsa = "*" - -[package.extras] -cryptography = ["cryptography (>=3.4.0)"] -pycrypto = ["pyasn1", "pycrypto (>=2.6.0,<2.7.0)"] -pycryptodome = ["pyasn1", "pycryptodome (>=3.3.1,<4.0.0)"] - [[package]] name = "python-json-logger" version = "2.0.7" @@ -5808,4 +5769,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "4e964a1857ac02dd12d32302c69392c614348a9dd269004deedbf9a0e5d108f9" +content-hash = "198a2966e0e24eb5b78aa2ca3e5acf29ddaa1ffda1ef219ebce4f856253b5d3a" diff --git a/pyproject.toml b/pyproject.toml index 82ae76ca7..fa433feda 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,6 @@ sqlmodel = "^0.0.22" cloud-sql-python-connector = "1.12.0" pymysql = "^1.1.1" google-cloud-secret-manager = "^2.16.1" -python-jose = "^3.3.0" sqlalchemy = "^2.0.14" snowflake-connector-python = "3.12.3" openai = "1.37.1"