Skip to content

Commit

Permalink
feat(statistical-detectors): Temporarily forward regressions from fun… (
Browse files Browse the repository at this point in the history
#57157)

…ction trends

We're still ironing out the detection pipeline but in order to produce
an occurrence for the regression issue, start creating them from the
results of the function trends endpoint.
  • Loading branch information
Zylphrex authored Sep 29, 2023
1 parent 1c12561 commit 8a7b2b8
Showing 1 changed file with 64 additions and 5 deletions.
69 changes: 64 additions & 5 deletions src/sentry/api/endpoints/organization_profiling_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

from datetime import timedelta
from enum import Enum
from typing import Any
from typing import Any, List

import sentry_sdk
from rest_framework import serializers
from rest_framework.request import Request
from rest_framework.response import Response
Expand All @@ -14,9 +15,11 @@
from sentry.api.bases import NoProjects, OrganizationEventsV2EndpointBase
from sentry.api.paginator import GenericOffsetPaginator
from sentry.exceptions import InvalidSearchQuery
from sentry.models.organization import Organization
from sentry.profiles.utils import get_from_profiling_service
from sentry.search.events.builder import ProfileTopFunctionsTimeseriesQueryBuilder
from sentry.search.events.types import QueryBuilderConfig
from sentry.seer.utils import detect_breakpoints
from sentry.seer.utils import BreakpointData, detect_breakpoints
from sentry.snuba import functions
from sentry.snuba.dataset import Dataset
from sentry.snuba.referrer import Referrer
Expand Down Expand Up @@ -68,12 +71,12 @@ class OrganizationProfilingFunctionTrendsEndpoint(OrganizationEventsV2EndpointBa
"GET": ApiPublishStatus.UNKNOWN,
}

def has_feature(self, organization, request):
def has_feature(self, organization: Organization, request: Request):
return features.has(
"organizations:profiling-global-suspect-functions", organization, actor=request.user
)

def get(self, request: Request, organization) -> Response:
def get(self, request: Request, organization: Organization) -> Response:
if not self.has_feature(organization, request):
return Response(status=404)

Expand Down Expand Up @@ -154,7 +157,7 @@ def get_event_stats(_columns, query, params, _rollup, zerofill_results, _compari

return results

def get_trends_data(stats_data):
def get_trends_data(stats_data) -> List[BreakpointData]:
if not stats_data:
return []

Expand Down Expand Up @@ -220,6 +223,17 @@ def get_trends_data(stats_data):
reverse=data["trend"] is TrendType.REGRESSION,
)

if data["trend"] is TrendType.REGRESSION:
try:
if features.has(
"organizations:profile-function-regression-exp-ingest",
organization,
actor=request.user,
):
forward_regression_occurrences(organization, trending_functions, stats_data)
except Exception as e:
sentry_sdk.capture_exception(e)

def paginate_trending_events(offset, limit):
return {"data": trending_functions[offset : limit + offset]}

Expand Down Expand Up @@ -308,3 +322,48 @@ def get_interval_from_range(date_range: timedelta) -> str:
return "2h"

return "1h"


def forward_regression_occurrences(
organization: Organization,
regressions: List[BreakpointData],
stats_data: Any,
):
payloads = []

for entry in regressions:
project_id = int(entry["project"])
fingerprint = int(entry["transaction"])

profile_id = None
examples = (
stats_data.get(f"{project_id},{fingerprint}", {}).get("worst()", {}).get("data", [])
)
for row in reversed(examples):
example = row[1][0]["count"]
if isinstance(example, str):
profile_id = example
break

if profile_id is None:
continue

payloads.append(
{
"organization_id": organization.id,
"project_id": project_id,
"profile_id": profile_id,
"fingerprint": fingerprint,
"absolute_percentage_change": entry["absolute_percentage_change"],
"aggregate_range_1": entry["aggregate_range_1"],
"aggregate_range_2": entry["aggregate_range_2"],
"breakpoint": int(entry["breakpoint"]),
"trend_difference": entry["trend_difference"],
"trend_percentage": entry["trend_percentage"],
"unweighted_p_value": entry["unweighted_p_value"],
"unweighted_t_value": entry["unweighted_t_value"],
}
)

get_from_profiling_service(method="POST", path="/regressed", json_data=payloads)
assert 0

0 comments on commit 8a7b2b8

Please sign in to comment.