Skip to content

Commit

Permalink
ref(releasehealth): Implement get_oldest_health_data_for_releases on …
Browse files Browse the repository at this point in the history
…metrics backend [INGEST-249] (#28943)

* implement get_oldest_health_data_for_releases in metrics backend
  • Loading branch information
RaduW authored Sep 30, 2021
1 parent 2cd05e2 commit d98825e
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 12 deletions.
3 changes: 1 addition & 2 deletions src/sentry/api/endpoints/organization_releases.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
from sentry.signals import release_created
from sentry.snuba.sessions import (
STATS_PERIODS,
get_oldest_health_data_for_releases,
get_project_releases_by_stability,
get_project_releases_count,
)
Expand Down Expand Up @@ -182,7 +181,7 @@ def debounce_update_release_health_data(organization, project_ids):
to_upsert.append(key)

if to_upsert:
dates = get_oldest_health_data_for_releases(to_upsert)
dates = release_health.get_oldest_health_data_for_releases(to_upsert)

for project_id, version in to_upsert:
project = projects.get(project_id)
Expand Down
9 changes: 3 additions & 6 deletions src/sentry/api/endpoints/project_release_stats.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
from rest_framework.response import Response

from sentry import release_health
from sentry.api.bases.project import ProjectEndpoint, ProjectEventsError, ProjectReleasePermission
from sentry.api.exceptions import ResourceDoesNotExist
from sentry.api.serializers import serialize
from sentry.models import Release, ReleaseProject
from sentry.snuba.sessions import (
get_crash_free_breakdown,
get_oldest_health_data_for_releases,
get_project_release_stats,
)
from sentry.snuba.sessions import get_crash_free_breakdown, get_project_release_stats
from sentry.utils.dates import get_rollup_from_request


Expand All @@ -17,7 +14,7 @@ def upsert_missing_release(project, version):
try:
return ReleaseProject.objects.get(project=project, release__version=version).release
except ReleaseProject.DoesNotExist:
rows = get_oldest_health_data_for_releases([(project.id, version)])
rows = release_health.get_oldest_health_data_for_releases([(project.id, version)])
if rows:
oldest = next(rows.values())
release = Release.get_or_create(project=project, version=version, date_added=oldest)
Expand Down
9 changes: 9 additions & 0 deletions src/sentry/release_health/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class ReleaseHealthBackend(Service): # type: ignore
"get_release_sessions_time_bounds",
"check_releases_have_health_data",
"get_changed_project_release_model_adoptions",
"get_oldest_health_data_for_releases",
)

def get_current_and_previous_crash_free_rates(
Expand Down Expand Up @@ -186,3 +187,11 @@ def get_changed_project_release_model_adoptions(
releases seen in the last 72 hours for the requested projects.
"""
raise NotImplementedError()

def get_oldest_health_data_for_releases(
self, project_releases: Sequence[ProjectRelease]
) -> Mapping[ProjectRelease, str]:
"""Returns the oldest health data we have observed in a release
in 90 days. This is used for backfilling.
"""
raise NotImplementedError()
61 changes: 61 additions & 0 deletions src/sentry/release_health/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -652,3 +652,64 @@ def extract_row_info(row: Mapping[str, Union[OrganizationId, str]]) -> ProjectRe
return row.get("project_id"), reverse_tag_value(org_id, row.get(release_column_name)) # type: ignore

return [extract_row_info(row) for row in result["data"]]

def get_oldest_health_data_for_releases(
self,
project_releases: Sequence[ProjectRelease],
) -> Mapping[ProjectRelease, str]:

now = datetime.now(pytz.utc)
start = now - timedelta(days=90)

project_ids: List[ProjectId] = [x[0] for x in project_releases]
org_id = self._get_org_id(project_ids)
release_column_name = tag_key(org_id, "release")
releases = [x[1] for x in project_releases]
releases_ids = [
release_id
for release_id in [try_get_tag_value(org_id, release) for release in releases]
if release_id is not None
]

query_cols = [
Column("project_id"),
Column(release_column_name),
Function("min", [Column("bucketed_time")], "oldest"),
]

group_by = [
Column("project_id"),
Column(release_column_name),
]

where_clause = [
Condition(Column("org_id"), Op.EQ, org_id),
Condition(Column("project_id"), Op.IN, project_ids),
Condition(Column("metric_id"), Op.EQ, metric_id(org_id, "session")),
Condition(Column("timestamp"), Op.GTE, start),
Condition(Column("timestamp"), Op.LT, now),
Condition(Column(release_column_name), Op.IN, releases_ids),
]

query = Query(
dataset=Dataset.Metrics.value,
match=Entity("metrics_counters"),
select=query_cols,
where=where_clause,
groupby=group_by,
granularity=Granularity(3600),
)
rows = raw_snql_query(
query,
referrer="release_health.metrics.get_oldest_health_data_for_releases",
use_cache=False,
)["data"]

result = {}

for row in rows:
result[row["project_id"], reverse_tag_value(org_id, row[release_column_name])] = row[
"oldest"
]

return result
9 changes: 8 additions & 1 deletion src/sentry/release_health/sessions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from datetime import datetime
from typing import Optional, Sequence, Set, Tuple
from typing import Mapping, Optional, Sequence, Set, Tuple

from sentry.release_health.base import (
CurrentAndPreviousCrashFreeRates,
Expand All @@ -17,6 +17,7 @@
_check_has_health_data,
_check_releases_have_health_data,
_get_changed_project_release_model_adoptions,
_get_oldest_health_data_for_releases,
_get_release_adoption,
_get_release_sessions_time_bounds,
get_current_and_previous_crash_free_rates,
Expand Down Expand Up @@ -93,3 +94,9 @@ def get_changed_project_release_model_adoptions(
project_ids: Sequence[ProjectId],
) -> Sequence[ProjectRelease]:
return _get_changed_project_release_model_adoptions(project_ids) # type: ignore

def get_oldest_health_data_for_releases(
self,
project_releases: Sequence[ProjectRelease],
) -> Mapping[ProjectRelease, str]:
return _get_oldest_health_data_for_releases(project_releases) # type: ignore
2 changes: 1 addition & 1 deletion src/sentry/snuba/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def _get_changed_project_release_model_adoptions(project_ids):
return rv


def get_oldest_health_data_for_releases(project_releases):
def _get_oldest_health_data_for_releases(project_releases):
"""Returns the oldest health data we have observed in a release
in 90 days. This is used for backfilling.
"""
Expand Down
5 changes: 3 additions & 2 deletions tests/snuba/sessions/test_sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from sentry.release_health.sessions import SessionsReleaseHealthBackend
from sentry.snuba.sessions import (
_make_stats,
get_oldest_health_data_for_releases,
get_project_releases_by_stability,
get_project_releases_count,
get_release_health_data_overview,
Expand Down Expand Up @@ -135,7 +134,9 @@ def setUp(self):
)

def test_get_oldest_health_data_for_releases(self):
data = get_oldest_health_data_for_releases([(self.project.id, self.session_release)])
data = self.backend.get_oldest_health_data_for_releases(
[(self.project.id, self.session_release)]
)
assert data == {
(self.project.id, self.session_release): format_timestamp(
self.session_started // 3600 * 3600
Expand Down

0 comments on commit d98825e

Please sign in to comment.