Skip to content

Commit 621ea23

Browse files
authored
feat(dynamic-sampling):Add raw_query and user relation to custom_rules model (second try) (#58447)
1 parent d73a8f4 commit 621ea23

File tree

12 files changed

+70
-19
lines changed

12 files changed

+70
-19
lines changed

fixtures/backup/model_dependencies/detailed.json

+5
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,11 @@
11031103
"sentry.customdynamicsamplingrule": {
11041104
"dangling": false,
11051105
"foreign_keys": {
1106+
"created_by_id": {
1107+
"kind": "HybridCloudForeignKey",
1108+
"model": "sentry.user",
1109+
"nullable": true
1110+
},
11061111
"organization": {
11071112
"kind": "FlexibleForeignKey",
11081113
"model": "sentry.organization",

fixtures/backup/model_dependencies/flat.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@
150150
"sentry.project"
151151
],
152152
"sentry.customdynamicsamplingrule": [
153-
"sentry.organization"
153+
"sentry.organization",
154+
"sentry.user"
154155
],
155156
"sentry.customdynamicsamplingruleproject": [
156157
"sentry.customdynamicsamplingrule",

migrations_lockfile.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ feedback: 0003_feedback_add_env
99
hybridcloud: 0005_add_missing_org_integration_scope
1010
nodestore: 0002_nodestore_no_dictfield
1111
replays: 0003_add_size_to_recording_segment
12-
sentry: 0577_drop_latest_incident_index
12+
sentry: 0578_add_query_and_users_to_custom_dynamic_sampling_rules
1313
social_auth: 0002_default_auto_field

src/sentry/api/endpoints/custom_rules.py

+1
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ def post(self, request: Request, organization: Organization) -> Response:
158158
organization_id=organization.id,
159159
num_samples=NUM_SAMPLES_PER_CUSTOM_RULE,
160160
sample_rate=1.0,
161+
query=query,
161162
)
162163

163164
# schedule update for affected project configs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Generated by Django 3.2.20 on 2023-10-20 07:59
2+
3+
from django.db import migrations, models
4+
5+
import sentry.db.models.fields.hybrid_cloud_foreign_key
6+
from sentry.new_migrations.migrations import CheckedMigration
7+
8+
9+
class Migration(CheckedMigration):
10+
# This flag is used to mark that a migration shouldn't be automatically run in production. For
11+
# the most part, this should only be used for operations where it's safe to run the migration
12+
# after your code has deployed. So this should not be used for most operations that alter the
13+
# schema of a table.
14+
# Here are some things that make sense to mark as dangerous:
15+
# - Large data migrations. Typically we want these to be run manually by ops so that they can
16+
# be monitored and not block the deploy for a long period of time while they run.
17+
# - Adding indexes to large tables. Since this can take a long time, we'd generally prefer to
18+
# have ops run this and not block the deploy. Note that while adding an index is a schema
19+
# change, it's completely safe to run the operation after the code has deployed.
20+
is_dangerous = False
21+
22+
dependencies = [
23+
("sentry", "0577_drop_latest_incident_index"),
24+
]
25+
26+
operations = [
27+
migrations.AddField(
28+
model_name="customdynamicsamplingrule",
29+
name="created_by_id",
30+
field=sentry.db.models.fields.hybrid_cloud_foreign_key.HybridCloudForeignKey(
31+
"sentry.User", blank=True, db_index=True, null=True, on_delete="CASCADE"
32+
),
33+
),
34+
migrations.AddField(
35+
model_name="customdynamicsamplingrule",
36+
name="query",
37+
field=models.TextField(null=True),
38+
),
39+
]

src/sentry/models/dynamicsampling.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88

99
from sentry.backup.scopes import RelocationScope
1010
from sentry.db.models import FlexibleForeignKey, Model, region_silo_only_model
11+
from sentry.db.models.fields.hybrid_cloud_foreign_key import HybridCloudForeignKey
1112
from sentry.utils import json
1213

1314
if TYPE_CHECKING:
1415
from sentry.models.project import Project
1516

16-
1717
# max number of custom rules that can be created per organization
1818
MAX_CUSTOM_RULES = 2000
1919
CUSTOM_RULE_START = 3000
@@ -104,6 +104,9 @@ class CustomDynamicSamplingRule(Model):
104104
end_date = models.DateTimeField()
105105
num_samples = models.IntegerField()
106106
condition_hash = models.CharField(max_length=40)
107+
# the raw query field from the request
108+
query = models.TextField(null=True)
109+
created_by_id = HybridCloudForeignKey("sentry.User", on_delete="CASCADE", null=True, blank=True)
107110

108111
@property
109112
def external_rule_id(self) -> int:
@@ -160,6 +163,7 @@ def update_or_create(
160163
organization_id: int,
161164
num_samples: int,
162165
sample_rate: float,
166+
query: str,
163167
) -> "CustomDynamicSamplingRule":
164168

165169
from sentry.models.project import Project
@@ -195,6 +199,7 @@ def update_or_create(
195199
condition_hash=rule_hash,
196200
is_active=True,
197201
is_org_level=is_org_level,
202+
query=query,
198203
)
199204

200205
rule.save()

src/sentry/testutils/helpers/backups.py

+1
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ def create_exhaustive_organization(
408408
organization_id=org.id,
409409
num_samples=100,
410410
sample_rate=0.5,
411+
query="environment:prod event.type:transaction",
411412
)
412413

413414
# Environment*

tests/sentry/api/endpoints/test_custom_rules.py

+2-16
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ def setUp(self):
5555
organization_id=self.organization.id,
5656
num_samples=100,
5757
sample_rate=1.0,
58+
query="event.type:transaction, environment:prod",
5859
)
5960

6061
# create an org rule
@@ -76,24 +77,9 @@ def setUp(self):
7677
organization_id=self.organization.id,
7778
num_samples=100,
7879
sample_rate=1.0,
80+
query="event.type:transaction, environment:dev",
7981
)
8082

81-
# # create a condition with empty query
82-
# now = timezone.now()
83-
# self.empty_condition = {"op": "and", "inner": []}
84-
# start = now - timedelta(hours=2)
85-
# end = now + timedelta(hours=2)
86-
#
87-
# CustomDynamicSamplingRule.update_or_create(
88-
# condition=self.empty_condition,
89-
# start=start,
90-
# end=end,
91-
# project_ids=[self.known_projects[0].id],
92-
# organization_id=self.organization.id,
93-
# num_samples=100,
94-
# sample_rate=1.0,
95-
# )
96-
9783
def test_finds_project_rule(self):
9884
"""
9985
Tests that the endpoint finds the rule when the query matches and

tests/sentry/backup/snapshots/ReleaseTests/test_at_head.pysnap

+2
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,8 @@ source: tests/sentry/backup/test_releases.py
672672
is_org_level: false
673673
num_samples: 100
674674
organization: 4552811202150400
675+
created_by_id: null
676+
query: environment:prod event.type:transaction
675677
rule_id: 1
676678
sample_rate: 0.5
677679
start_date: '2023-10-17T01:50:40.016Z'

tests/sentry/backup/test_models.py

+1
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ def test_custom_dynamic_sampling(self):
247247
organization_id=self.organization.id,
248248
num_samples=100,
249249
sample_rate=0.5,
250+
query="environment:prod",
250251
)
251252
return self.import_export_then_validate()
252253

tests/sentry/dynamic_sampling/test_generate_rules.py

+2
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,7 @@ def test_generate_rules_return_custom_rules(get_blended_sample_rate, default_old
738738
organization_id=default_old_project.organization.id,
739739
num_samples=100,
740740
sample_rate=0.5,
741+
query="environment:prod1",
741742
)
742743
# and an organization rule
743744
condition = {"op": "eq", "name": "environment", "value": "prod2"}
@@ -749,6 +750,7 @@ def test_generate_rules_return_custom_rules(get_blended_sample_rate, default_old
749750
organization_id=default_old_project.organization.id,
750751
num_samples=100,
751752
sample_rate=0.5,
753+
query="environment:prod2",
752754
)
753755

754756
rules = generate_rules(default_old_project)

tests/sentry/models/test_dynamicsampling.py

+8
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def test_update_or_create(self):
3131
organization_id=self.organization.id,
3232
num_samples=100,
3333
sample_rate=0.5,
34+
query="environment:prod",
3435
)
3536

3637
end2 = timezone.now() + timedelta(hours=1)
@@ -42,6 +43,7 @@ def test_update_or_create(self):
4243
organization_id=self.organization.id,
4344
num_samples=100,
4445
sample_rate=0.5,
46+
query="environment:prod",
4547
)
4648

4749
assert rule.id == updated_rule.id
@@ -64,6 +66,7 @@ def create_rule_for_env(env_idx: int):
6466
organization_id=self.organization.id,
6567
num_samples=100,
6668
sample_rate=0.5,
69+
query=f"environment:prod{env_idx}",
6770
)
6871

6972
rule_ids = set()
@@ -116,6 +119,7 @@ def create_rule(is_old: bool, idx: int):
116119
organization_id=self.organization.id,
117120
num_samples=100,
118121
sample_rate=0.5,
122+
query=f"environment:prod{idx}",
119123
)
120124

121125
for i in range(10):
@@ -160,6 +164,7 @@ def test_get_rule_for_org(self):
160164
organization_id=self.organization.id,
161165
num_samples=100,
162166
sample_rate=0.5,
167+
query="environment:prod",
163168
)
164169

165170
rule = CustomDynamicSamplingRule.get_rule_for_org(
@@ -204,6 +209,7 @@ def create_rule(
204209
organization_id=org_id,
205210
num_samples=100,
206211
sample_rate=0.5,
212+
query=f"environment:prod{idx[0]}",
207213
)
208214

209215
valid_project_rule = create_rule([self.project.id, self.second_project.id])
@@ -243,6 +249,7 @@ def test_separate_projects_create_different_rules(self):
243249
organization_id=self.organization.id,
244250
num_samples=100,
245251
sample_rate=0.5,
252+
query="environment:prod",
246253
)
247254

248255
end2 = timezone.now() + timedelta(hours=1)
@@ -254,6 +261,7 @@ def test_separate_projects_create_different_rules(self):
254261
organization_id=self.organization.id,
255262
num_samples=100,
256263
sample_rate=0.5,
264+
query="environment:prod",
257265
)
258266

259267
assert rule.id != second_rule.id

0 commit comments

Comments
 (0)