Skip to content

Commit f0cb11c

Browse files
committed
Merge branch 'master' into ryan953/insights-session-health-layout-ref
2 parents 0bf822c + f730536 commit f0cb11c

File tree

26 files changed

+327
-111
lines changed

26 files changed

+327
-111
lines changed

.github/CODEOWNERS

+7-6
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ yarn.lock @getsentry/owners-js-de
171171
/static/app/views/alerts/ @getsentry/alerts-notifications
172172
/static/app/views/alerts/rules/uptime @getsentry/crons
173173
/static/app/views/releases/ @getsentry/alerts-notifications
174+
/static/app/views/releases/drawer/ @getsentry/replay-frontend
175+
/static/app/views/releases/releaseBubbles/ @getsentry/replay-frontend
174176
/src/sentry/rules/processing/delayed_processing.py @getsentry/alerts-notifications
175177

176178
/static/app/views/settings/account/notifications/ @getsentry/alerts-notifications
@@ -329,12 +331,11 @@ tests/sentry/api/endpoints/test_organization_dashboard_widget_details.py @ge
329331

330332

331333
## Replays
332-
/static/app/views/releases/drawer/ @getsentry/replay-frontend
333-
/static/app/components/replays/ @getsentry/replay-frontend
334-
/static/app/utils/replays/ @getsentry/replay-frontend
335-
/static/app/views/replays/ @getsentry/replay-frontend
336-
/src/sentry/replays/ @getsentry/replay-backend
337-
/tests/sentry/replays/ @getsentry/replay-backend
334+
/static/app/components/replays/ @getsentry/replay-frontend
335+
/static/app/utils/replays/ @getsentry/replay-frontend
336+
/static/app/views/replays/ @getsentry/replay-frontend
337+
/src/sentry/replays/ @getsentry/replay-backend
338+
/tests/sentry/replays/ @getsentry/replay-backend
338339
## End of Replays
339340

340341

src/sentry/api/endpoints/api_tokens.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
from sentry.api.authentication import SessionNoAuthTokenAuthentication
1414
from sentry.api.base import Endpoint, control_silo_endpoint
1515
from sentry.api.exceptions import ResourceDoesNotExist
16-
from sentry.api.fields import MultipleChoiceField
1716
from sentry.api.permissions import SentryIsAuthenticated
1817
from sentry.api.serializers import serialize
1918
from sentry.auth.elevated_mode import has_elevated_mode
@@ -27,7 +26,7 @@
2726

2827
class ApiTokenSerializer(serializers.Serializer):
2928
name = CharField(max_length=255, allow_blank=True, required=False)
30-
scopes = MultipleChoiceField(required=True, choices=settings.SENTRY_SCOPES)
29+
scopes = serializers.MultipleChoiceField(required=True, choices=list(settings.SENTRY_SCOPES))
3130

3231

3332
def get_appropriate_user_id(request: Request) -> int:

src/sentry/api/fields/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from .avatar import * # noqa: F401,F403
33
from .empty_decimal import * # noqa: F401,F403
44
from .empty_integer import * # noqa: F401,F403
5-
from .multiplechoice import * # noqa: F401,F403
65
from .sentry_slug import * # noqa: F401,F403
76
from .serializedfile import * # noqa: F401,F403
87
from .user import * # noqa: F401,F403

src/sentry/api/fields/multiplechoice.py

-24
This file was deleted.

src/sentry/discover/compare_timeseries.py

+45-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
from collections import defaultdict
23
from datetime import datetime, timedelta, timezone
34
from typing import Any, TypedDict
@@ -13,12 +14,16 @@
1314
from sentry.search.events.fields import get_function_alias
1415
from sentry.search.events.types import SnubaParams
1516
from sentry.snuba.entity_subscription import apply_dataset_query_conditions
17+
from sentry.snuba.metrics import parse_mri_field
1618
from sentry.snuba.metrics.extraction import MetricSpecType
1719
from sentry.snuba.metrics_performance import timeseries_query
1820
from sentry.snuba.models import SnubaQuery
21+
from sentry.snuba.referrer import Referrer
1922
from sentry.snuba.spans_rpc import run_timeseries_query
2023
from sentry.utils.snuba import SnubaTSResult
2124

25+
logger = logging.getLogger(__name__)
26+
2227

