Skip to content

Commit 2d9c6e2

Browse files
committed
🧪 scaffold experiment detector
1 parent 925f407 commit 2d9c6e2

File tree

9 files changed

+498
-19
lines changed

9 files changed

+498
-19
lines changed

src/sentry/issues/grouptype.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,16 @@ class PerformanceNPlusOneAPICallsGroupType(GroupType):
339339
released = True
340340

341341

342+
@dataclass(frozen=True)
343+
class PerformanceNPlusOneAPICallsExperimentalGroupType(GroupType):
344+
type_id = 1910
345+
slug = "performance_n_plus_one_api_calls_experimental"
346+
description = "N+1 API Call (Experimental)"
347+
category = GroupCategory.PERFORMANCE.value
348+
default_priority = PriorityLevel.LOW
349+
released = False
350+
351+
342352
@dataclass(frozen=True)
343353
class PerformanceMNPlusOneDBQueriesGroupType(PerformanceGroupTypeDefaults, GroupType):
344354
type_id = 1011

src/sentry/notifications/utils/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from sentry.integrations.services.integration import integration_service
2222
from sentry.issues.grouptype import (
2323
PerformanceConsecutiveDBQueriesGroupType,
24+
PerformanceNPlusOneAPICallsExperimentalGroupType,
2425
PerformanceNPlusOneAPICallsGroupType,
2526
PerformanceRenderBlockingAssetSpanGroupType,
2627
)
@@ -336,7 +337,7 @@ def occurrence_perf_to_email_html(context: Any) -> str:
336337

337338

338339
def get_spans(
339-
entries: list[dict[str, list[dict[str, str | float]] | str]]
340+
entries: list[dict[str, list[dict[str, str | float]] | str]],
340341
) -> list[dict[str, str | float]] | None:
341342
"""Get the given event's spans"""
342343
if not len(entries):
@@ -496,7 +497,10 @@ def from_problem_and_spans(
496497
spans: list[dict[str, str | float]] | None,
497498
event: Event | None = None,
498499
) -> PerformanceProblemContext:
499-
if problem.type == PerformanceNPlusOneAPICallsGroupType:
500+
if problem.type in (
501+
PerformanceNPlusOneAPICallsGroupType,
502+
PerformanceNPlusOneAPICallsExperimentalGroupType,
503+
):
500504
return NPlusOneAPICallProblemContext(problem, spans, event)
501505
if problem.type == PerformanceConsecutiveDBQueriesGroupType:
502506
return ConsecutiveDBQueriesProblemContext(problem, spans, event)

src/sentry/utils/performance_issues/detectors/experiments/__init__.py

Whitespace-only changes.

src/sentry/utils/performance_issues/detectors/dummy_n_plus_one_api_calls_detector.py renamed to src/sentry/utils/performance_issues/detectors/experiments/n_plus_one_api_calls_detector.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,11 @@
88
from typing import Any
99
from urllib.parse import urlparse
1010

