Skip to content

Commit 58e5445

Browse files
authored
Merge branch 'master' into mifu67/member-merge/sentry-app-leaky-bucket
2 parents c0687bb + 24d0105 commit 58e5445

File tree

290 files changed

+4660
-2128
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

290 files changed

+4660
-2128
lines changed

.github/CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,8 @@ tests/sentry/api/endpoints/test_organization_dashboard_widget_details.py @ge
523523
/static/app/views/settings/dynamicSampling/ @getsentry/telemetry-experience
524524
/static/app/views/onboarding* @getsentry/telemetry-experience
525525
/static/app/views/projectInstall/ @getsentry/telemetry-experience
526+
/static/app/views/insights/agentMonitoring/ @getsentry/telemetry-experience
527+
/static/app/views/insights/pages/platform/ @getsentry/telemetry-experience
526528
## End of Telemetry Experience
527529

528530

.pre-commit-config.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ repos:
143143
|static/app/utils/profiling/profile/formats/typescript/trace\.json
144144
)$
145145
146+
- id: knip
147+
name: knip
148+
language: system
149+
files: \.(ts|js|tsx|jsx|mjs)$
150+
pass_filenames: false
151+
stages: [pre-push]
152+
entry: bash -c 'if [ -n "${SENTRY_KNIP_PRE_PUSH:-}" ]; then exec ./node_modules/.bin/knip; fi' --
153+
146154
- repo: https://github.com/pre-commit/pygrep-hooks
147155
rev: v1.10.0
148156
hooks:

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ test-cli: create-db
100100
cd test_cli && sentry init test_conf
101101
cd test_cli && sentry --config=test_conf help
102102
cd test_cli && sentry --config=test_conf upgrade --traceback --noinput
103-
cd test_cli && sentry --config=test_conf export
103+
cd test_cli && sentry --config=test_conf export --help
104104
rm -r test_cli
105105
@echo ""
106106

knip.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const storyBookEntryPoints = [
3333
// our storybook implementation is here
3434
'static/app/stories/storyBook.tsx',
3535
// custom webpack loaders for stories
36-
'static/app/**/stories/*loader.ts',
36+
'static/app/stories/*loader.ts',
3737
];
3838