2328
class TSResultForComparison(TypedDict):
2429
result: SnubaTSResult
@@ -40,7 +45,7 @@ def make_rpc_request(
4045
snuba_params,
4146
query_string=query_parts["query"],
4247
y_axes=query_parts["selected_columns"],
43-
referrer="job-runner.compare-timeseries",
48+
referrer=Referrer.JOB_COMPARE_TIMESERIES.value,
4449
granularity_secs=time_window,
4550
config=SearchResolverConfig(),
4651
)
@@ -62,7 +67,7 @@ def make_snql_request(
6267
query,
6368
snuba_params=snuba_params,
6469
rollup=time_window,
65-
referrer="job-runner.compare-timeseries",
70+
referrer=Referrer.JOB_COMPARE_TIMESERIES.value,
6671
on_demand_metrics_enabled=on_demand_metrics_enabled,
6772
on_demand_metrics_type=MetricSpecType.SIMPLE_QUERY,
6873
zerofill_results=True,
@@ -86,7 +91,7 @@ def fill_aligned_series(data: dict[str, Any], alias: str, key: str):
8691
return aligned_results
8792

8893

89-
def assert_timeseries_close(aligned_timeseries):
94+
def assert_timeseries_close(aligned_timeseries, alert_rule):
9095
mismatches: dict[int, dict[str, float]] = {}
9196
missing_buckets = 0
9297
for timestamp, values in aligned_timeseries.items():
@@ -116,12 +121,22 @@ def assert_timeseries_close(aligned_timeseries):
116121
if mismatches:
117122
with sentry_sdk.isolation_scope() as scope:
118123
scope.set_extra("mismatches", mismatches)
124+
scope.set_extra("alert_id", alert_rule.id)
119125
sentry_sdk.capture_message("Timeseries mismatch", level="info")
126+
logger.info("Alert %s has too many mismatches", alert_rule.id)
127+
128+
return False, mismatches
120129

121130
if missing_buckets > 1:
122-
sentry_sdk.capture_message("Multiple missing buckets!", level="info")
131+
with sentry_sdk.isolation_scope() as scope:
132+
scope.set_extra("alert_id", alert_rule.id)
133+
sentry_sdk.capture_message("Multiple missing buckets", level="info")
134+
logger.info("Alert %s has multiple missing buckets", alert_rule.id)
135+
136+
return False, mismatches
123137

124-
return mismatches
138+
logger.info("Alert %s timeseries is close", alert_rule.id)
139+
return True, mismatches
125140

126141

127142
def compare_timeseries_for_alert_rule(alert_rule: AlertRule):
@@ -130,6 +145,22 @@ def compare_timeseries_for_alert_rule(alert_rule: AlertRule):
130145
if not project:
131146
raise NoProjects
132147

148+
if snuba_query.aggregate in ["apdex()"]:
149+
logger.info(
150+
"Skipping alert %s, %s aggregate not yet supported by RPC",
151+
alert_rule.id,
152+
snuba_query.aggregate,
153+
)
154+
return {"skipped": True, "is_close": False}
155+
156+
if parse_mri_field(snuba_query.aggregate):
157+
logger.info(
158+
"Skipping alert %s, %s, MRI fields not supported in aggregates",
159+
alert_rule.id,
160+
snuba_query.aggregate,
161+
)
162+
return {"skipped": True, "is_close": False}
163+
133164
organization = Organization.objects.get_from_cache(id=project.organization_id)
134165

135166
on_demand_metrics_enabled = features.has(
@@ -139,8 +170,13 @@ def compare_timeseries_for_alert_rule(alert_rule: AlertRule):
139170

140171
# Align time to the nearest hour because RPCs roll up on exact timestamps.
141172
now = datetime.now(tz=timezone.utc).replace(minute=0, second=0, microsecond=0)
173+
174+
environments = []
175+
if snuba_query.environment:
176+
environments = [snuba_query.environment]
177+
142178
snuba_params = SnubaParams(
143-
environments=[snuba_query.environment],
179+
environments=environments,
144180
projects=[project],
145181
organization=organization,
146182
start=now - timedelta(days=1),
@@ -164,4 +200,6 @@ def compare_timeseries_for_alert_rule(alert_rule: AlertRule):
164200

165201
aligned_timeseries = align_timeseries(snql_result=snql_result, rpc_result=rpc_result)
166202

167-
return assert_timeseries_close(aligned_timeseries)
203+
is_close, mismatches = assert_timeseries_close(aligned_timeseries, alert_rule)
204+
205+
return {"is_close": is_close, "skipped": False, "mismatches": mismatches}

src/sentry/discover/translation/mep_to_eap.py

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from sentry.api.event_search import event_search_grammar
66
from sentry.search.events import fields
7+
from sentry.snuba.metrics import parse_mri
78

89

910
class QueryParts(TypedDict):
@@ -20,6 +21,10 @@ def apply_is_segment_condition(query: str) -> str:
2021

2122

2223
def column_switcheroo(term):
24+
parsed_mri = parse_mri(term)
25+
if parsed_mri:
26+
term = parsed_mri.name
27+
2328
if term == "transaction.duration":
2429
return "span.duration"
2530

src/sentry/features/temporary.py

+2
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,8 @@ def register_temporary_features(manager: FeatureManager):
483483
manager.add("organizations:workflow-engine-issue-alert-dual-write", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
484484
# Enable workflow engine for issue alerts
485485
manager.add("organizations:workflow-engine-process-workflows", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
486+
# Enable logging to debug workflow engine process workflows
487+
manager.add("organizations:workflow-engine-process-workflows-logs", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
486488
# Enable firing actions for workflow engine issue alerts
487489
manager.add("organizations:workflow-engine-trigger-actions", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
488490
# Enable dual writing for metric alert issues (see: alerts create issues)

src/sentry/rules/processing/delayed_processing.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from celery import Task
1010
from django.db.models import OuterRef, Subquery
1111

12-
from sentry import buffer, nodestore
12+
from sentry import buffer, features, nodestore
1313
from sentry.buffer.base import BufferField
1414
from sentry.db import models
1515
from sentry.eventstore.models import Event, GroupEvent
@@ -465,6 +465,19 @@ def fire_rules(
465465
groupevent = group_to_groupevent[group]
466466
rule_fire_history = history.record(rule, group, groupevent.event_id, notification_uuid)
467467

468+
if features.has(
469+
"organizations:workflow-engine-process-workflows-logs",
470+
project.organization,
471+
):
472+
logger.info(
473+
"post_process.delayed_processing.triggered_rule",
474+
extra={
475+
"rule_id": rule.id,
476+
"group_id": group.id,
477+
"event_id": groupevent.event_id,
478+
},
479+
)
480+
468481
callback_and_futures = activate_downstream_actions(
469482
rule, groupevent, notification_uuid, rule_fire_history, is_post_process=False
470483
).values()

src/sentry/rules/processing/processor.py

+15
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,21 @@ def apply_rule(self, rule: Rule, status: GroupRuleStatus) -> None:
396396
organization_id=rule.project.organization.id,
397397
rule_id=rule.id,
398398
)
399+
400+
if features.has(
401+
"organizations:workflow-engine-process-workflows-logs",
402+
rule.project.organization,
403+
):
404+
logger.info(
405+
"post_process.process_rules.triggered_rule",
406+
extra={
407+
"rule_id": rule.id,
408+
"payload": state,
409+
"group_id": self.group.id,
410+
"event_id": self.event.event_id,
411+
},
412+
)
413+
399414
notification_uuid = str(uuid.uuid4())
400415
rule_fire_history = history.record(rule, self.group, self.event.event_id, notification_uuid)
401416
grouped_futures = activate_downstream_actions(

src/sentry/search/eap/spans/formulas.py

+38
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,38 @@
3232
)
3333

3434

35+
def failure_rate(_: ResolvedArguments) -> Column.BinaryFormula:
36+
return Column.BinaryFormula(
37+
left=Column(
38+
conditional_aggregation=AttributeConditionalAggregation(
39+
aggregate=Function.FUNCTION_COUNT,
40+
key=AttributeKey(
41+
name="sentry.trace.status",
42+
type=AttributeKey.TYPE_STRING,
43+
),
44+
filter=TraceItemFilter(
45+
comparison_filter=ComparisonFilter(
46+
key=AttributeKey(
47+
name="sentry.trace.status",
48+
type=AttributeKey.TYPE_STRING,
49+
),
50+
op=ComparisonFilter.OP_NOT_IN,
51+
value=AttributeValue(
52+
val_str_array=StrArray(
53+
values=["ok", "cancelled", "unknown"],
54+
),
55+
),
56+
)
57+
),
58+
label="trace_status_count",
59+
extrapolation_mode=ExtrapolationMode.EXTRAPOLATION_MODE_NONE,
60+
),
61+
),
62+
op=Column.BinaryFormula.OP_DIVIDE,
63+
right=TOTAL_SPAN_COUNT,
64+
)
65+
66+
3567
def http_response_rate(args: ResolvedArguments) -> Column.BinaryFormula:
3668
code = cast(Literal[1, 2, 3, 4, 5], args[0])
3769

@@ -223,6 +255,12 @@ def ttid_contribution_rate(args: ResolvedArguments) -> Column.BinaryFormula:
223255
],
224256
formula_resolver=trace_status_rate,
225257
),
258+
"failure_rate": FormulaDefinition(
259+
default_search_type="percentage",
260+
arguments=[],
261+
formula_resolver=failure_rate,
262+
is_aggregate=True,
263+
),
226264
"ttfd_contribution_rate": FormulaDefinition(
227265
default_search_type="percentage",
228266
arguments=[],

src/sentry/snuba/referrer.py

+2
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,8 @@ class Referrer(StrEnum):
984984
TEST_QUERY = "test_query"
985985
METRIC_VALIDATION = "metric_validation"
986986

987+
JOB_COMPARE_TIMESERIES = "job-runner.compare-timeseries"
988+
987989

988990
VALUES = {referrer.value for referrer in Referrer}
989991

src/sentry/workflow_engine/processors/delayed_workflow.py

+11
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
from sentry.workflow_engine.processors.workflow import (
4747
WORKFLOW_ENGINE_BUFFER_LIST_KEY,
4848
evaluate_workflows_action_filters,
49+
log_fired_workflows,
4950
)
5051
from sentry.workflow_engine.types import DataConditionHandler, WorkflowJob
5152

@@ -423,6 +424,16 @@ def fire_actions_for_groups(
423424
tags={"event_type": group_event.group.type},
424425
)
425426

427+
if features.has(
428+
"organizations:workflow-engine-process-workflows-logs",
429+
organization,
430+
):
431+
log_fired_workflows(
432+
log_name="workflow_engine.delayed_workflow.fired_workflow",
433+
actions=filtered_actions,
434+
job=job,
435+
)
436+
426437
if features.has(
427438
"organizations:workflow-engine-trigger-actions",
428439
organization,

0 commit comments

Comments
 (0)