Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions src/sentry/seer/assisted_query/issues_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,14 @@ def get_issue_filter_keys(
stats_period: str | None = None,
start: str | None = None,
end: str | None = None,
include_feature_flags: bool = True,
) -> dict[str, Any] | None:
"""
Get available issue filter keys (tags, feature flags, and built-in fields).

Calls the Sentry tags API endpoint with different datasets to get:
- Tags (dataset=events and dataset=search_issues merged)
- Feature flags (dataset=events with useFlagsBackend=1)
- Feature flags (dataset=events with useFlagsBackend=1) - optional
- Built-in fields (e.g., is, assigned_or_suggested, issue.priority, etc.)

Args:
Expand All @@ -266,11 +267,12 @@ def get_issue_filter_keys(
stats_period: Time period for the query (e.g., "24h", "7d", "14d"). Cannot be provided with start and end.
start: Start date for the query (ISO string). Must be provided with end.
end: End date for the query (ISO string). Must be provided with start.
include_feature_flags: Whether to include feature flags in the response (default True).

Returns:
Dictionary containing three arrays:
Dictionary containing:
- tags: Merged tags from events and search_issues datasets
- feature_flags: Feature flags from events dataset
- feature_flags: Feature flags from events dataset (only if include_feature_flags is True)
- built_in_fields: Built-in issue search fields (e.g., is, assigned_or_suggested, issue.priority)
Returns None if organization doesn't exist.
"""
Expand Down Expand Up @@ -328,31 +330,37 @@ def get_issue_filter_keys(
tags_dict[tag.get("key")] = tag
tags = list(tags_dict.values())

# Get feature flags
flags_params = {
**base_params,
"dataset": Dataset.Events.value,
"useFlagsBackend": "1",
"useCache": "1",
}
flags_resp = client.get(
auth=api_key,
user=None,
path=f"/organizations/{organization.slug}/tags/",
params=flags_params,
)
feature_flags = flags_resp.data if flags_resp.status_code == 200 else []
# Get feature flags (optional)
feature_flags: list[Any] = []
if include_feature_flags:
flags_params = {
**base_params,
"dataset": Dataset.Events.value,
"useFlagsBackend": "1",
"useCache": "1",
}
flags_resp = client.get(
auth=api_key,
user=None,
path=f"/organizations/{organization.slug}/tags/",
params=flags_params,
)
feature_flags = flags_resp.data if flags_resp.status_code == 200 else []

# Get built-in issue fields
tag_keys = [tag.get("key") for tag in tags if tag.get("key")]
built_in_fields = _get_built_in_issue_fields(organization, tag_keys)

return {
result: dict[str, Any] = {
"tags": tags,
"feature_flags": feature_flags,
"built_in_fields": built_in_fields,
}

if include_feature_flags:
result["feature_flags"] = feature_flags

return result


def get_filter_key_values(
*,
Expand Down
73 changes: 73 additions & 0 deletions tests/sentry/seer/assisted_query/test_issues_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,79 @@ def test_get_issue_filter_keys_multiple_projects(self):
assert "project1_tag" in tag_keys
assert "project2_tag" in tag_keys

def test_get_issue_filter_keys_without_feature_flags(self):
"""Test that feature flags are excluded when include_feature_flags=False"""
# Create an error event with custom tags
self.store_event(
data={
"event_id": "a" * 32,
"tags": {"fruit": "apple"},
"timestamp": self.min_ago.isoformat(),
},
project_id=self.project.id,
)

# Create an event with feature flags
self.store_event(
data={
"contexts": {
"flags": {
"values": [
{"flag": "feature_a", "result": True},
]
}
},
"timestamp": self.min_ago.isoformat(),
},
project_id=self.project.id,
)

result = get_issue_filter_keys(
org_id=self.organization.id,
project_ids=[self.project.id],
include_feature_flags=False,
)

assert result is not None
# Tags and built_in_fields should still be present
assert "tags" in result
assert "built_in_fields" in result
# feature_flags key should NOT be in the result
assert "feature_flags" not in result

# Verify tags still work
tags = result["tags"]
tag_keys = {tag["key"] for tag in tags}
assert "fruit" in tag_keys

def test_get_issue_filter_keys_with_feature_flags_default(self):
"""Test that feature flags are included by default"""
# Create an event with feature flags
self.store_event(
data={
"contexts": {
"flags": {
"values": [
{"flag": "feature_a", "result": True},
]
}
},
"timestamp": self.min_ago.isoformat(),
},
project_id=self.project.id,
)

# Call without specifying include_feature_flags (should default to True)
result = get_issue_filter_keys(
org_id=self.organization.id,
project_ids=[self.project.id],
)

assert result is not None
# feature_flags key should be present by default
assert "feature_flags" in result
assert isinstance(result["feature_flags"], list)


@pytest.mark.django_db(databases=["default", "control"])
class TestGetFilterKeyValues(APITestCase, SnubaTestCase, OccurrenceTestMixin):
Expand Down
Loading