Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(inbound-filters): Add react-hydration-errors filter #45188

Merged
merged 10 commits into from
Mar 3, 2023
5 changes: 5 additions & 0 deletions src/sentry/api/endpoints/project_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,11 @@ def put(self, request: Request, project) -> Response:
"sentry:reprocessing_active",
bool(options["sentry:reprocessing_active"]),
)
if "filters:react-hydration-errors" in options:
project.update_option(
"filters:react-hydration-errors",
bool(options["filters:react-hydration-errors"]),
)
if "filters:blacklisted_ips" in options:
project.update_option(
"sentry:blacklisted_ips",
Expand Down
1 change: 1 addition & 0 deletions src/sentry/api/serializers/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ def format_options(attrs: defaultdict(dict)):
"sentry:performance_issue_creation_rate"
),
"filters:blacklisted_ips": "\n".join(options.get("sentry:blacklisted_ips", [])),
"filters:react-hydration-errors": bool(options.get("filters:react-hydration-errors", True)),
priscilawebdev marked this conversation as resolved.
Show resolved Hide resolved
f"filters:{FilterTypes.RELEASES}": "\n".join(
options.get(f"sentry:{FilterTypes.RELEASES}", [])
),
Expand Down
1 change: 1 addition & 0 deletions src/sentry/models/options/project_option.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"digests:mail:maximum_delay",
"mail:subject_prefix",
"mail:subject_template",
"filters:react-hydration-errors",
]
)

Expand Down
9 changes: 6 additions & 3 deletions src/sentry/projectoptions/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,18 @@
# Default legacy-browsers filter
register(key="filters:legacy-browsers", epoch_defaults={1: "0"})

# Default legacy-browsers filter
# Default web crawlers filter
register(key="filters:web-crawlers", epoch_defaults={1: "1", 6: "0"})

# Default legacy-browsers filter
# Default browser extensions filter
register(key="filters:browser-extensions", epoch_defaults={1: "0"})

# Default legacy-browsers filter
# Default localhost filter
register(key="filters:localhost", epoch_defaults={1: "0"})

# Default react hydration errors filter
register(key="filters:react-hydration-errors", epoch_defaults={1: "1"})

# Default breakdowns config
register(
key="sentry:breakdowns",
Expand Down
23 changes: 20 additions & 3 deletions src/sentry/relay/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,31 @@ def get_filter_settings(project: Project) -> Mapping[str, Any]:
settings = _load_filter_settings(flt, project)
filter_settings[filter_id] = settings

error_messages = []
if features.has("projects:custom-inbound-filters", project):
invalid_releases = project.get_option(f"sentry:{FilterTypes.RELEASES}")
if invalid_releases:
filter_settings["releases"] = {"releases": invalid_releases}

error_messages = project.get_option(f"sentry:{FilterTypes.ERROR_MESSAGES}")
if error_messages:
filter_settings["errorMessages"] = {"patterns": error_messages}
error_messages += project.get_option(f"sentry:{FilterTypes.ERROR_MESSAGES}") or []

enable_react = project.get_option("filters:react-hydration-errors")
if enable_react:
error_messages += [
# Hydration failed because the initial UI does not match what was rendered on the server.
"https://reactjs.org/docs/error-decoder.html?invariant=418",
# The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.
"https://reactjs.org/docs/error-decoder.html?invariant=419",
# There was an error while hydrating this Suspense boundary. Switched to client rendering.
"https://reactjs.org/docs/error-decoder.html?invariant=422",
# There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.
"https://reactjs.org/docs/error-decoder.html?invariant=423",
# Text content does not match server-rendered HTML.
"https://reactjs.org/docs/error-decoder.html?invariant=425",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because error_messages parses glob patterns, we could shorten this to

Suggested change
"https://reactjs.org/docs/error-decoder.html?invariant=418",
# The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.
"https://reactjs.org/docs/error-decoder.html?invariant=419",
# There was an error while hydrating this Suspense boundary. Switched to client rendering.
"https://reactjs.org/docs/error-decoder.html?invariant=422",
# There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.
"https://reactjs.org/docs/error-decoder.html?invariant=423",
# Text content does not match server-rendered HTML.
"https://reactjs.org/docs/error-decoder.html?invariant=425",
"https://reactjs.org/docs/error-decoder.html?invariant={418,419,422,423,425}"

Copy link
Member

@HazAT HazAT Mar 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's please leave it like this, obviously more verbose, but the comments are helpful to understand what the numbers actually mean.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm totally in favor of keeping the comments, but we could still shorten the value itself.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I have updated the code shortening the value but still keeping the comments... Hope it's better now

]

if error_messages:
filter_settings["errorMessages"] = {"patterns": error_messages}

blacklisted_ips = project.get_option("sentry:blacklisted_ips")
if blacklisted_ips:
Expand Down
11 changes: 11 additions & 0 deletions tests/sentry/api/endpoints/test_project_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ def test_options(self):
"sentry:token_header": "*",
"sentry:verify_ssl": False,
"feedback:branding": False,
"filters:react-hydration-errors": True,
}
with self.feature("projects:custom-inbound-filters"):
self.get_success_response(self.org_slug, self.proj_slug, options=options)
Expand Down Expand Up @@ -558,6 +559,7 @@ def test_options(self):
assert AuditLogEntry.objects.filter(
organization=project.organization, event=audit_log.get_event_id("PROJECT_EDIT")
).exists()
assert project.get_option("filters:react-hydration-errors", "1")

def test_bookmarks(self):
self.get_success_response(self.org_slug, self.proj_slug, isBookmarked="false")
Expand Down Expand Up @@ -688,6 +690,15 @@ def test_store_crash_reports_exceeded(self):
assert self.project.get_option("sentry:store_crash_reports") is None
assert b"storeCrashReports" in resp.content

def test_react_hydration_errors(self):
value = False
resp = self.get_success_response(
self.org_slug, self.proj_slug, options={"filters:react-hydration-errors": value}
)
project = Project.objects.get(id=self.project.id)
assert project.get_option("filters:react_hydration_errors") == value
assert resp.data["options"]["filters:react_hydration_errors"] == value

def test_relay_pii_config(self):
value = '{"applications": {"freeform": []}}'
resp = self.get_success_response(self.org_slug, self.proj_slug, relayPiiConfig=value)
Expand Down