3939
const config: KnipConfig = {

migrations_lockfile.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ nodestore: 0001_squashed_0002_nodestore_no_dictfield
2121

2222
replays: 0001_squashed_0005_drop_replay_index
2323

24-
sentry: 0908_increase_email_field_length
24+
sentry: 0911_increase_email_model_email_field_length
2525

2626
social_auth: 0001_squashed_0002_default_auto_field
2727

2828
tempest: 0001_squashed_0002_make_message_type_nullable
2929

3030
uptime: 0001_squashed_0042_extra_uptime_indexes
3131

32-
workflow_engine: 0066_workflow_action_group_status_table
32+
workflow_engine: 0001_squashed_0065_add_status_to_detector_and_workflow

requirements-base.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ botocore>=1.34.8
66
brotli>=1.1.0
77
cachetools>=5
88
celery>=5
9-
click>=8.1
9+
click>=8.2
1010
confluent-kafka>=2.3.0
1111
cronsim>=2.6
1212
cssselect>=1.0.3

requirements-dev-frozen.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ cffi==1.17.1
2525
cfgv==3.3.1
2626
chardet==5.2.0
2727
charset-normalizer==3.4.0
28-
click==8.1.7
29-
click-didyoumean==0.3.0
28+
click==8.2.1
29+
click-didyoumean==0.3.1
3030
click-plugins==1.1.1
3131
click-repl==0.3.0
3232
confluent-kafka==2.8.0

requirements-frozen.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ certifi==2024.7.4
2222
cffi==1.17.1
2323
chardet==5.2.0
2424
charset-normalizer==3.4.0
25-
click==8.1.7
26-
click-didyoumean==0.3.0
25+
click==8.2.1
26+
click-didyoumean==0.3.1
2727
click-plugins==1.1.1
2828
click-repl==0.3.0
2929
confluent-kafka==2.8.0

rspack.config.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,8 @@ const appConfig: Configuration = {
380380
resolveLoader: {
381381
alias: {
382382
'type-loader': STORYBOOK_TYPES
383-
? path.resolve(__dirname, 'static/app/views/stories/type-loader.ts')
384-
: path.resolve(__dirname, 'static/app/views/stories/noop-type-loader.ts'),
383+
? path.resolve(__dirname, 'static/app/stories/type-loader.ts')
384+
: path.resolve(__dirname, 'static/app/stories/noop-type-loader.ts'),
385385
},
386386
},
387387

@@ -784,7 +784,8 @@ appConfig.plugins?.push(
784784
create: false,
785785
},
786786
reactComponentAnnotation: {
787-
enabled: true,
787+
// Enabled only in production because annotating is slow
788+
enabled: IS_PRODUCTION,
788789
},
789790
bundleSizeOptimizations: {
790791
// This is enabled so that our SDKs send exceptions to Sentry

src/sentry/api/bases/organization.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ def is_not_2fa_compliant(
6464
if request.user.is_authenticated and request.user.is_sentry_app:
6565
return False
6666

67+
if request.user.is_anonymous:
68+
return False
69+
6770
if is_active_superuser(request):
6871
return False
6972

src/sentry/api/endpoints/organization_events_meta.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -178,18 +178,16 @@ def get(self, request: Request, organization) -> Response:
178178
except NoProjects:
179179
return Response({})
180180

181-
# TODO: remove useRpc param
182-
use_eap = (
183-
request.GET.get("useRpc", "0") == "1" or request.GET.get("dataset", None) == "spans"
184-
)
181+
use_eap = request.GET.get("dataset", None) == "spans"
185182
orderby = self.get_orderby(request) or ["timestamp"]
186183

187-
if use_eap:
188-
result = get_eap_span_samples(request, snuba_params, orderby)
189-
dataset = spans_rpc
190-
else:
191-
result = get_span_samples(request, snuba_params, orderby)
192-
dataset = spans_indexed
184+
with handle_query_errors():
185+
if use_eap:
186+
result = get_eap_span_samples(request, snuba_params, orderby)
187+
dataset = spans_rpc
188+
else:
189+
result = get_span_samples(request, snuba_params, orderby)
190+
dataset = spans_indexed
193191

194192
return Response(
195193
self.handle_results_with_meta(

src/sentry/api/endpoints/organization_trace_item_attributes.py

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
TraceItemAttributeNamesRequest,
1111
TraceItemAttributeValuesRequest,
1212
)
13+
from sentry_protos.snuba.v1.request_common_pb2 import PageToken
1314
from sentry_protos.snuba.v1.request_common_pb2 import TraceItemType as ProtoTraceItemType
1415
from sentry_protos.snuba.v1.trace_item_attribute_pb2 import AttributeKey
1516

@@ -20,7 +21,7 @@
2021
from sentry.api.bases import NoProjects, OrganizationEventsV2EndpointBase
2122
from sentry.api.endpoints.organization_spans_fields import BaseSpanFieldValuesAutocompletionExecutor
2223
from sentry.api.event_search import translate_escape_sequences
23-
from sentry.api.paginator import ChainPaginator
24+
from sentry.api.paginator import ChainPaginator, GenericOffsetPaginator
2425
from sentry.api.serializers import serialize
2526
from sentry.api.utils import handle_query_errors
2627
from sentry.models.organization import Organization
@@ -35,6 +36,40 @@
3536
from sentry.snuba.referrer import Referrer
3637
from sentry.tagstore.types import TagValue
3738
from sentry.utils import snuba_rpc
39+
from sentry.utils.cursors import Cursor, CursorResult
40+
41+
42+
class TraceItemAttributesNamesPaginator:
43+
"""
44+
This is a bit of a weird paginator.
45+
46+
The trace item attributes RPC returns a list of attribute names from the
47+
database. But depending on the item type, it is possible that there are some
48+
hard coded attribute names that gets appended to the end of the results.
49+
Because of that, the number of results returned can exceed limit + 1.
50+
51+
To handle this nicely, here we choose to return the full set of results
52+
even if it exceeds limit + 1.
53+
"""
54+
55+
def __init__(self, data_fn):
56+
self.data_fn = data_fn
57+
58+
def get_result(self, limit, cursor=None):
59+
if limit <= 0:
60+
raise ValueError(f"invalid limit for paginator, expected >0, got {limit}")
61+
62+
offset = cursor.offset if cursor is not None else 0
63+
# Request 1 more than limit so we can tell if there is another page
64+
data = self.data_fn(offset=offset, limit=limit + 1)
65+
assert isinstance(data, list)
66+
has_more = len(data) >= limit + 1
67+
68+
return CursorResult(
69+
data,
70+
prev=Cursor(0, max(0, offset - limit), True, offset > 0),
71+
next=Cursor(0, max(0, offset + limit), False, has_more),
72+
)
3873

3974

4075
class OrganizationTraceItemAttributesEndpointBase(OrganizationEventsV2EndpointBase):
@@ -166,32 +201,28 @@ def get(self, request: Request, organization: Organization) -> Response:
166201
else AttributeKey.Type.TYPE_STRING
167202
)
168203

169-
rpc_request = TraceItemAttributeNamesRequest(
170-
meta=meta,
171-
limit=max_attributes,
172-
offset=0,
173-
type=attr_type,
174-
value_substring_match=value_substring_match,
175-
intersecting_attributes_filter=filter,
176-
)
204+
def data_fn(offset: int, limit: int):
205+
rpc_request = TraceItemAttributeNamesRequest(
206+
meta=meta,
207+
limit=limit,
208+
page_token=PageToken(offset=offset),
209+
type=attr_type,
210+
value_substring_match=value_substring_match,
211+
intersecting_attributes_filter=filter,
212+
)
177213

178-
with handle_query_errors():
179-
rpc_response = snuba_rpc.attribute_names_rpc(rpc_request)
180-
181-
paginator = ChainPaginator(
182-
[
183-
[
184-
as_attribute_key(attribute.name, serialized["attribute_type"], trace_item_type)
185-
for attribute in rpc_response.attributes
186-
if attribute.name and can_expose_attribute(attribute.name, trace_item_type)
187-
],
188-
],
189-
max_limit=max_attributes,
190-
)
214+
with handle_query_errors():
215+
rpc_response = snuba_rpc.attribute_names_rpc(rpc_request)
216+
217+
return [
218+
as_attribute_key(attribute.name, serialized["attribute_type"], trace_item_type)
219+
for attribute in rpc_response.attributes
220+
if attribute.name and can_expose_attribute(attribute.name, trace_item_type)
221+
]
191222

192223
return self.paginate(
193224
request=request,
194-
paginator=paginator,
225+
paginator=TraceItemAttributesNamesPaginator(data_fn=data_fn),
195226
on_results=lambda results: serialize(results, request.user),
196227
default_per_page=max_attributes,
197228
max_per_page=max_attributes,
@@ -230,24 +261,25 @@ def get(self, request: Request, organization: Organization, key: str) -> Respons
230261
else OURLOG_DEFINITIONS
231262
)
232263

233-
executor = TraceItemAttributeValuesAutocompletionExecutor(
234-
organization=organization,
235-
snuba_params=snuba_params,
236-
key=key,
237-
query=substring_match,
238-
max_span_tag_values=max_attribute_values,
239-
definitions=definitions,
240-
)
241-
242-
with handle_query_errors():
243-
tag_values = executor.execute()
244-
tag_values.sort(key=lambda tag: tag.value)
264+
def data_fn(offset: int, limit: int):
265+
executor = TraceItemAttributeValuesAutocompletionExecutor(
266+
organization=organization,
267+
snuba_params=snuba_params,
268+
key=key,
269+
query=substring_match,
270+
limit=limit,
271+
offset=offset,
272+
definitions=definitions,
273+
)
245274

246-
paginator = ChainPaginator([tag_values], max_limit=max_attribute_values)
275+
with handle_query_errors():
276+
tag_values = executor.execute()
277+
tag_values.sort(key=lambda tag: tag.value)
278+
return tag_values
247279

248280
return self.paginate(
249281
request=request,
250-
paginator=paginator,
282+
paginator=GenericOffsetPaginator(data_fn=data_fn),
251283
on_results=lambda results: serialize(results, request.user),
252284
default_per_page=max_attribute_values,
253285
max_per_page=max_attribute_values,
@@ -261,10 +293,13 @@ def __init__(
261293
snuba_params: SnubaParams,
262294
key: str,
263295
query: str | None,
264-
max_span_tag_values: int,
296+
limit: int,
297+
offset: int,
265298
definitions: ColumnDefinitions,
266299
):
267-
super().__init__(organization, snuba_params, key, query, max_span_tag_values)
300+
super().__init__(organization, snuba_params, key, query, limit)
301+
self.limit = limit
302+
self.offset = offset
268303
self.resolver = SearchResolver(
269304
params=snuba_params, config=SearchResolverConfig(), definitions=definitions
270305
)
@@ -326,7 +361,8 @@ def string_autocomplete_function(self) -> list[TagValue]:
326361
meta=meta,
327362
key=self.attribute_key,
328363
value_substring_match=query,
329-
limit=self.max_span_tag_values,
364+
limit=self.limit,
365+
page_token=PageToken(offset=self.offset),
330366
)
331367
rpc_response = snuba_rpc.attribute_values_rpc(rpc_request)
332368

src/sentry/api/endpoints/project_details.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,6 @@ class ProjectMemberSerializer(serializers.Serializer):
128128
"copy_from_project",
129129
"targetSampleRate",
130130
"dynamicSamplingBiases",
131-
"performanceIssueCreationRate",
132-
"performanceIssueCreationThroughPlatform",
133-
"performanceIssueSendToPlatform",
134131
"tempestFetchScreenshots",
135132
"tempestFetchDumps",
136133
"autofixAutomationTuning",
@@ -223,9 +220,6 @@ class ProjectAdminSerializer(ProjectMemberSerializer):
223220
copy_from_project = serializers.IntegerField(required=False)
224221
targetSampleRate = serializers.FloatField(required=False, min_value=0, max_value=1)
225222
dynamicSamplingBiases = DynamicSamplingBiasSerializer(required=False, many=True)
226-
performanceIssueCreationRate = serializers.FloatField(required=False, min_value=0, max_value=1)
227-
performanceIssueCreationThroughPlatform = serializers.BooleanField(required=False)
228-
performanceIssueSendToPlatform = serializers.BooleanField(required=False)
229223
tempestFetchScreenshots = serializers.BooleanField(required=False)
230224
tempestFetchDumps = serializers.BooleanField(required=False)
231225
autofixAutomationTuning = serializers.ChoiceField(

0 commit comments

Comments
 (0)