diff --git a/src/sentry/tasks/web_vitals_issue_detection.py b/src/sentry/tasks/web_vitals_issue_detection.py index 5661984da6d37e..429ad7db83b19a 100644 --- a/src/sentry/tasks/web_vitals_issue_detection.py +++ b/src/sentry/tasks/web_vitals_issue_detection.py @@ -103,7 +103,7 @@ def dispatch_detection_for_project_ids( results[project.id] = {"success": False, "reason": "web_vitals_detection_not_enabled"} continue - detect_web_vitals_issues_for_project.delay(project.id) + detect_web_vitals_issues_for_project.delay(project.id, project.organization.slug) results[project.id] = {"success": True} projects_dispatched_count += 1 @@ -126,11 +126,23 @@ def dispatch_detection_for_project_ids( namespace=issues_tasks, processing_deadline_duration=120, ) -def detect_web_vitals_issues_for_project(project_id: int) -> None: +def detect_web_vitals_issues_for_project( + project_id: int, organization_slug: str | None = None +) -> None: """ Process a single project for Web Vitals issue detection. """ if not options.get("issue-detection.web-vitals-detection.enabled"): + metrics.incr( + "web_vitals_issue_detection.projects.skipped", + amount=1, + tags={ + "reason": "disabled", + "project_id": project_id, + "organization": organization_slug, + }, + sample_rate=1.0, + ) return web_vital_issue_groups = get_highest_opportunity_page_vitals_for_project( @@ -138,6 +150,7 @@ def detect_web_vitals_issues_for_project(project_id: int) -> None: ) sent_counts: dict[WebVitalIssueDetectionGroupingType, int] = defaultdict(int) rejected_no_trace_count = 0 + rejected_already_exists_count = 0 for web_vital_issue_group in web_vital_issue_groups: scores = web_vital_issue_group["scores"] values = web_vital_issue_group["values"] @@ -158,6 +171,8 @@ def detect_web_vitals_issues_for_project(project_id: int) -> None: sent = send_web_vitals_issue_to_platform(web_vital_issue_group, trace_id=trace.trace_id) if sent: sent_counts[web_vital_issue_group["vital_grouping"]] += 1 + else: + rejected_already_exists_count += 1 else: rejected_no_trace_count += 1 @@ -165,14 +180,33 @@ def detect_web_vitals_issues_for_project(project_id: int) -> None: metrics.incr( "web_vitals_issue_detection.issues.sent", amount=count, - tags={"kind": vital_grouping}, # rendering, cls, or inp + tags={ + "kind": vital_grouping, + "project_id": project_id, + "organization": organization_slug, + }, # rendering, cls, or inp sample_rate=1.0, ) metrics.incr( "web_vitals_issue_detection.rejected", amount=rejected_no_trace_count, - tags={"reason": "no_trace"}, + tags={ + "reason": "no_trace", + "project_id": project_id, + "organization": organization_slug, + }, + sample_rate=1.0, + ) + + metrics.incr( + "web_vitals_issue_detection.rejected", + amount=rejected_already_exists_count, + tags={ + "reason": "already_exists", + "project_id": project_id, + "organization": organization_slug, + }, sample_rate=1.0, ) @@ -190,7 +224,7 @@ def get_highest_opportunity_page_vitals_for_project( The number of samples is set by SAMPLES_COUNT_THRESHOLD. """ try: - project = Project.objects.get(id=project_id) + project = Project.objects.select_related("organization").get(id=project_id) except Project.DoesNotExist: logger.exception( "Project does not exist; cannot fetch transactions", extra={"project_id": project_id} @@ -291,7 +325,11 @@ def get_highest_opportunity_page_vitals_for_project( metrics.incr( "web_vitals_issue_detection.rejected", amount=rejected_insufficient_samples_count, - tags={"reason": "insufficient_samples"}, + tags={ + "reason": "insufficient_samples", + "project_id": project.id, + "organization": project.organization.slug, + }, sample_rate=1.0, ) diff --git a/src/sentry/web_vitals/issue_platform_adapter.py b/src/sentry/web_vitals/issue_platform_adapter.py index a82ad5fdb8456c..bd6bc7e5082648 100644 --- a/src/sentry/web_vitals/issue_platform_adapter.py +++ b/src/sentry/web_vitals/issue_platform_adapter.py @@ -2,6 +2,8 @@ from datetime import UTC, datetime from uuid import uuid4 +import sentry_sdk + from sentry.issues.grouptype import WebVitalsGroup from sentry.issues.ingest import hash_fingerprint from sentry.issues.issue_occurrence import IssueEvidence, IssueOccurrence @@ -16,7 +18,12 @@ def create_fingerprint(vital_grouping: WebVitalIssueDetectionGroupingType, trans return fingerprint +@sentry_sdk.tracing.trace def send_web_vitals_issue_to_platform(data: WebVitalIssueGroupData, trace_id: str) -> bool: + project = data["project"] + sentry_sdk.set_tag("project_id", project.id) + sentry_sdk.set_tag("organization_id", project.organization_id) + # Do not create a new web vital issue if an open issue already exists if check_unresolved_web_vitals_issue_exists(data): return False