-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(workflow-engine): add EventAttributeConditionHandler
#82741
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,10 @@ | ||
from typing import Any | ||
|
||
import sentry_sdk | ||
|
||
from sentry.rules import MatchType, match_values | ||
from sentry.rules.conditions.event_attribute import attribute_registry | ||
from sentry.utils.registry import NoRegistrationExistsError | ||
from sentry.workflow_engine.models.data_condition import Condition | ||
from sentry.workflow_engine.registry import condition_handler_registry | ||
from sentry.workflow_engine.types import DataConditionHandler, WorkflowJob | ||
|
@@ -29,3 +34,45 @@ class EventSeenCountConditionHandler(DataConditionHandler[WorkflowJob]): | |
def evaluate_value(job: WorkflowJob, comparison: Any) -> bool: | ||
event = job["event"] | ||
return event.group.times_seen == comparison | ||
|
||
|
||
@condition_handler_registry.register(Condition.EVENT_ATTRIBUTE) | ||
class EventAttributeConditionHandler(DataConditionHandler[WorkflowJob]): | ||
@staticmethod | ||
def evaluate_value(job: WorkflowJob, comparison: Any) -> bool: | ||
event = job["event"] | ||
|
||
attribute = comparison.get("attribute", "") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think |
||
path = attribute.split(".") | ||
first_attribute = path[0] | ||
try: | ||
attribute_handler = attribute_registry.get(first_attribute) | ||
except NoRegistrationExistsError: | ||
attribute_handler = None | ||
|
||
if not attribute_handler: | ||
attribute_values = [] | ||
else: | ||
try: | ||
attribute_values = attribute_handler.handle(path, event) | ||
except KeyError as e: | ||
attribute_values = [] | ||
sentry_sdk.capture_exception(e) | ||
|
||
match = comparison.get("match") | ||
desired_value = comparison.get("value") | ||
if not (match and desired_value) and not (match in (MatchType.IS_SET, MatchType.NOT_SET)): | ||
return False | ||
|
||
desired_value = str(desired_value).lower() | ||
attribute_values = [str(value).lower() for value in attribute_values if value is not None] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this go inside |
||
|
||
# NOTE: IS_SET condition differs btw tagged_event and event_attribute so not handled by match_values | ||
if match == MatchType.IS_SET: | ||
return bool(attribute_values) | ||
elif match == MatchType.NOT_SET: | ||
return not attribute_values | ||
|
||
return match_values( | ||
group_values=attribute_values, match_value=desired_value, match_type=match | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
from collections.abc import Callable | ||
from typing import Any | ||
|
||
from sentry.rules.conditions.event_attribute import EventAttributeCondition | ||
from sentry.rules.conditions.every_event import EveryEventCondition | ||
from sentry.rules.conditions.existing_high_priority_issue import ExistingHighPriorityIssueCondition | ||
from sentry.rules.conditions.reappeared_event import ReappearedEventCondition | ||
|
@@ -65,3 +66,15 @@ def create_existing_high_priority_issue_data_condition( | |
condition_result=True, | ||
condition_group=dcg, | ||
) | ||
|
||
|
||
@data_condition_translator_registry.register(EventAttributeCondition.id) | ||
def create_event_attribute_data_condition( | ||
data: dict[str, Any], dcg: DataConditionGroup | ||
) -> DataCondition: | ||
return DataCondition.objects.create( | ||
type=Condition.EVENT_ATTRIBUTE, | ||
comparison=True, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where are the attribute, match type, and desired value being stored? one way to do this is to put them in a dictionary and |
||
condition_result=True, | ||
condition_group=dcg, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: if there's a lot happening in this function you can also break it up into several smaller ones