11-
from sentry.issues.grouptype import PerformanceNPlusOneAPICallsGroupType
11+
from sentry.issues.grouptype import PerformanceNPlusOneAPICallsExperimentalGroupType
1212
from sentry.issues.issue_occurrence import IssueEvidence
1313
from sentry.models.organization import Organization
1414
from sentry.models.project import Project
15-
from sentry.utils.performance_issues.detectors.utils import get_total_span_duration
16-
from sentry.utils.performance_issues.performance_problem import PerformanceProblem
17-
18-
from ..base import (
15+
from sentry.utils.performance_issues.base import (
1916
DetectorType,
2017
PerformanceDetector,
2118
fingerprint_http_spans,
@@ -25,12 +22,14 @@
2522
parameterize_url,
2623
parameterize_url_with_result,
2724
)
28-
from ..types import PerformanceProblemsMap, Span
25+
from sentry.utils.performance_issues.detectors.utils import get_total_span_duration
26+
from sentry.utils.performance_issues.performance_problem import PerformanceProblem
27+
from sentry.utils.performance_issues.types import PerformanceProblemsMap, Span
2928

3029
logger = logging.getLogger(__name__)
3130

3231

33-
class DummyNPlusOneAPICallsDetector(PerformanceDetector):
32+
class NPlusOneAPICallsExperimentalDetector(PerformanceDetector):
3433
"""
3534
Detect parallel network calls to the same endpoint.
3635
@@ -54,7 +53,7 @@ def __init__(self, settings: dict[DetectorType, Any], event: dict[str, Any]) ->
5453
self.spans: list[Span] = []
5554

5655
def visit_span(self, span: Span) -> None:
57-
if not DummyNPlusOneAPICallsDetector.is_span_eligible(span):
56+
if not NPlusOneAPICallsExperimentalDetector.is_span_eligible(span):
5857
return
5958

6059
op = span.get("op", None)
@@ -171,7 +170,7 @@ def _maybe_store_problem(self) -> None:
171170
fingerprint=fingerprint,
172171
op=last_span["op"],
173172
desc=problem_description,
174-
type=PerformanceNPlusOneAPICallsGroupType,
173+
type=PerformanceNPlusOneAPICallsExperimentalGroupType,
175174
cause_span_ids=[],
176175
parent_span_ids=[last_span.get("parent_span_id", None)],
177176
offender_span_ids=offender_span_ids,
@@ -243,7 +242,7 @@ def _fingerprint(self) -> str | None:
243242

244243
fingerprint = fingerprint_http_spans([self.spans[0]])
245244

246-
return f"1-{PerformanceNPlusOneAPICallsGroupType.type_id}-{fingerprint}"
245+
return f"1-{PerformanceNPlusOneAPICallsExperimentalGroupType.type_id}-{fingerprint}"
247246

248247
def _spans_are_concurrent(self, span_a: Span, span_b: Span) -> bool:
249248
span_a_start: int = span_a.get("start_timestamp", 0) or 0

src/sentry/utils/performance_issues/detectors/n_plus_one_api_calls_detector.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@
1414
from sentry.issues.issue_occurrence import IssueEvidence
1515
from sentry.models.organization import Organization
1616
from sentry.models.project import Project
17-
from sentry.utils.performance_issues.detectors.utils import get_total_span_duration
18-
19-
from ..base import (
17+
from sentry.utils.performance_issues.base import (
2018
DetectorType,
2119
PerformanceDetector,
2220
fingerprint_http_spans,
@@ -25,8 +23,9 @@
2523
get_url_from_span,
2624
parameterize_url,
2725
)
28-
from ..performance_problem import PerformanceProblem
29-
from ..types import PerformanceProblemsMap, Span
26+
from sentry.utils.performance_issues.detectors.utils import get_total_span_duration
27+
from sentry.utils.performance_issues.performance_problem import PerformanceProblem
28+
from sentry.utils.performance_issues.types import PerformanceProblemsMap, Span
3029

3130

3231
class NPlusOneAPICallsDetector(PerformanceDetector):

src/sentry/utils/performance_issues/performance_detection.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
from .base import DetectorType, PerformanceDetector
2323
from .detectors.consecutive_db_detector import ConsecutiveDBSpanDetector
2424
from .detectors.consecutive_http_detector import ConsecutiveHTTPSpanDetector
25-
from .detectors.dummy_n_plus_one_api_calls_detector import DummyNPlusOneAPICallsDetector
25+
from .detectors.experiments.n_plus_one_api_calls_detector import (
26+
NPlusOneAPICallsExperimentalDetector,
27+
)
2628
from .detectors.http_overhead_detector import HTTPOverheadDetector
2729
from .detectors.io_main_thread_detector import DBMainThreadDetector, FileIOMainThreadDetector
2830
from .detectors.large_payload_detector import LargeHTTPPayloadDetector
@@ -323,7 +325,7 @@ def get_detection_settings(project_id: int | None = None) -> dict[DetectorType,
323325
NPlusOneDBSpanDetectorExtended,
324326
FileIOMainThreadDetector,
325327
NPlusOneAPICallsDetector,
326-
DummyNPlusOneAPICallsDetector,
328+
NPlusOneAPICallsExperimentalDetector,
327329
MNPlusOneDBSpanDetector,
328330
UncompressedAssetSpanDetector,
329331
LargeHTTPPayloadDetector,

tests/sentry/utils/performance_issues/__init__.py

Whitespace-only changes.

tests/sentry/utils/performance_issues/experiments/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)