Skip to content

Commit 9b74711

Browse files
committed
fix(spans-migration): make script to migrate the AM1 metrics queries to transactions
1 parent a6af143 commit 9b74711

2 files changed

Lines changed: 400 additions & 0 deletions

File tree

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import logging
2+
3+
import sentry_sdk
4+
from django.db import router
5+
6+
from sentry import features
7+
from sentry.incidents.utils.types import DATA_SOURCE_SNUBA_QUERY_SUBSCRIPTION
8+
from sentry.snuba.dataset import Dataset
9+
from sentry.snuba.models import (
10+
QuerySubscription,
11+
SnubaQuery,
12+
SnubaQueryEventType,
13+
)
14+
from sentry.snuba.subscriptions import bulk_update_snuba_subscriptions
15+
from sentry.utils.db import atomic_transaction
16+
from sentry.workflow_engine.models.data_source import DataSource
17+
18+
logger = logging.getLogger(__name__)
19+
20+
21+
def snapshot_snuba_query(snuba_query: SnubaQuery):
22+
if not snuba_query.query_snapshot and snuba_query.dataset in [
23+
Dataset.PerformanceMetrics.value,
24+
]:
25+
query_snapshot = {
26+
"metrics_to_transactions": True,
27+
"dataset": snuba_query.dataset,
28+
"query": snuba_query.query,
29+
"aggregate": snuba_query.aggregate,
30+
}
31+
snuba_query.query_snapshot = query_snapshot
32+
snuba_query.save()
33+
34+
return snuba_query
35+
36+
37+
def _get_old_query_info(snuba_query: SnubaQuery):
38+
old_query_type = SnubaQuery.Type(snuba_query.type)
39+
old_dataset = Dataset(snuba_query.dataset)
40+
old_query = snuba_query.query
41+
old_aggregate = snuba_query.aggregate
42+
43+
return old_query_type, old_dataset, old_query, old_aggregate
44+
45+
46+
def translate_am1_metrics_detector_and_update_subscription_in_snuba(snuba_query: SnubaQuery):
47+
query_subscription_qs = QuerySubscription.objects.filter(
48+
snuba_query_id=snuba_query.id,
49+
status__in=[QuerySubscription.Status.ACTIVE.value, QuerySubscription.Status.UPDATING.value],
50+
)
51+
query_subscription = query_subscription_qs.first()
52+
53+
if not query_subscription:
54+
logger.info("No active query subscription found for snuba query %s", snuba_query.id)
55+
return
56+
57+
try:
58+
data_source: DataSource = DataSource.objects.get(
59+
source_id=str(query_subscription.id), type=DATA_SOURCE_SNUBA_QUERY_SUBSCRIPTION
60+
)
61+
except DataSource.DoesNotExist as e:
62+
logger.info("Data source not found for snuba query %s", snuba_query.id)
63+
sentry_sdk.capture_exception(e)
64+
return
65+
if not features.has(
66+
"organizations:migrate-am1-metrics-alerts-to-transactions", data_source.organization
67+
):
68+
logger.info("Feature flag not enabled")
69+
return
70+
71+
snapshot_snuba_query(snuba_query)
72+
73+
snapshot = snuba_query.query_snapshot
74+
if not snapshot:
75+
logger.info("No snapshot created for snuba query %s", snuba_query.id)
76+
return
77+
78+
old_query_type, old_dataset, old_query, old_aggregate = _get_old_query_info(snuba_query)
79+
80+
snuba_query.dataset = Dataset.Transactions.value
81+
82+
with atomic_transaction(
83+
using=(
84+
router.db_for_write(SnubaQuery),
85+
router.db_for_write(SnubaQueryEventType),
86+
router.db_for_write(QuerySubscription),
87+
)
88+
):
89+
snuba_query.save()
90+
91+
query_subscriptions = list(snuba_query.subscriptions.all())
92+
try:
93+
bulk_update_snuba_subscriptions(
94+
query_subscriptions, old_query_type, old_dataset, old_aggregate, old_query
95+
)
96+
except Exception as e:
97+
logger.info(
98+
"Query not migrated: error updating subscriptions in snuba",
99+
extra={"snuba_query_id": snuba_query.id, "error": e},
100+
)
101+
raise
102+
103+
logger.info(
104+
"Query successfully migrated to transactions", extra={"snuba_query_id": snuba_query.id}
105+
)
106+
return
107+
108+
109+
def rollback_am1_metrics_detector_query_and_update_subscription_in_snuba(snuba_query: SnubaQuery):
110+
# querying for updating as well just in case the subscription gets stuck in updating
111+
query_subscription_qs = QuerySubscription.objects.filter(
112+
snuba_query_id=snuba_query.id,
113+
status__in=[QuerySubscription.Status.ACTIVE.value, QuerySubscription.Status.UPDATING.value],
114+
)
115+
query_subscription = query_subscription_qs.first()
116+
117+
if not query_subscription:
118+
logger.info("No active query subscription found for snuba query %s", snuba_query.id)
119+
return
120+
121+
try:
122+
data_source: DataSource = DataSource.objects.get(
123+
source_id=str(query_subscription.id), type=DATA_SOURCE_SNUBA_QUERY_SUBSCRIPTION
124+
)
125+
except DataSource.DoesNotExist as e:
126+
logger.info("Data source not found for snuba query %s", snuba_query.id)
127+
sentry_sdk.capture_exception(e)
128+
return
129+
130+
if not features.has(
131+
"organizations:migrate-am1-metrics-alerts-to-transactions", data_source.organization
132+
):
133+
logger.info("Feature flag not enabled")
134+
return
135+
136+
snapshot = snuba_query.query_snapshot
137+
138+
if not snapshot:
139+
logger.info("No snapshot found for snuba query %s", snuba_query.id)
140+
return
141+
142+
old_query_type, old_dataset, old_query, old_aggregate = _get_old_query_info(snuba_query)
143+
144+
with atomic_transaction(
145+
using=(
146+
router.db_for_write(SnubaQuery),
147+
router.db_for_write(SnubaQueryEventType),
148+
router.db_for_write(QuerySubscription),
149+
)
150+
):
151+
snuba_query.update(
152+
dataset=snapshot["dataset"],
153+
query=snapshot["query"],
154+
aggregate=snapshot["aggregate"],
155+
)
156+
157+
query_subscriptions = list(snuba_query.subscriptions.all())
158+
try:
159+
bulk_update_snuba_subscriptions(
160+
query_subscriptions, old_query_type, old_dataset, old_aggregate, old_query
161+
)
162+
except Exception as e:
163+
logger.info(
164+
"Query not rolled back: error updating subscriptions in snuba",
165+
extra={"snuba_query_id": snuba_query.id, "error": e},
166+
)
167+
raise
168+
169+
logger.info(
170+
"Query successfully rolled back to legacy", extra={"snuba_query_id": snuba_query.id}
171+
)
172+
return

0 commit comments

Comments
 (0)