11from __future__ import annotations
22
33import logging
4+ from collections import defaultdict
45from datetime import UTC , datetime , timedelta
56
67from sentry import features , options
1617from sentry .snuba .spans_rpc import Spans
1718from sentry .tasks .base import instrumented_task
1819from sentry .taskworker .namespaces import issues_tasks
20+ from sentry .utils import metrics
1921from sentry .web_vitals .issue_platform_adapter import send_web_vitals_issue_to_platform
2022from sentry .web_vitals .query import get_trace_by_web_vital_measurement
2123from sentry .web_vitals .types import (
@@ -67,8 +69,11 @@ def run_web_vitals_issue_detection() -> None:
6769
6870 # Spawn a sub-task for each project
6971 projects = Project .objects .filter (id__in = enabled_project_ids ).select_related ("organization" )
72+ projects_checked_count = 0
73+ projects_dispatched_count = 0
7074
7175 for project in projects :
76+ projects_checked_count += 1
7277 if not check_seer_setup_for_project (project ):
7378 continue
7479
@@ -78,6 +83,18 @@ def run_web_vitals_issue_detection() -> None:
7883 continue
7984
8085 detect_web_vitals_issues_for_project .delay (project .id )
86+ projects_dispatched_count += 1
87+
88+ metrics .incr (
89+ "web_vitals_issue_detection.projects.checked" ,
90+ amount = projects_checked_count ,
91+ sample_rate = 1.0 ,
92+ )
93+ metrics .incr (
94+ "web_vitals_issue_detection.projects.dispatched" ,
95+ amount = projects_dispatched_count ,
96+ sample_rate = 1.0 ,
97+ )
8198
8299
83100@instrumented_task (
@@ -95,6 +112,8 @@ def detect_web_vitals_issues_for_project(project_id: int) -> None:
95112 web_vital_issue_groups = get_highest_opportunity_page_vitals_for_project (
96113 project_id , limit = TRANSACTIONS_PER_PROJECT_LIMIT
97114 )
115+ sent_counts = defaultdict [WebVitalIssueDetectionGroupingType , int ](int )
116+ rejected_no_trace_count = 0
98117 for web_vital_issue_group in web_vital_issue_groups :
99118 scores = web_vital_issue_group ["scores" ]
100119 values = web_vital_issue_group ["values" ]
@@ -113,6 +132,24 @@ def detect_web_vitals_issues_for_project(project_id: int) -> None:
113132 )
114133 if trace :
115134 send_web_vitals_issue_to_platform (web_vital_issue_group , trace_id = trace .trace_id )
135+ sent_counts [web_vital_issue_group ["vital_grouping" ]] += 1
136+ else :
137+ rejected_no_trace_count += 1
138+
139+ for vital_grouping , count in sent_counts .items ():
140+ metrics .incr (
141+ "web_vitals_issue_detection.issues.sent" ,
142+ amount = count ,
143+ tags = {"kind" : vital_grouping }, # rendering, cls, or inp
144+ sample_rate = 1.0 ,
145+ )
146+
147+ metrics .incr (
148+ "web_vitals_issue_detection.rejected" ,
149+ amount = rejected_no_trace_count ,
150+ tags = {"reason" : "no_trace" },
151+ sample_rate = 1.0 ,
152+ )
116153
117154
118155def get_highest_opportunity_page_vitals_for_project (
@@ -189,6 +226,7 @@ def get_highest_opportunity_page_vitals_for_project(
189226 tuple [WebVitalIssueDetectionGroupingType , str ], WebVitalIssueGroupData
190227 ] = {}
191228 seen_names = set ()
229+ rejected_insufficient_samples_count = 0
192230 for row in result .get ("data" , []):
193231 name = row .get ("transaction" )
194232 if not name :
@@ -205,12 +243,10 @@ def get_highest_opportunity_page_vitals_for_project(
205243 samples_count = row .get (f"count_scores(measurements.score.{ vital } )" )
206244 score_under_threshold = score is not None and score < SCORE_THRESHOLD
207245 enough_samples = samples_count is not None and samples_count >= samples_count_threshold
208- if (
209- score is not None
210- and score_under_threshold
211- and enough_samples
212- and p75_value is not None
213- ):
246+ if not enough_samples :
247+ rejected_insufficient_samples_count += 1
248+ continue
249+ if score is not None and score_under_threshold and p75_value is not None :
214250 if (VITAL_GROUPING_MAP [vital ], name ) not in web_vital_issue_groups :
215251 web_vital_issue_groups [(VITAL_GROUPING_MAP [vital ], name )] = {
216252 "transaction" : name ,
@@ -227,6 +263,13 @@ def get_highest_opportunity_page_vitals_for_project(
227263 vital
228264 ] = p75_value
229265
266+ metrics .incr (
267+ "web_vitals_issue_detection.rejected" ,
268+ amount = rejected_insufficient_samples_count ,
269+ tags = {"reason" : "insufficient_samples" },
270+ sample_rate = 1.0 ,
271+ )
272+
230273 return list (web_vital_issue_groups .values ())
231274
232275
0 commit comments