Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 13 additions & 20 deletions src/sentry/grouping/ingest/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,22 @@ def update_or_set_grouping_config_if_needed(project: Project, source: str) -> st
use by scripts.
"""
current_config = project.get_option("sentry:grouping_config")
current_config_is_valid = current_config in GROUPING_CONFIG_CLASSES.keys()

# If the project's current config comes back as the default one, it might be because that's
# actually what's set in the database for that project, or it might be relying on the default
# value of that project option. In the latter case, we can use this upgrade check as a chance to
# set it. (We want projects to have their own record of the config they're using, so that when
# we introduce a new one, we know to transition them.)
project_option_exists = ProjectOption.objects.filter(
key="sentry:grouping_config", project_id=project.id
).exists()

if current_config == BETA_GROUPING_CONFIG:
return "skipped - beta config"

if current_config == DEFAULT_GROUPING_CONFIG:
# If the project's current config comes back as the default one, it might be because that's
# actually what's set in the database for that project, or it might be relying on the
# default value of that project option. In the latter case, we can use this upgrade check as
# a chance to set it. (We want projects to have their own record of the config they're
# using, so that when we introduce a new one, we know to transition them.)
project_option_exists = ProjectOption.objects.filter(
key="sentry:grouping_config", project_id=project.id
).exists()

if project_option_exists:
return "skipped - up-to-date record exists"
if current_config == DEFAULT_GROUPING_CONFIG and project_option_exists:
return "skipped - up-to-date record exists"

# We want to try to write the audit log entry and project option change just once, so we use a
# cache key to avoid raciness. It's not perfect, but it reduces the risk significantly.
Expand All @@ -69,10 +69,7 @@ def update_or_set_grouping_config_if_needed(project: Project, source: str) -> st
changes: dict[str, str | int] = {"sentry:grouping_config": DEFAULT_GROUPING_CONFIG}

# If the current config is out of date but still valid, start a transition period
if (
current_config != DEFAULT_GROUPING_CONFIG
and current_config in GROUPING_CONFIG_CLASSES.keys()
):
if current_config != DEFAULT_GROUPING_CONFIG and current_config_is_valid:
# This is when we will stop calculating the old hash in cases where we don't find the
# new hash (which we do in an effort to preserve group continuity).
transition_expiry = (
Expand All @@ -86,10 +83,6 @@ def update_or_set_grouping_config_if_needed(project: Project, source: str) -> st
}
)

project_option_exists = ProjectOption.objects.filter(
key="sentry:grouping_config", project_id=project.id
).exists()

for key, value in changes.items():
project.update_option(key, value)

Expand Down
19 changes: 7 additions & 12 deletions src/sentry/grouping/strategies/newstyle.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
ErrorTypeGroupingComponent,
ErrorValueGroupingComponent,
ExceptionGroupingComponent,
ExceptionGroupingComponentChildren,
FilenameGroupingComponent,
FrameGroupingComponent,
FunctionGroupingComponent,
Expand Down Expand Up @@ -461,7 +462,7 @@ def _single_stacktrace_variant(
and frame_components[0].contributes
and get_behavior_family_for_platform(frames[0].platform or event.platform) == "javascript"
and not frames[0].function
and frames[0].is_url()
and has_url_origin(frames[0].abs_path, files_count_as_urls=True)
):
frame_components[0].update(
contributes=False, hint="ignored single non-URL JavaScript frame"
Expand Down Expand Up @@ -558,16 +559,6 @@ def single_exception(
exception_components_by_variant = {}

for variant_name, stacktrace_component in stacktrace_components_by_variant.items():
values: list[
ErrorTypeGroupingComponent
| ErrorValueGroupingComponent
| NSErrorGroupingComponent
| StacktraceGroupingComponent
] = [stacktrace_component, type_component]

if ns_error_component is not None:
values.append(ns_error_component)

value_component = ErrorValueGroupingComponent()

raw = exception.value
Expand All @@ -593,7 +584,11 @@ def single_exception(
hint="ignored because ns-error info takes precedence",
)

values.append(value_component)
values: list[ExceptionGroupingComponentChildren] = []
if ns_error_component is not None:
values = [stacktrace_component, type_component, ns_error_component, value_component]
else:
values = [stacktrace_component, type_component, value_component]

exception_components_by_variant[variant_name] = ExceptionGroupingComponent(
values=values, frame_counts=stacktrace_component.frame_counts
Expand Down
Loading