Skip to content

Commit dddcf05

Browse files
authored
feat(llm-detecor): Add basic task for LLM issue detection (#101637)
this pr adds a base task for LLM issue detection - it's basically a no-op right now, but sets the foundation for future changes that actually gather the data and make the request. https://linear.app/getsentry/issue/ID-1006/create-base-cron-job-for-llm-detected-issues
1 parent be7268d commit dddcf05

File tree

4 files changed

+86
-0
lines changed

4 files changed

+86
-0
lines changed

.github/CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ pnpm-lock.yaml @getsentry/owners-js-de
575575
/src/sentry/tasks/post_process.py @getsentry/issue-detection-backend
576576
/src/sentry/tasks/unmerge.py @getsentry/issue-detection-backend
577577
/src/sentry/tasks/weekly_escalating_forecast.py @getsentry/issue-detection-backend
578+
/src/sentry/tasks/llm_issue_detection.py @getsentry/issue-detection-backend
578579
/static/app/components/events/contexts/ @getsentry/issue-workflow
579580
/static/app/components/events/eventTags/ @getsentry/issue-workflow
580581
/static/app/components/events/highlights/ @getsentry/issue-workflow
@@ -615,6 +616,7 @@ pnpm-lock.yaml @getsentry/owners-js-de
615616
/tests/sentry/tasks/test_merge.py @getsentry/issue-detection-backend
616617
/tests/sentry/tasks/test_post_process.py @getsentry/issue-detection-backend
617618
/tests/sentry/tasks/test_weekly_escalating_forecast.py @getsentry/issue-detection-backend
619+
/tests/sentry/tasks/test_llm_issue_detection.py @getsentry/issue-detection-backend
618620
/tests/snuba/search/ @getsentry/issue-workflow
619621
## End of Issues
620622

src/sentry/conf/server.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,7 @@ def SOCIAL_AUTH_DEFAULT_USERNAME() -> str:
895895
"sentry.tasks.email",
896896
"sentry.tasks.embeddings_grouping.backfill_seer_grouping_records_for_project",
897897
"sentry.tasks.groupowner",
898+
"sentry.tasks.llm_issue_detection",
898899
"sentry.tasks.merge",
899900
"sentry.tasks.on_demand_metrics",
900901
"sentry.tasks.options",
@@ -1102,6 +1103,10 @@ def SOCIAL_AUTH_DEFAULT_USERNAME() -> str:
11021103
"task": "ai_agent_monitoring:sentry.tasks.ai_agent_monitoring.fetch_ai_model_costs",
11031104
"schedule": task_crontab("*/30", "*", "*", "*", "*"),
11041105
},
1106+
"llm-issue-detection": {
1107+
"task": "issues:sentry.tasks.llm_issue_detection.run_llm_issue_detection",
1108+
"schedule": task_crontab("*/30", "*", "*", "*", "*"),
1109+
},
11051110
"preprod-detect-expired-artifacts": {
11061111
"task": "preprod:sentry.preprod.tasks.detect_expired_preprod_artifacts",
11071112
"schedule": task_crontab("0", "*", "*", "*", "*"),
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from __future__ import annotations
2+
3+
import logging
4+
5+
from sentry import options
6+
from sentry.models.project import Project
7+
from sentry.tasks.base import instrumented_task
8+
from sentry.taskworker.namespaces import issues_tasks
9+
10+
logger = logging.getLogger("sentry.tasks.llm_issue_detection")
11+
12+
13+
def get_enabled_project_ids() -> list[int]:
14+
"""
15+
Get the list of project IDs that are explicitly enabled for LLM detection.
16+
17+
Returns the allowlist from system options.
18+
"""
19+
return options.get("issue-detection.llm-detection.projects-allowlist")
20+
21+
22+
@instrumented_task(
23+
name="sentry.tasks.llm_issue_detection.run_llm_issue_detection",
24+
namespace=issues_tasks,
25+
processing_deadline_duration=120,
26+
)
27+
def run_llm_issue_detection() -> None:
28+
"""
29+
Main scheduled task for LLM issue detection.
30+
"""
31+
if not options.get("issue-detection.llm-detection.enabled"):
32+
return
33+
34+
enabled_project_ids = get_enabled_project_ids()
35+
if not enabled_project_ids:
36+
return
37+
38+
# Spawn a sub-task for each project
39+
for project_id in enabled_project_ids:
40+
detect_llm_issues_for_project.delay(project_id)
41+
42+
43+
@instrumented_task(
44+
name="sentry.tasks.llm_issue_detection.detect_llm_issues_for_project",
45+
namespace=issues_tasks,
46+
processing_deadline_duration=120,
47+
)
48+
def detect_llm_issues_for_project(project_id: int) -> None:
49+
"""
50+
Process a single project for LLM issue detection.
51+
"""
52+
project = Project.objects.get(id=project_id)
53+
54+
logger.info(
55+
"Processing project for LLM detection",
56+
extra={"project_id": project.id, "org_id": project.organization_id},
57+
)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from unittest.mock import patch
2+
3+
from sentry.tasks.llm_issue_detection import run_llm_issue_detection
4+
from sentry.testutils.cases import TestCase
5+
6+
7+
class LLMIssueDetectionTest(TestCase):
8+
@patch("sentry.tasks.llm_issue_detection.detect_llm_issues_for_project.delay")
9+
def test_run_detection_dispatches_sub_tasks(self, mock_delay):
10+
"""Test run_detection spawns sub-tasks for each project."""
11+
project = self.create_project()
12+
13+
with self.options(
14+
{
15+
"issue-detection.llm-detection.enabled": True,
16+
"issue-detection.llm-detection.projects-allowlist": [project.id],
17+
}
18+
):
19+
run_llm_issue_detection()
20+
21+
assert mock_delay.called
22+
assert mock_delay.call_args[0][0] == project.id

0 commit comments

Comments
 (0)