From fb811de040eda4c863137ec5a5f0136cfea7a7ed Mon Sep 17 00:00:00 2001 From: Riccardo Busetti Date: Mon, 2 Oct 2023 13:43:52 +0200 Subject: [PATCH 1/9] feat(inbound-filters): Add inbound filter for ChunkLoadError --- src/sentry/api/endpoints/project_details.py | 5 + src/sentry/api/serializers/models/project.py | 1 + .../apidocs/examples/project_examples.py | 1 + src/sentry/models/options/project_option.py | 1 + src/sentry/projectoptions/defaults.py | 3 + src/sentry/relay/config/__init__.py | 5 + .../api/endpoints/test_project_details.py | 14 ++ .../full_config/MONOLITH.pysnap.new | 125 ++++++++++++++++++ .../full_config/REGION.pysnap.new | 125 ++++++++++++++++++ tests/sentry/relay/test_config.py | 1 + 10 files changed, 281 insertions(+) create mode 100644 tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap.new create mode 100644 tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap.new diff --git a/src/sentry/api/endpoints/project_details.py b/src/sentry/api/endpoints/project_details.py index e8865bbb5f0061..88e96a2a7015a7 100644 --- a/src/sentry/api/endpoints/project_details.py +++ b/src/sentry/api/endpoints/project_details.py @@ -811,6 +811,11 @@ def put(self, request: Request, project) -> Response: "filters:react-hydration-errors", bool(options["filters:react-hydration-errors"]), ) + if "filters:chunk-load-error" in options: + project.update_option( + "filters:chunk-load-error", + bool(options["filters:chunk-load-error"]), + ) if "filters:blacklisted_ips" in options: project.update_option( "sentry:blacklisted_ips", diff --git a/src/sentry/api/serializers/models/project.py b/src/sentry/api/serializers/models/project.py index d8b9c8e7c9dcd9..cdd317515810a1 100644 --- a/src/sentry/api/serializers/models/project.py +++ b/src/sentry/api/serializers/models/project.py @@ -216,6 +216,7 @@ def format_options(attrs: dict[str, Any]) -> dict[str, Any]: "sentry:reprocessing_active": bool(options.get("sentry:reprocessing_active", False)), "filters:blacklisted_ips": "\n".join(options.get("sentry:blacklisted_ips", [])), "filters:react-hydration-errors": bool(options.get("filters:react-hydration-errors", True)), + "filters:chunk-load-error": bool(options.get("filters:chunk-load-error", True)), f"filters:{FilterTypes.RELEASES}": "\n".join( options.get(f"sentry:{FilterTypes.RELEASES}", []) ), diff --git a/src/sentry/apidocs/examples/project_examples.py b/src/sentry/apidocs/examples/project_examples.py index a87a83b75655ba..b6bcb6abf4cc16 100644 --- a/src/sentry/apidocs/examples/project_examples.py +++ b/src/sentry/apidocs/examples/project_examples.py @@ -189,6 +189,7 @@ "sentry:reprocessing_active": False, "filters:blacklisted_ips": "", "filters:react-hydration-errors": True, + "filters:chunk-load-error": True, "filters:releases": "", "filters:error_messages": "", "feedback:branding": True, diff --git a/src/sentry/models/options/project_option.py b/src/sentry/models/options/project_option.py index 0d956f8f847814..3c64d63ba5c70a 100644 --- a/src/sentry/models/options/project_option.py +++ b/src/sentry/models/options/project_option.py @@ -64,6 +64,7 @@ "mail:subject_prefix", "mail:subject_template", "filters:react-hydration-errors", + "filters:chunk-load-error", ] ) diff --git a/src/sentry/projectoptions/defaults.py b/src/sentry/projectoptions/defaults.py index 051bd1d3422c97..ffb8967d42cd09 100644 --- a/src/sentry/projectoptions/defaults.py +++ b/src/sentry/projectoptions/defaults.py @@ -79,6 +79,9 @@ # Default react hydration errors filter register(key="filters:react-hydration-errors", epoch_defaults={1: "1"}) +# Default NextJS chunk load error filter +register(key="filters:chunk-load-error", epoch_defaults={1: "1"}) + # Default breakdowns config register( key="sentry:breakdowns", diff --git a/src/sentry/relay/config/__init__.py b/src/sentry/relay/config/__init__.py index 7c571ffc8b5102..103796dc7e1b3d 100644 --- a/src/sentry/relay/config/__init__.py +++ b/src/sentry/relay/config/__init__.py @@ -146,6 +146,11 @@ def get_filter_settings(project: Project) -> Mapping[str, Any]: "*https://reactjs.org/docs/error-decoder.html?invariant={418,419,422,423,425}*" ] + enable_chunk_upload_error_filter = project.get_option("filters:chunk-load-error") + if enable_chunk_upload_error_filter: + # ChunkLoadError: Loading chunk 3662 failed. (error: https://xxx.com/_next/static/chunks/29107295-0151559bd23117ba.js) + error_messages += ["ChunkLoadError: Loading chunk * failed. (error: *)"] + if error_messages: filter_settings["errorMessages"] = {"patterns": error_messages} diff --git a/tests/sentry/api/endpoints/test_project_details.py b/tests/sentry/api/endpoints/test_project_details.py index 71806d38af6b9d..fc85523d13996a 100644 --- a/tests/sentry/api/endpoints/test_project_details.py +++ b/tests/sentry/api/endpoints/test_project_details.py @@ -600,6 +600,7 @@ def test_options(self): "sentry:verify_ssl": False, "feedback:branding": False, "filters:react-hydration-errors": True, + "filters:chunk-load-error": True, } with self.feature("projects:custom-inbound-filters"), outbox_runner(): self.get_success_response(self.org_slug, self.proj_slug, options=options) @@ -716,6 +717,12 @@ def test_options(self): event=audit_log.get_event_id("PROJECT_EDIT"), ).exists() assert project.get_option("filters:react-hydration-errors", "1") + with assume_test_silo_mode(SiloMode.CONTROL): + assert AuditLogEntry.objects.filter( + organization_id=project.organization_id, + event=audit_log.get_event_id("PROJECT_EDIT"), + ).exists() + assert project.get_option("filters:chunk-load-error", "1") def test_bookmarks(self): self.get_success_response(self.org_slug, self.proj_slug, isBookmarked="false") @@ -855,6 +862,13 @@ def test_react_hydration_errors(self): assert self.project.get_option("filters:react-hydration-errors") == value assert resp.data["options"]["filters:react-hydration-errors"] == value + def test_chunk_load_error(self): + value = False + options = {"filters:chunk-load-error": value} + resp = self.get_success_response(self.org_slug, self.proj_slug, options=options) + assert self.project.get_option("filters:chunk-load-error") == value + assert resp.data["options"]["filters:chunk-load-error"] == value + def test_relay_pii_config(self): value = '{"applications": {"freeform": []}}' resp = self.get_success_response(self.org_slug, self.proj_slug, relayPiiConfig=value) diff --git a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap.new b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap.new new file mode 100644 index 00000000000000..54122a511c92ea --- /dev/null +++ b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap.new @@ -0,0 +1,125 @@ +--- +created: '2023-10-02T11:41:08.185986Z' +creator: sentry +source: tests/sentry/relay/test_config.py +--- +config: + allowedDomains: + - '*' + breakdownsV2: + span_ops: + matches: + - http + - db + - browser + - resource + - ui + type: spanOperations + datascrubbingSettings: + excludeFields: [] + scrubData: true + scrubDefaults: true + sensitiveFields: [] + features: + - organizations:transaction-name-mark-scrubbed-as-sanitized + - organizations:transaction-name-normalize + filterSettings: + csp: + disallowedSources: + - about + - ms-browser-extension + - chrome://* + - chrome-extension://* + - chromeinvokeimmediate://* + - chromenull://* + - data:text/html,chromewebdata + - safari-extension://* + - mxaddon-pkg://* + - jar://* + - webviewprogressproxy://* + - ms-browser-extension://* + - tmtbff://* + - mbinit://* + - symres://* + - resource://* + - moz-extension://* + - '*.metrext.com' + - static.image2play.com + - '*.tlscdn.com' + - 73a5b0806e464be8bd4e694c744624f0.com + - 020dfefc4ac745dab7594f2f771c1ded.com + - '*.superfish.com' + - addons.mozilla.org + - v.zilionfast.in + - widgets.amung.us + - '*.superfish.com' + - xls.searchfun.in + - istatic.datafastguru.info + - v.zilionfast.in + - localhost + - resultshub-a.akamaihd.net + - pulseadnetwork.com + - gateway.zscalertwo.net + - www.passpack.com + - middlerush-a.akamaihd.net + - www.websmartcenter.com + - a.linkluster.com + - saveyoutime.ru + - cdncache-a.akamaihd.net + - x.rafomedia.com + - savingsslider-a.akamaihd.net + - injections.adguard.com + - icontent.us + - amiok.org + - connectionstrenth.com + - siteheart.net + - netanalitics.space + - printapplink.com + - godlinkapp.com + - devappstor.com + - hoholikik.club + - smartlink.cool + - promfflinkdev.com + errorMessages: + patterns: + - '*https://reactjs.org/docs/error-decoder.html?invariant={418,419,422,423,425}*' + - 'ChunkLoadError: Loading chunk * failed. (error: *)' + ignoreTransactions: + isEnabled: true + patterns: + - '*healthcheck*' + - '*healthy*' + - '*live*' + - '*ready*' + - '*heartbeat*' + - '*/health' + - '*/healthz' + - '*/ping' + groupingConfig: + enhancements: eJybzDRxc15qeXFJZU6qlZGBkbGugaGuoeEEAHJMCAM + id: newstyle:2023-01-11 + piiConfig: + applications: + $string: + - organization:remove_ips_and_macs + - project:remove_ips_and_macs + rules: + organization:remove_ips_and_macs: + redaction: + method: remove + rules: + - '@ip' + - '@mac' + type: multiple + project:remove_ips_and_macs: + redaction: + method: remove + rules: + - '@ip' + - '@mac' + type: multiple + spanAttributes: + - exclusive-time + trustedRelays: [] +disabled: false +slug: bar diff --git a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap.new b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap.new new file mode 100644 index 00000000000000..ac6131615f2fae --- /dev/null +++ b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap.new @@ -0,0 +1,125 @@ +--- +created: '2023-10-02T11:41:08.393725Z' +creator: sentry +source: tests/sentry/relay/test_config.py +--- +config: + allowedDomains: + - '*' + breakdownsV2: + span_ops: + matches: + - http + - db + - browser + - resource + - ui + type: spanOperations + datascrubbingSettings: + excludeFields: [] + scrubData: true + scrubDefaults: true + sensitiveFields: [] + features: + - organizations:transaction-name-mark-scrubbed-as-sanitized + - organizations:transaction-name-normalize + filterSettings: + csp: + disallowedSources: + - about + - ms-browser-extension + - chrome://* + - chrome-extension://* + - chromeinvokeimmediate://* + - chromenull://* + - data:text/html,chromewebdata + - safari-extension://* + - mxaddon-pkg://* + - jar://* + - webviewprogressproxy://* + - ms-browser-extension://* + - tmtbff://* + - mbinit://* + - symres://* + - resource://* + - moz-extension://* + - '*.metrext.com' + - static.image2play.com + - '*.tlscdn.com' + - 73a5b0806e464be8bd4e694c744624f0.com + - 020dfefc4ac745dab7594f2f771c1ded.com + - '*.superfish.com' + - addons.mozilla.org + - v.zilionfast.in + - widgets.amung.us + - '*.superfish.com' + - xls.searchfun.in + - istatic.datafastguru.info + - v.zilionfast.in + - localhost + - resultshub-a.akamaihd.net + - pulseadnetwork.com + - gateway.zscalertwo.net + - www.passpack.com + - middlerush-a.akamaihd.net + - www.websmartcenter.com + - a.linkluster.com + - saveyoutime.ru + - cdncache-a.akamaihd.net + - x.rafomedia.com + - savingsslider-a.akamaihd.net + - injections.adguard.com + - icontent.us + - amiok.org + - connectionstrenth.com + - siteheart.net + - netanalitics.space + - printapplink.com + - godlinkapp.com + - devappstor.com + - hoholikik.club + - smartlink.cool + - promfflinkdev.com + errorMessages: + patterns: + - '*https://reactjs.org/docs/error-decoder.html?invariant={418,419,422,423,425}*' + - 'ChunkLoadError: Loading chunk * failed. (error: *)' + ignoreTransactions: + isEnabled: true + patterns: + - '*healthcheck*' + - '*healthy*' + - '*live*' + - '*ready*' + - '*heartbeat*' + - '*/health' + - '*/healthz' + - '*/ping' + groupingConfig: + enhancements: eJybzDRxc15qeXFJZU6qlZGBkbGugaGuoeEEAHJMCAM + id: newstyle:2023-01-11 + piiConfig: + applications: + $string: + - organization:remove_ips_and_macs + - project:remove_ips_and_macs + rules: + organization:remove_ips_and_macs: + redaction: + method: remove + rules: + - '@ip' + - '@mac' + type: multiple + project:remove_ips_and_macs: + redaction: + method: remove + rules: + - '@ip' + - '@mac' + type: multiple + spanAttributes: + - exclusive-time + trustedRelays: [] +disabled: false +slug: bar diff --git a/tests/sentry/relay/test_config.py b/tests/sentry/relay/test_config.py index 9c2df8b5ef8185..7af95b32b6373d 100644 --- a/tests/sentry/relay/test_config.py +++ b/tests/sentry/relay/test_config.py @@ -179,6 +179,7 @@ def test_project_config_uses_filter_features( default_project.update_option("sentry:error_messages", error_messages) default_project.update_option("sentry:releases", releases) default_project.update_option("filters:react-hydration-errors", False) + default_project.update_option("filters:chunk-load-error", False) if has_blacklisted_ips: default_project.update_option("sentry:blacklisted_ips", blacklisted_ips) From ddb91b9a82e85a3508b264a221c285b736c11093 Mon Sep 17 00:00:00 2001 From: Riccardo Busetti Date: Mon, 2 Oct 2023 13:46:18 +0200 Subject: [PATCH 2/9] Fix snapshots --- .../full_config/MONOLITH.pysnap | 3 +- .../full_config/MONOLITH.pysnap.new | 125 ------------------ .../full_config/REGION.pysnap | 3 +- .../full_config/REGION.pysnap.new | 125 ------------------ 4 files changed, 4 insertions(+), 252 deletions(-) delete mode 100644 tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap.new delete mode 100644 tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap.new diff --git a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap index 04e9df6a6f928b..54122a511c92ea 100644 --- a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap +++ b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap @@ -1,5 +1,5 @@ --- -created: '2023-09-15T07:41:54.167449Z' +created: '2023-10-02T11:41:08.185986Z' creator: sentry source: tests/sentry/relay/test_config.py --- @@ -83,6 +83,7 @@ config: errorMessages: patterns: - '*https://reactjs.org/docs/error-decoder.html?invariant={418,419,422,423,425}*' + - 'ChunkLoadError: Loading chunk * failed. (error: *)' ignoreTransactions: isEnabled: true patterns: diff --git a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap.new b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap.new deleted file mode 100644 index 54122a511c92ea..00000000000000 --- a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap.new +++ /dev/null @@ -1,125 +0,0 @@ ---- -created: '2023-10-02T11:41:08.185986Z' -creator: sentry -source: tests/sentry/relay/test_config.py ---- -config: - allowedDomains: - - '*' - breakdownsV2: - span_ops: - matches: - - http - - db - - browser - - resource - - ui - type: spanOperations - datascrubbingSettings: - excludeFields: [] - scrubData: true - scrubDefaults: true - sensitiveFields: [] - features: - - organizations:transaction-name-mark-scrubbed-as-sanitized - - organizations:transaction-name-normalize - filterSettings: - csp: - disallowedSources: - - about - - ms-browser-extension - - chrome://* - - chrome-extension://* - - chromeinvokeimmediate://* - - chromenull://* - - data:text/html,chromewebdata - - safari-extension://* - - mxaddon-pkg://* - - jar://* - - webviewprogressproxy://* - - ms-browser-extension://* - - tmtbff://* - - mbinit://* - - symres://* - - resource://* - - moz-extension://* - - '*.metrext.com' - - static.image2play.com - - '*.tlscdn.com' - - 73a5b0806e464be8bd4e694c744624f0.com - - 020dfefc4ac745dab7594f2f771c1ded.com - - '*.superfish.com' - - addons.mozilla.org - - v.zilionfast.in - - widgets.amung.us - - '*.superfish.com' - - xls.searchfun.in - - istatic.datafastguru.info - - v.zilionfast.in - - localhost - - resultshub-a.akamaihd.net - - pulseadnetwork.com - - gateway.zscalertwo.net - - www.passpack.com - - middlerush-a.akamaihd.net - - www.websmartcenter.com - - a.linkluster.com - - saveyoutime.ru - - cdncache-a.akamaihd.net - - x.rafomedia.com - - savingsslider-a.akamaihd.net - - injections.adguard.com - - icontent.us - - amiok.org - - connectionstrenth.com - - siteheart.net - - netanalitics.space - - printapplink.com - - godlinkapp.com - - devappstor.com - - hoholikik.club - - smartlink.cool - - promfflinkdev.com - errorMessages: - patterns: - - '*https://reactjs.org/docs/error-decoder.html?invariant={418,419,422,423,425}*' - - 'ChunkLoadError: Loading chunk * failed. (error: *)' - ignoreTransactions: - isEnabled: true - patterns: - - '*healthcheck*' - - '*healthy*' - - '*live*' - - '*ready*' - - '*heartbeat*' - - '*/health' - - '*/healthz' - - '*/ping' - groupingConfig: - enhancements: eJybzDRxc15qeXFJZU6qlZGBkbGugaGuoeEEAHJMCAM - id: newstyle:2023-01-11 - piiConfig: - applications: - $string: - - organization:remove_ips_and_macs - - project:remove_ips_and_macs - rules: - organization:remove_ips_and_macs: - redaction: - method: remove - rules: - - '@ip' - - '@mac' - type: multiple - project:remove_ips_and_macs: - redaction: - method: remove - rules: - - '@ip' - - '@mac' - type: multiple - spanAttributes: - - exclusive-time - trustedRelays: [] -disabled: false -slug: bar diff --git a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap index 0cfa19b7f00cca..ac6131615f2fae 100644 --- a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap +++ b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap @@ -1,5 +1,5 @@ --- -created: '2023-09-15T07:41:54.637425Z' +created: '2023-10-02T11:41:08.393725Z' creator: sentry source: tests/sentry/relay/test_config.py --- @@ -83,6 +83,7 @@ config: errorMessages: patterns: - '*https://reactjs.org/docs/error-decoder.html?invariant={418,419,422,423,425}*' + - 'ChunkLoadError: Loading chunk * failed. (error: *)' ignoreTransactions: isEnabled: true patterns: diff --git a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap.new b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap.new deleted file mode 100644 index ac6131615f2fae..00000000000000 --- a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap.new +++ /dev/null @@ -1,125 +0,0 @@ ---- -created: '2023-10-02T11:41:08.393725Z' -creator: sentry -source: tests/sentry/relay/test_config.py ---- -config: - allowedDomains: - - '*' - breakdownsV2: - span_ops: - matches: - - http - - db - - browser - - resource - - ui - type: spanOperations - datascrubbingSettings: - excludeFields: [] - scrubData: true - scrubDefaults: true - sensitiveFields: [] - features: - - organizations:transaction-name-mark-scrubbed-as-sanitized - - organizations:transaction-name-normalize - filterSettings: - csp: - disallowedSources: - - about - - ms-browser-extension - - chrome://* - - chrome-extension://* - - chromeinvokeimmediate://* - - chromenull://* - - data:text/html,chromewebdata - - safari-extension://* - - mxaddon-pkg://* - - jar://* - - webviewprogressproxy://* - - ms-browser-extension://* - - tmtbff://* - - mbinit://* - - symres://* - - resource://* - - moz-extension://* - - '*.metrext.com' - - static.image2play.com - - '*.tlscdn.com' - - 73a5b0806e464be8bd4e694c744624f0.com - - 020dfefc4ac745dab7594f2f771c1ded.com - - '*.superfish.com' - - addons.mozilla.org - - v.zilionfast.in - - widgets.amung.us - - '*.superfish.com' - - xls.searchfun.in - - istatic.datafastguru.info - - v.zilionfast.in - - localhost - - resultshub-a.akamaihd.net - - pulseadnetwork.com - - gateway.zscalertwo.net - - www.passpack.com - - middlerush-a.akamaihd.net - - www.websmartcenter.com - - a.linkluster.com - - saveyoutime.ru - - cdncache-a.akamaihd.net - - x.rafomedia.com - - savingsslider-a.akamaihd.net - - injections.adguard.com - - icontent.us - - amiok.org - - connectionstrenth.com - - siteheart.net - - netanalitics.space - - printapplink.com - - godlinkapp.com - - devappstor.com - - hoholikik.club - - smartlink.cool - - promfflinkdev.com - errorMessages: - patterns: - - '*https://reactjs.org/docs/error-decoder.html?invariant={418,419,422,423,425}*' - - 'ChunkLoadError: Loading chunk * failed. (error: *)' - ignoreTransactions: - isEnabled: true - patterns: - - '*healthcheck*' - - '*healthy*' - - '*live*' - - '*ready*' - - '*heartbeat*' - - '*/health' - - '*/healthz' - - '*/ping' - groupingConfig: - enhancements: eJybzDRxc15qeXFJZU6qlZGBkbGugaGuoeEEAHJMCAM - id: newstyle:2023-01-11 - piiConfig: - applications: - $string: - - organization:remove_ips_and_macs - - project:remove_ips_and_macs - rules: - organization:remove_ips_and_macs: - redaction: - method: remove - rules: - - '@ip' - - '@mac' - type: multiple - project:remove_ips_and_macs: - redaction: - method: remove - rules: - - '@ip' - - '@mac' - type: multiple - spanAttributes: - - exclusive-time - trustedRelays: [] -disabled: false -slug: bar From 862acfe3716d08d48cf0498f61554c86d18aa376 Mon Sep 17 00:00:00 2001 From: Riccardo Busetti Date: Mon, 2 Oct 2023 14:39:55 +0200 Subject: [PATCH 3/9] fiX --- src/sentry/relay/config/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sentry/relay/config/__init__.py b/src/sentry/relay/config/__init__.py index 103796dc7e1b3d..f2f501e9225ce0 100644 --- a/src/sentry/relay/config/__init__.py +++ b/src/sentry/relay/config/__init__.py @@ -148,8 +148,8 @@ def get_filter_settings(project: Project) -> Mapping[str, Any]: enable_chunk_upload_error_filter = project.get_option("filters:chunk-load-error") if enable_chunk_upload_error_filter: - # ChunkLoadError: Loading chunk 3662 failed. (error: https://xxx.com/_next/static/chunks/29107295-0151559bd23117ba.js) - error_messages += ["ChunkLoadError: Loading chunk * failed. (error: *)"] + # ChunkLoadError: Loading chunk 3662 failed.\n(error: https://xxx.com/_next/static/chunks/29107295-0151559bd23117ba.js) + error_messages += ["ChunkLoadError: Loading chunk * failed.\n(error: *)"] if error_messages: filter_settings["errorMessages"] = {"patterns": error_messages} From 7949be9c17ab02bf549fca2c538046e82d6f33d0 Mon Sep 17 00:00:00 2001 From: Riccardo Busetti Date: Mon, 2 Oct 2023 14:41:53 +0200 Subject: [PATCH 4/9] fiX --- .../test_get_project_config/full_config/MONOLITH.pysnap | 2 +- .../test_get_project_config/full_config/REGION.pysnap | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap index 54122a511c92ea..7ab572febffbd1 100644 --- a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap +++ b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap @@ -83,7 +83,7 @@ config: errorMessages: patterns: - '*https://reactjs.org/docs/error-decoder.html?invariant={418,419,422,423,425}*' - - 'ChunkLoadError: Loading chunk * failed. (error: *)' + - 'ChunkLoadError: Loading chunk * failed.\n(error: *)' ignoreTransactions: isEnabled: true patterns: diff --git a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap index ac6131615f2fae..6f5f8bbd42a22f 100644 --- a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap +++ b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap @@ -83,7 +83,7 @@ config: errorMessages: patterns: - '*https://reactjs.org/docs/error-decoder.html?invariant={418,419,422,423,425}*' - - 'ChunkLoadError: Loading chunk * failed. (error: *)' + - 'ChunkLoadError: Loading chunk * failed.\n(error: *)' ignoreTransactions: isEnabled: true patterns: From 773f2d49bbfd01f5249e1bde7e4bef1c5d4093ff Mon Sep 17 00:00:00 2001 From: Riccardo Busetti Date: Mon, 2 Oct 2023 15:11:12 +0200 Subject: [PATCH 5/9] Fix --- .../test_get_project_config/full_config/MONOLITH.pysnap | 4 +++- .../test_get_project_config/full_config/REGION.pysnap | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap index 7ab572febffbd1..ae681b336f4fa3 100644 --- a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap +++ b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/MONOLITH.pysnap @@ -83,7 +83,9 @@ config: errorMessages: patterns: - '*https://reactjs.org/docs/error-decoder.html?invariant={418,419,422,423,425}*' - - 'ChunkLoadError: Loading chunk * failed.\n(error: *)' + - 'ChunkLoadError: Loading chunk * failed. + + (error: *)' ignoreTransactions: isEnabled: true patterns: diff --git a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap index 6f5f8bbd42a22f..b0f223413f55f2 100644 --- a/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap +++ b/tests/sentry/relay/snapshots/test_config/test_get_project_config/full_config/REGION.pysnap @@ -83,7 +83,9 @@ config: errorMessages: patterns: - '*https://reactjs.org/docs/error-decoder.html?invariant={418,419,422,423,425}*' - - 'ChunkLoadError: Loading chunk * failed.\n(error: *)' + - 'ChunkLoadError: Loading chunk * failed. + + (error: *)' ignoreTransactions: isEnabled: true patterns: From df9c8b3ecbd8738664878223301dea18b7908227 Mon Sep 17 00:00:00 2001 From: Riccardo Busetti Date: Mon, 2 Oct 2023 16:03:39 +0200 Subject: [PATCH 6/9] Add tests --- .../api/endpoints/test_project_details.py | 5 ----- tests/sentry/relay/test_config.py | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/tests/sentry/api/endpoints/test_project_details.py b/tests/sentry/api/endpoints/test_project_details.py index fc85523d13996a..5f45ea591e3dc7 100644 --- a/tests/sentry/api/endpoints/test_project_details.py +++ b/tests/sentry/api/endpoints/test_project_details.py @@ -717,11 +717,6 @@ def test_options(self): event=audit_log.get_event_id("PROJECT_EDIT"), ).exists() assert project.get_option("filters:react-hydration-errors", "1") - with assume_test_silo_mode(SiloMode.CONTROL): - assert AuditLogEntry.objects.filter( - organization_id=project.organization_id, - event=audit_log.get_event_id("PROJECT_EDIT"), - ).exists() assert project.get_option("filters:chunk-load-error", "1") def test_bookmarks(self): diff --git a/tests/sentry/relay/test_config.py b/tests/sentry/relay/test_config.py index 7af95b32b6373d..ae4e21b8c3ad12 100644 --- a/tests/sentry/relay/test_config.py +++ b/tests/sentry/relay/test_config.py @@ -206,6 +206,23 @@ def test_project_config_uses_filter_features( assert cfg_client_ips is None +@django_db_all +@region_silo_test(stable=True) +def test_project_config_with_chunk_load_error_filter(default_project): + default_project.update_option("filters:react-hydration-errors", False) + default_project.update_option("filters:chunk-load-error", True) + + project_cfg = get_project_config(default_project, full_config=True) + + cfg = project_cfg.to_dict() + _validate_project_config(cfg["config"]) + cfg_error_messages = get_path(cfg, "config", "filterSettings", "errorMessages") + + assert cfg_error_messages == { + "patterns": ["ChunkLoadError: Loading chunk * failed.\n(error: *)"] + } + + @django_db_all @region_silo_test(stable=True) @mock.patch("sentry.relay.config.EXPOSABLE_FEATURES", ["organizations:profiling"]) From eeb0c9a03b14a052ff5c8487387a25671d1aff79 Mon Sep 17 00:00:00 2001 From: Riccardo Busetti Date: Tue, 3 Oct 2023 16:06:54 +0200 Subject: [PATCH 7/9] Use 0 and 1 instead of bools --- src/sentry/api/endpoints/project_details.py | 2 +- src/sentry/api/serializers/models/project.py | 2 +- src/sentry/relay/config/__init__.py | 8 +++++--- tests/sentry/api/endpoints/test_project_details.py | 12 ++++++++---- tests/sentry/relay/test_config.py | 10 +++++----- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/sentry/api/endpoints/project_details.py b/src/sentry/api/endpoints/project_details.py index 88e96a2a7015a7..62ede4b919d27b 100644 --- a/src/sentry/api/endpoints/project_details.py +++ b/src/sentry/api/endpoints/project_details.py @@ -814,7 +814,7 @@ def put(self, request: Request, project) -> Response: if "filters:chunk-load-error" in options: project.update_option( "filters:chunk-load-error", - bool(options["filters:chunk-load-error"]), + "1" if bool(options["filters:chunk-load-error"]) else "0", ) if "filters:blacklisted_ips" in options: project.update_option( diff --git a/src/sentry/api/serializers/models/project.py b/src/sentry/api/serializers/models/project.py index cdd317515810a1..ff0fb92779e08d 100644 --- a/src/sentry/api/serializers/models/project.py +++ b/src/sentry/api/serializers/models/project.py @@ -216,7 +216,7 @@ def format_options(attrs: dict[str, Any]) -> dict[str, Any]: "sentry:reprocessing_active": bool(options.get("sentry:reprocessing_active", False)), "filters:blacklisted_ips": "\n".join(options.get("sentry:blacklisted_ips", [])), "filters:react-hydration-errors": bool(options.get("filters:react-hydration-errors", True)), - "filters:chunk-load-error": bool(options.get("filters:chunk-load-error", True)), + "filters:chunk-load-error": options.get("filters:chunk-load-error", "1") == "1", f"filters:{FilterTypes.RELEASES}": "\n".join( options.get(f"sentry:{FilterTypes.RELEASES}", []) ), diff --git a/src/sentry/relay/config/__init__.py b/src/sentry/relay/config/__init__.py index f2f501e9225ce0..bf1f118fd79754 100644 --- a/src/sentry/relay/config/__init__.py +++ b/src/sentry/relay/config/__init__.py @@ -135,6 +135,8 @@ def get_filter_settings(project: Project) -> Mapping[str, Any]: error_messages += project.get_option(f"sentry:{FilterTypes.ERROR_MESSAGES}") or [] + # TODO: refactor the system to allow management of error messages filtering via the inbound filters, since right + # now the system maps an option to a single top-level filter like "ignoreTransactions". enable_react = project.get_option("filters:react-hydration-errors") if enable_react: # 418 - Hydration failed because the initial UI does not match what was rendered on the server. @@ -146,9 +148,9 @@ def get_filter_settings(project: Project) -> Mapping[str, Any]: "*https://reactjs.org/docs/error-decoder.html?invariant={418,419,422,423,425}*" ] - enable_chunk_upload_error_filter = project.get_option("filters:chunk-load-error") - if enable_chunk_upload_error_filter: - # ChunkLoadError: Loading chunk 3662 failed.\n(error: https://xxx.com/_next/static/chunks/29107295-0151559bd23117ba.js) + if project.get_option("filters:chunk-load-error") == "1": + # ChunkLoadError: Loading chunk 3662 failed.\n(error: + # https://xxx.com/_next/static/chunks/29107295-0151559bd23117ba.js) error_messages += ["ChunkLoadError: Loading chunk * failed.\n(error: *)"] if error_messages: diff --git a/tests/sentry/api/endpoints/test_project_details.py b/tests/sentry/api/endpoints/test_project_details.py index 5f45ea591e3dc7..655e3afa1c94cd 100644 --- a/tests/sentry/api/endpoints/test_project_details.py +++ b/tests/sentry/api/endpoints/test_project_details.py @@ -858,11 +858,15 @@ def test_react_hydration_errors(self): assert resp.data["options"]["filters:react-hydration-errors"] == value def test_chunk_load_error(self): - value = False - options = {"filters:chunk-load-error": value} + options = {"filters:chunk-load-error": False} + resp = self.get_success_response(self.org_slug, self.proj_slug, options=options) + assert self.project.get_option("filters:chunk-load-error") == "0" + assert resp.data["options"]["filters:chunk-load-error"] is False + + options = {"filters:chunk-load-error": True} resp = self.get_success_response(self.org_slug, self.proj_slug, options=options) - assert self.project.get_option("filters:chunk-load-error") == value - assert resp.data["options"]["filters:chunk-load-error"] == value + assert self.project.get_option("filters:chunk-load-error") == "1" + assert resp.data["options"]["filters:chunk-load-error"] is True def test_relay_pii_config(self): value = '{"applications": {"freeform": []}}' diff --git a/tests/sentry/relay/test_config.py b/tests/sentry/relay/test_config.py index ae4e21b8c3ad12..f4de2f12f276db 100644 --- a/tests/sentry/relay/test_config.py +++ b/tests/sentry/relay/test_config.py @@ -179,7 +179,7 @@ def test_project_config_uses_filter_features( default_project.update_option("sentry:error_messages", error_messages) default_project.update_option("sentry:releases", releases) default_project.update_option("filters:react-hydration-errors", False) - default_project.update_option("filters:chunk-load-error", False) + default_project.update_option("filters:chunk-load-error", "0") if has_blacklisted_ips: default_project.update_option("sentry:blacklisted_ips", blacklisted_ips) @@ -209,8 +209,10 @@ def test_project_config_uses_filter_features( @django_db_all @region_silo_test(stable=True) def test_project_config_with_chunk_load_error_filter(default_project): + # The react-hydration-errors option is set as string in the defaults but then its changed as a boolean in the + # options endpoint, which is something that should be changed. default_project.update_option("filters:react-hydration-errors", False) - default_project.update_option("filters:chunk-load-error", True) + default_project.update_option("filters:chunk-load-error", "1") project_cfg = get_project_config(default_project, full_config=True) @@ -218,9 +220,7 @@ def test_project_config_with_chunk_load_error_filter(default_project): _validate_project_config(cfg["config"]) cfg_error_messages = get_path(cfg, "config", "filterSettings", "errorMessages") - assert cfg_error_messages == { - "patterns": ["ChunkLoadError: Loading chunk * failed.\n(error: *)"] - } + assert len(cfg_error_messages) == 1 @django_db_all From 2ba796942229024ac30b885051d64c900b71090e Mon Sep 17 00:00:00 2001 From: Riccardo Busetti Date: Mon, 2 Oct 2023 14:21:55 +0200 Subject: [PATCH 8/9] feat(inbound-filters): Add UI toggle for ChunkLoadError inbound filter --- .../projectFilters/projectFiltersSettings.tsx | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/static/app/views/settings/project/projectFilters/projectFiltersSettings.tsx b/static/app/views/settings/project/projectFilters/projectFiltersSettings.tsx index 66776f364051c8..a4b9dc08dbd713 100644 --- a/static/app/views/settings/project/projectFilters/projectFiltersSettings.tsx +++ b/static/app/views/settings/project/projectFilters/projectFiltersSettings.tsx @@ -433,6 +433,33 @@ export function ProjectFiltersSettings({project, params, features}: Props) { /> + + ProjectsStore.onUpdateSuccess(response)} + > + + + From f26ebb976304e766df6cb10d77eeaf327ccffd72 Mon Sep 17 00:00:00 2001 From: Riccardo Busetti Date: Mon, 2 Oct 2023 14:30:15 +0200 Subject: [PATCH 9/9] Fix --- .../project/projectFilters/projectFiltersSettings.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static/app/views/settings/project/projectFilters/projectFiltersSettings.tsx b/static/app/views/settings/project/projectFilters/projectFiltersSettings.tsx index a4b9dc08dbd713..acda85ab7051b8 100644 --- a/static/app/views/settings/project/projectFilters/projectFiltersSettings.tsx +++ b/static/app/views/settings/project/projectFilters/projectFiltersSettings.tsx @@ -451,9 +451,9 @@ export function ProjectFiltersSettings({project, params, features}: Props) { field={{ type: 'boolean', name: 'filters:chunk-load-error', - label: t('Filter out chunk load errors'), + label: t('Filter out ChunkLoadError(s)'), help: t( - 'In NextJS, chunk load errors can occur due to caching split chunks of the JavaScript bundle.' + 'It can happen that in full automatic deploy environments like Next.js & Vercel the frontend gets out of sync with the backend which results in a ChunkLoadError. The application refreshes and everything should work as expected.' ), disabled: !hasAccess, }}