From ecfbeb1b45f41028400721ffbbe5e4fd22f186c8 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Feb 2023 15:15:46 +0100 Subject: [PATCH 1/8] feat(loader): Add new dynamic cdn options to js loader --- .../api/endpoints/project_docs_platform.py | 4 - .../api/serializers/models/project_key.py | 1 - src/sentry/models/projectkey.py | 11 -- .../web/frontend/js_sdk_dynamic_loader.py | 105 ------------------ src/sentry/web/frontend/js_sdk_loader.py | 53 +++++++-- src/sentry/web/urls.py | 7 -- tests/sentry/models/test_projectkey.py | 13 --- .../frontend/test_js_sdk_dynamic_loader.py | 41 ------- .../sentry/web/frontend/test_js_sdk_loader.py | 85 ++++++++++++++ 9 files changed, 131 insertions(+), 189 deletions(-) delete mode 100644 src/sentry/web/frontend/js_sdk_dynamic_loader.py delete mode 100644 tests/sentry/web/frontend/test_js_sdk_dynamic_loader.py diff --git a/src/sentry/api/endpoints/project_docs_platform.py b/src/sentry/api/endpoints/project_docs_platform.py index 1636e4daf28d09..07d906be77ffb5 100644 --- a/src/sentry/api/endpoints/project_docs_platform.py +++ b/src/sentry/api/endpoints/project_docs_platform.py @@ -24,10 +24,6 @@ def replace_keys(html, project_key): "___RELAY_CDN_URL___", absolute_uri(reverse("sentry-js-sdk-loader", args=[project_key.public_key])), ) - html = html.replace( - "___RELAY_DYNAMIC_CDN_URL___", - absolute_uri(reverse("sentry-js-sdk-dynamic-loader", args=[project_key.public_key])), - ) # If we actually render this in the main UI we can also provide # extra information about the project (org slug and project slug) diff --git a/src/sentry/api/serializers/models/project_key.py b/src/sentry/api/serializers/models/project_key.py index d33abc8f960422..ebc3a7adf3ab1f 100644 --- a/src/sentry/api/serializers/models/project_key.py +++ b/src/sentry/api/serializers/models/project_key.py @@ -31,7 +31,6 @@ def serialize(self, obj, attrs, user): "minidump": obj.minidump_endpoint, "unreal": obj.unreal_endpoint, "cdn": obj.js_sdk_loader_cdn_url, - "dynamicCdn": obj.js_sdk_dynamic_loader_cdn_url, }, "browserSdkVersion": get_selected_browser_sdk_version(obj), "browserSdk": {"choices": get_browser_sdk_version_choices()}, diff --git a/src/sentry/models/projectkey.py b/src/sentry/models/projectkey.py index b76c733ba07e20..2411144a2e2abc 100644 --- a/src/sentry/models/projectkey.py +++ b/src/sentry/models/projectkey.py @@ -237,17 +237,6 @@ def js_sdk_loader_cdn_url(self) -> str: reverse("sentry-js-sdk-loader", args=[self.public_key, ".min"]), ) - @property - def js_sdk_dynamic_loader_cdn_url(self) -> str: - if settings.JS_SDK_LOADER_CDN_URL: - return f"{settings.JS_SDK_LOADER_CDN_URL}dynamic/{self.public_key}.min.js" - else: - endpoint = self.get_endpoint() - return "{}{}".format( - endpoint, - reverse("sentry-js-sdk-dynamic-loader", args=[self.public_key, ".min"]), - ) - def get_endpoint(self, public=True): if public: endpoint = settings.SENTRY_PUBLIC_ENDPOINT or settings.SENTRY_ENDPOINT diff --git a/src/sentry/web/frontend/js_sdk_dynamic_loader.py b/src/sentry/web/frontend/js_sdk_dynamic_loader.py deleted file mode 100644 index a7ef17509e0ac6..00000000000000 --- a/src/sentry/web/frontend/js_sdk_dynamic_loader.py +++ /dev/null @@ -1,105 +0,0 @@ -from typing import Optional, Tuple, TypedDict - -from django.conf import settings -from rest_framework.request import Request -from rest_framework.response import Response - -from sentry.loader.browsersdkversion import get_browser_sdk_version -from sentry.loader.dynamic_sdk_options import DynamicSdkLoaderOption, get_dynamic_sdk_loader_option -from sentry.models import Project, ProjectKey -from sentry.web.frontend.base import BaseView -from sentry.web.helpers import render_to_response - -CACHE_CONTROL = ( - "public, max-age=3600, s-maxage=60, stale-while-revalidate=315360000, stale-if-error=315360000" -) - - -class SdkConfig(TypedDict): - dsn: str - - -class LoaderContext(TypedDict): - config: SdkConfig - jsSdkUrl: Optional[str] - publicKey: Optional[str] - - -class JavaScriptSdkDynamicLoader(BaseView): - auth_required = False - - # Do not let an organization load trigger session, breaking Vary header. - # TODO: This view should probably not be a subclass of BaseView if it doesn't actually use the - # large amount of organization related support utilities, but that ends up being a large refactor. - def determine_active_organization(self, request: Request, organization_slug=None) -> None: - pass - - def _get_context(self, key: ProjectKey) -> Tuple[LoaderContext, Optional[str], Optional[str]]: - """Sets context information needed to render the loader""" - if not key: - return ({}, None, None) - - sdk_version = get_browser_sdk_version(key) - - bundle_kind_modifier = self._get_bundle_kind_modifier(key) - - sdk_url = "" - try: - sdk_url = settings.JS_SDK_LOADER_DEFAULT_SDK_URL % (sdk_version, bundle_kind_modifier) - except TypeError: - sdk_url = "" # It fails if it cannot inject the version in the string - - return ( - { - "config": { - "dsn": key.dsn_public, - "jsSdkUrl": sdk_url, - "publicKey": key.public_key, - } - }, - sdk_version, - sdk_url, - ) - - def _get_bundle_kind_modifier(self, key: ProjectKey) -> str: - """Returns a string that is used to modify the bundle name""" - bundle_kind_modifier = "" - - if get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_PERFORMANCE): - bundle_kind_modifier += ".tracing" - - if get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_REPLAY): - bundle_kind_modifier += ".replay" - - # TODO(abhi): Right now this loader only supports returning es6 JS bundles. - # We may want to re-evaluate this. - # if es5 - # bundle_kind_modifier += ".es5" - - if get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_DEBUG): - bundle_kind_modifier += ".debug" - - return bundle_kind_modifier - - def get(self, request: Request, public_key: str, minified: str) -> Response: - """Returns a JS file that dynamically loads the SDK based on project settings""" - key = None - try: - key = ProjectKey.objects.get_from_cache(public_key=public_key) - except ProjectKey.DoesNotExist: - pass - else: - key.project = Project.objects.get_from_cache(id=key.project_id) - - # TODO(abhi): Return more than no-op template - tmpl = "sentry/js-sdk-loader-noop.js.tmpl" - - context, sdk_version, sdk_url = self._get_context(key) - - response = render_to_response(tmpl, context, content_type="text/javascript") - - response["Access-Control-Allow-Origin"] = "*" - response["Cross-Origin-Resource-Policy"] = "cross-origin" - response["Cache-Control"] = CACHE_CONTROL - - return response diff --git a/src/sentry/web/frontend/js_sdk_loader.py b/src/sentry/web/frontend/js_sdk_loader.py index 7b81b3f895b66b..e300fbeab4ec35 100644 --- a/src/sentry/web/frontend/js_sdk_loader.py +++ b/src/sentry/web/frontend/js_sdk_loader.py @@ -1,4 +1,5 @@ import time +from typing import Optional, Tuple, TypedDict from django.conf import settings from packaging.version import Version @@ -6,6 +7,7 @@ from rest_framework.response import Response from sentry.loader.browsersdkversion import get_browser_sdk_version +from sentry.loader.dynamic_sdk_options import DynamicSdkLoaderOption, get_dynamic_sdk_loader_option from sentry.models import Project, ProjectKey from sentry.utils import metrics from sentry.web.frontend.base import BaseView @@ -16,6 +18,16 @@ ) +class SdkConfig(TypedDict): + dsn: str + + +class LoaderContext(TypedDict): + config: SdkConfig + jsSdkUrl: Optional[str] + publicKey: Optional[str] + + class JavaScriptSdkLoader(BaseView): auth_required = False @@ -25,18 +37,45 @@ class JavaScriptSdkLoader(BaseView): def determine_active_organization(self, request: Request, organization_slug=None) -> None: pass - def _get_context(self, key): + def _get_bundle_kind_modifier(self, key: ProjectKey, sdk_version: str) -> str: + """Returns a string that is used to modify the bundle name""" + bundle_kind_modifier = "" + + # The order in which these modifiers are added is important, as the + # bundle name is built up from left to right. + # https://docs.sentry.io/platforms/javascript/install/cdn/ + + if get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_PERFORMANCE): + bundle_kind_modifier += ".tracing" + + has_replay = get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_REPLAY) + + if has_replay: + bundle_kind_modifier += ".replay" + + # From JavaScript SDK version 7 onwards, the default bundle code is ES6, however, in the loader we + # want to provide the ES5 version. This is why we need to modify the requested bundle name here. + # + # If we are loading replay, do not add the es5 modifier, as those bundles are + # ES6 only. + if sdk_version >= Version("7.0.0") and not has_replay: + bundle_kind_modifier += ".es5" + + if get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_DEBUG): + bundle_kind_modifier += ".debug" + + return bundle_kind_modifier + + def _get_context( + self, key: Optional[ProjectKey] + ) -> Tuple[LoaderContext, Optional[str], Optional[str]]: """Sets context information needed to render the loader""" if not key: return ({}, None, None) sdk_version = get_browser_sdk_version(key) - # From JavaScript SDK version 7 onwards, the default bundle code is ES6, however, in the loader we - # want to provide the ES5 version. This is why we need to modify the requested bundle name here. - bundle_kind_modifier = "" - if sdk_version >= Version("7.0.0"): - bundle_kind_modifier = ".es5" + bundle_kind_modifier = self._get_bundle_kind_modifier(key, sdk_version) js_sdk_loader_default_sdk_url_template_slot_count = ( settings.JS_SDK_LOADER_DEFAULT_SDK_URL.count("%s") @@ -65,7 +104,7 @@ def _get_context(self, key): sdk_url, ) - def get(self, request: Request, public_key, minified) -> Response: + def get(self, request: Request, public_key: Optional[str], minified: Optional[str]) -> Response: """Returns a js file that can be integrated into a website""" start_time = time.time() key = None diff --git a/src/sentry/web/urls.py b/src/sentry/web/urls.py index 0354b4882a3b18..6421367f3ed54f 100644 --- a/src/sentry/web/urls.py +++ b/src/sentry/web/urls.py @@ -23,7 +23,6 @@ from sentry.web.frontend.group_tag_export import GroupTagExportView from sentry.web.frontend.home import HomeView from sentry.web.frontend.idp_email_verification import AccountConfirmationView -from sentry.web.frontend.js_sdk_dynamic_loader import JavaScriptSdkDynamicLoader from sentry.web.frontend.js_sdk_loader import JavaScriptSdkLoader from sentry.web.frontend.mailgun_inbound_webhook import MailgunInboundWebhookView from sentry.web.frontend.newest_performance_issue import NewestPerformanceIssueView @@ -117,12 +116,6 @@ JavaScriptSdkLoader.as_view(), name="sentry-js-sdk-loader", ), - # JavaScript SDK Dynamic Loader - url( - r"^js-sdk-loader/dynamic/(?P[^/\.]+)(?:(?P\.min))?\.js$", - JavaScriptSdkDynamicLoader.as_view(), - name="sentry-js-sdk-dynamic-loader", - ), # Versioned API url(r"^api/0/", include("sentry.api.urls")), # Legacy unversioned endpoints diff --git a/tests/sentry/models/test_projectkey.py b/tests/sentry/models/test_projectkey.py index 9c041cf1476244..d303cf49b0960d 100644 --- a/tests/sentry/models/test_projectkey.py +++ b/tests/sentry/models/test_projectkey.py @@ -76,19 +76,6 @@ def test_get_dsn(self): assert key.minidump_endpoint == "http://testserver/api/1/minidump/?sentry_key=abc" assert key.unreal_endpoint == "http://testserver/api/1/unreal/abc/" assert key.js_sdk_loader_cdn_url == "http://testserver/js-sdk-loader/abc.min.js" - assert ( - key.js_sdk_dynamic_loader_cdn_url - == "http://testserver/js-sdk-loader/dynamic/abc.min.js" - ) - - def test_get_js_sdk_dynamic_loader_cdn_url_from_settings(self): - key = self.model(project_id=1, public_key="abc", secret_key="xyz") - - with self.settings(JS_SDK_LOADER_CDN_URL="https://sentry-best-cdn.com/"): - assert ( - key.js_sdk_dynamic_loader_cdn_url - == "https://sentry-best-cdn.com/dynamic/abc.min.js" - ) def test_get_dsn_org_subdomain(self): with self.feature("organizations:org-subdomains"): diff --git a/tests/sentry/web/frontend/test_js_sdk_dynamic_loader.py b/tests/sentry/web/frontend/test_js_sdk_dynamic_loader.py deleted file mode 100644 index 7fcb238f03cb85..00000000000000 --- a/tests/sentry/web/frontend/test_js_sdk_dynamic_loader.py +++ /dev/null @@ -1,41 +0,0 @@ -from functools import cached_property - -import pytest -from django.conf import settings -from django.urls import reverse - -from sentry.testutils import TestCase - - -class JavaScriptSdkLoaderTest(TestCase): - @pytest.fixture(autouse=True) - def set_settings(self): - settings.JS_SDK_LOADER_SDK_VERSION = "0.5.2" - settings.JS_SDK_LOADER_DEFAULT_SDK_URL = "https://browser.sentry-cdn.com/%s/bundle%s.min.js" - - @cached_property - def path(self): - return reverse("sentry-js-sdk-dynamic-loader", args=[self.projectkey.public_key]) - - def test_noop_no_pub_key(self): - resp = self.client.get(reverse("sentry-js-sdk-dynamic-loader", args=["abc"])) - assert resp.status_code == 200 - self.assertTemplateUsed(resp, "sentry/js-sdk-loader-noop.js.tmpl") - - def test_noop(self): - settings.JS_SDK_LOADER_DEFAULT_SDK_URL = "" - resp = self.client.get( - reverse("sentry-js-sdk-dynamic-loader", args=[self.projectkey.public_key]) - ) - assert resp.status_code == 200 - self.assertTemplateUsed(resp, "sentry/js-sdk-loader-noop.js.tmpl") - - def test_absolute_url(self): - assert ( - reverse("sentry-js-sdk-dynamic-loader", args=[self.projectkey.public_key, ".min"]) - in self.projectkey.js_sdk_dynamic_loader_cdn_url - ) - settings.JS_SDK_LOADER_CDN_URL = "https://js.sentry-cdn.com/" - assert ( - "https://js.sentry-cdn.com/dynamic/%s.min.js" % self.projectkey.public_key - ) == self.projectkey.js_sdk_dynamic_loader_cdn_url diff --git a/tests/sentry/web/frontend/test_js_sdk_loader.py b/tests/sentry/web/frontend/test_js_sdk_loader.py index 29468d630987ee..6b23329496114e 100644 --- a/tests/sentry/web/frontend/test_js_sdk_loader.py +++ b/tests/sentry/web/frontend/test_js_sdk_loader.py @@ -6,10 +6,15 @@ from django.conf import settings from django.urls import reverse +from sentry.loader.dynamic_sdk_options import DynamicSdkLoaderOption from sentry.testutils import TestCase class JavaScriptSdkLoaderTest(TestCase): + # def setUp(self): + # self.project = self.create_project() + # self.project_key = self.create_project_key(project=self.project) + @pytest.fixture(autouse=True) def set_settings(self): settings.JS_SDK_LOADER_SDK_VERSION = "0.5.2" @@ -104,6 +109,86 @@ def test_greater_than_v7_returns_es5( self.assertTemplateUsed(resp, "sentry/js-sdk-loader.js.tmpl") assert b"/8.3.15/bundle.es5.min.js" in resp.content + @mock.patch("sentry.loader.browsersdkversion.load_version_from_file", return_value=["7.37.0"]) + @mock.patch( + "sentry.loader.browsersdkversion.get_selected_browser_sdk_version", return_value="latest" + ) + def test_bundle_kind_modifiers(self, load_version_from_file, get_selected_browser_sdk_version): + settings.JS_SDK_LOADER_DEFAULT_SDK_URL = "https://browser.sentry-cdn.com/%s/bundle%s.min.js" + settings.JS_SDK_LOADER_SDK_VERSION = "7.32.0" + + for data, expected in [ + ( + { + "dynamicSdkLoaderOptions": { + DynamicSdkLoaderOption.HAS_PERFORMANCE.value: True, + } + }, + b"/7.37.0/bundle.tracing.es5.min.js", + ), + ( + { + "dynamicSdkLoaderOptions": { + DynamicSdkLoaderOption.HAS_DEBUG.value: True, + } + }, + b"/7.37.0/bundle.es5.debug.min.js", + ), + ( + { + "dynamicSdkLoaderOptions": { + DynamicSdkLoaderOption.HAS_REPLAY.value: True, + } + }, + b"/7.37.0/bundle.replay.min.js", + ), + ( + { + "dynamicSdkLoaderOptions": { + DynamicSdkLoaderOption.HAS_PERFORMANCE.value: True, + DynamicSdkLoaderOption.HAS_REPLAY.value: True, + } + }, + b"/7.37.0/bundle.tracing.replay.min.js", + ), + ( + { + "dynamicSdkLoaderOptions": { + DynamicSdkLoaderOption.HAS_REPLAY.value: True, + DynamicSdkLoaderOption.HAS_DEBUG.value: True, + } + }, + b"/7.37.0/bundle.replay.debug.min.js", + ), + ( + { + "dynamicSdkLoaderOptions": { + DynamicSdkLoaderOption.HAS_PERFORMANCE.value: True, + DynamicSdkLoaderOption.HAS_DEBUG.value: True, + } + }, + b"/7.37.0/bundle.tracing.es5.debug.min.js", + ), + ( + { + "dynamicSdkLoaderOptions": { + DynamicSdkLoaderOption.HAS_PERFORMANCE.value: True, + DynamicSdkLoaderOption.HAS_DEBUG.value: True, + DynamicSdkLoaderOption.HAS_REPLAY.value: True, + } + }, + b"/7.37.0/bundle.tracing.replay.debug.min.js", + ), + ]: + self.projectkey.data = data + self.projectkey.save() + resp = self.client.get(self.path) + assert resp.status_code == 200 + self.assertTemplateUsed(resp, "sentry/js-sdk-loader.js.tmpl") + assert expected in resp.content + self.projectkey.data = {} + self.projectkey.save() + @patch("sentry.loader.browsersdkversion.load_version_from_file") def test_headers(self, mock_load_version_from_file): # We want to always load the major version here since otherwise we fall back to From 4e532417b4d54018edb6f093346375e09cabf5e7 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Feb 2023 16:30:48 +0100 Subject: [PATCH 2/8] add lazy to loader --- .../templates/sentry/js-sdk-loader.js.tmpl | 7 +++--- .../sentry/js-sdk-loader.min.js.tmpl | 8 +++---- src/sentry/web/frontend/js_sdk_loader.py | 22 +++++++++++++++---- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/sentry/templates/sentry/js-sdk-loader.js.tmpl b/src/sentry/templates/sentry/js-sdk-loader.js.tmpl index 4eb3adbfc0847e..08d53ccca33d86 100644 --- a/src/sentry/templates/sentry/js-sdk-loader.js.tmpl +++ b/src/sentry/templates/sentry/js-sdk-loader.js.tmpl @@ -7,9 +7,10 @@ _namespace, _publicKey, _sdkBundleUrl, - _config + _config, + _lazy ) { - var lazy = true; + var lazy = _lazy; var forceLoad = false; for (var i = 0; i < document.scripts.length; i++) { @@ -213,4 +214,4 @@ injectSdk(onLoadCallbacks); }); } -})(window, document, 'script', 'onerror', 'onunhandledrejection', 'Sentry', '{{ publicKey|safe }}', '{{ jsSdkUrl|safe }}', {{ config|to_json|safe }}); +})(window, document, 'script', 'onerror', 'onunhandledrejection', 'Sentry', '{{ publicKey|safe }}', '{{ jsSdkUrl|safe }}', {{ config|to_json|safe }}, {{ isLazy|safe }}); diff --git a/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl b/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl index 7b43f9f8b7c6ba..5783c7c9d342cb 100644 --- a/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl +++ b/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl @@ -1,4 +1,4 @@ -{% load sentry_helpers %}(function(c,w,C,p,q,k,D,E,x){function r(a){if(!y){y=!0;var f=w.scripts[0],d=w.createElement(C);d.src=E;d.crossOrigin="anonymous";d.addEventListener("load",function(){try{c[p]=u;c[q]=v;c.SENTRY_SDK_SOURCE="loader";var b=c[k],g=b.init;b.init=function(e){for(var h in e)Object.prototype.hasOwnProperty.call(e,h)&&(x[h]=e[h]);g(x)};F(a,b)}catch(e){console.error(e)}});f.parentNode.insertBefore(d,f)}}function F(a,f){try{for(var d=l.data,b=0;b None: pass - def _get_bundle_kind_modifier(self, key: ProjectKey, sdk_version: str) -> str: + def _get_bundle_kind_modifier(self, key: ProjectKey, sdk_version: str) -> Tuple[str, bool]: """Returns a string that is used to modify the bundle name""" + + # If we load a performance/replay bundle, set this to be false, as we do not want to + # load the default bundle. + isLazy = True bundle_kind_modifier = "" # The order in which these modifiers are added is important, as the @@ -47,11 +52,13 @@ def _get_bundle_kind_modifier(self, key: ProjectKey, sdk_version: str) -> str: if get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_PERFORMANCE): bundle_kind_modifier += ".tracing" + isLazy = False has_replay = get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_REPLAY) if has_replay: bundle_kind_modifier += ".replay" + isLazy = False # From JavaScript SDK version 7 onwards, the default bundle code is ES6, however, in the loader we # want to provide the ES5 version. This is why we need to modify the requested bundle name here. @@ -64,18 +71,24 @@ def _get_bundle_kind_modifier(self, key: ProjectKey, sdk_version: str) -> str: if get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_DEBUG): bundle_kind_modifier += ".debug" - return bundle_kind_modifier + return bundle_kind_modifier, isLazy def _get_context( self, key: Optional[ProjectKey] ) -> Tuple[LoaderContext, Optional[str], Optional[str]]: """Sets context information needed to render the loader""" if not key: - return ({}, None, None) + return ( + { + "isLazy": True, + }, + None, + None, + ) sdk_version = get_browser_sdk_version(key) - bundle_kind_modifier = self._get_bundle_kind_modifier(key, sdk_version) + bundle_kind_modifier, is_lazy = self._get_bundle_kind_modifier(key, sdk_version) js_sdk_loader_default_sdk_url_template_slot_count = ( settings.JS_SDK_LOADER_DEFAULT_SDK_URL.count("%s") @@ -99,6 +112,7 @@ def _get_context( "config": {"dsn": key.dsn_public}, "jsSdkUrl": sdk_url, "publicKey": key.public_key, + "isLazy": is_lazy, }, sdk_version, sdk_url, From 59f1349779b0ba7753285bbf2b5701c06fa0d340 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Thu, 23 Feb 2023 16:24:45 +0100 Subject: [PATCH 3/8] replay only works with v7 --- src/sentry/templates/sentry/js-sdk-loader.js.tmpl | 6 +++++- src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl | 5 +++++ src/sentry/web/frontend/js_sdk_loader.py | 7 +++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/sentry/templates/sentry/js-sdk-loader.js.tmpl b/src/sentry/templates/sentry/js-sdk-loader.js.tmpl index 08d53ccca33d86..5c14ca6a4754a1 100644 --- a/src/sentry/templates/sentry/js-sdk-loader.js.tmpl +++ b/src/sentry/templates/sentry/js-sdk-loader.js.tmpl @@ -15,7 +15,11 @@ for (var i = 0; i < document.scripts.length; i++) { if (document.scripts[i].src.indexOf(_publicKey) > -1) { - lazy = !(document.scripts[i].getAttribute('data-lazy') === 'no'); + // If lazy was set to true above, we need to check if the user has set data-lazy="no" + // to confirm that we should lazy load the CDN bundle + if (lazy && document.scripts[i].getAttribute('data-lazy') === 'no') { + lazy = false; + } break; } } diff --git a/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl b/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl index 5783c7c9d342cb..dfd6e23e6a98f8 100644 --- a/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl +++ b/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl @@ -2,3 +2,8 @@ var g=!1,e=c.__SENTRY__;"undefined"!==typeof e&&e.hub&&e.hub.getClient()&&(g=!0);e=!1;for(b=0;b Tuple[str, bool]: """Returns a string that is used to modify the bundle name""" + is_v7_sdk = sdk_version >= Version("7.0.0") + # If we load a performance/replay bundle, set this to be false, as we do not want to # load the default bundle. isLazy = True @@ -56,7 +58,8 @@ def _get_bundle_kind_modifier(self, key: ProjectKey, sdk_version: str) -> Tuple[ has_replay = get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_REPLAY) - if has_replay: + # If the project does not have a v7 sdk set, we cannot load the replay bundle. + if not is_v7_sdk and has_replay: bundle_kind_modifier += ".replay" isLazy = False @@ -65,7 +68,7 @@ def _get_bundle_kind_modifier(self, key: ProjectKey, sdk_version: str) -> Tuple[ # # If we are loading replay, do not add the es5 modifier, as those bundles are # ES6 only. - if sdk_version >= Version("7.0.0") and not has_replay: + if is_v7_sdk and not has_replay: bundle_kind_modifier += ".es5" if get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_DEBUG): From c04cb38bdc27e52a9df1cc7685176e3cecfbbbe9 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Fri, 24 Feb 2023 09:50:41 +0100 Subject: [PATCH 4/8] fix is lazy --- src/sentry/web/frontend/js_sdk_loader.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/sentry/web/frontend/js_sdk_loader.py b/src/sentry/web/frontend/js_sdk_loader.py index bbc302d4fc8273..c5eb74c4e4dec0 100644 --- a/src/sentry/web/frontend/js_sdk_loader.py +++ b/src/sentry/web/frontend/js_sdk_loader.py @@ -43,9 +43,7 @@ def _get_bundle_kind_modifier(self, key: ProjectKey, sdk_version: str) -> Tuple[ is_v7_sdk = sdk_version >= Version("7.0.0") - # If we load a performance/replay bundle, set this to be false, as we do not want to - # load the default bundle. - isLazy = True + is_lazy = True bundle_kind_modifier = "" # The order in which these modifiers are added is important, as the @@ -54,14 +52,14 @@ def _get_bundle_kind_modifier(self, key: ProjectKey, sdk_version: str) -> Tuple[ if get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_PERFORMANCE): bundle_kind_modifier += ".tracing" - isLazy = False + is_lazy = False has_replay = get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_REPLAY) # If the project does not have a v7 sdk set, we cannot load the replay bundle. - if not is_v7_sdk and has_replay: + if is_v7_sdk and has_replay: bundle_kind_modifier += ".replay" - isLazy = False + is_lazy = False # From JavaScript SDK version 7 onwards, the default bundle code is ES6, however, in the loader we # want to provide the ES5 version. This is why we need to modify the requested bundle name here. @@ -74,7 +72,7 @@ def _get_bundle_kind_modifier(self, key: ProjectKey, sdk_version: str) -> Tuple[ if get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_DEBUG): bundle_kind_modifier += ".debug" - return bundle_kind_modifier, isLazy + return bundle_kind_modifier, is_lazy def _get_context( self, key: Optional[ProjectKey] From 18a250229cc9d05887c95e8ab0ca7393a6c1b4b6 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Thu, 2 Mar 2023 11:58:34 +0100 Subject: [PATCH 5/8] Remove duplicated minified code --- src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl b/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl index dfd6e23e6a98f8..5709a35b13ee95 100644 --- a/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl +++ b/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl @@ -1,8 +1,3 @@ -{% load sentry_helpers %}(function(c,w,C,q,r,k,D,E,x,l){function t(a){if(!y){y=!0;var f=w.scripts[0],d=w.createElement(C);d.src=E;d.crossOrigin="anonymous";d.addEventListener("load",function(){try{c[q]=u;c[r]=v;c.SENTRY_SDK_SOURCE="loader";var b=c[k],g=b.init;b.init=function(e){for(var h in e)Object.prototype.hasOwnProperty.call(e,h)&&(x[h]=e[h]);g(x)};F(a,b)}catch(e){console.error(e)}});f.parentNode.insertBefore(d,f)}}function F(a,f){try{for(var d=m.data,b=0;b Date: Thu, 2 Mar 2023 13:19:02 +0100 Subject: [PATCH 6/8] Remove dead commented code --- tests/sentry/web/frontend/test_js_sdk_loader.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/sentry/web/frontend/test_js_sdk_loader.py b/tests/sentry/web/frontend/test_js_sdk_loader.py index 6b23329496114e..39b3b66fafd161 100644 --- a/tests/sentry/web/frontend/test_js_sdk_loader.py +++ b/tests/sentry/web/frontend/test_js_sdk_loader.py @@ -11,10 +11,6 @@ class JavaScriptSdkLoaderTest(TestCase): - # def setUp(self): - # self.project = self.create_project() - # self.project_key = self.create_project_key(project=self.project) - @pytest.fixture(autouse=True) def set_settings(self): settings.JS_SDK_LOADER_SDK_VERSION = "0.5.2" From e0dedaf3c85b90cc67eb3c2cd31237bd2b1968fb Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Thu, 2 Mar 2023 14:11:20 +0100 Subject: [PATCH 7/8] Make isLazy template variable output lowercase --- src/sentry/templates/sentry/js-sdk-loader.js.tmpl | 2 +- src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sentry/templates/sentry/js-sdk-loader.js.tmpl b/src/sentry/templates/sentry/js-sdk-loader.js.tmpl index 5c14ca6a4754a1..aee842cba6b899 100644 --- a/src/sentry/templates/sentry/js-sdk-loader.js.tmpl +++ b/src/sentry/templates/sentry/js-sdk-loader.js.tmpl @@ -218,4 +218,4 @@ injectSdk(onLoadCallbacks); }); } -})(window, document, 'script', 'onerror', 'onunhandledrejection', 'Sentry', '{{ publicKey|safe }}', '{{ jsSdkUrl|safe }}', {{ config|to_json|safe }}, {{ isLazy|safe }}); +})(window, document, 'script', 'onerror', 'onunhandledrejection', 'Sentry', '{{ publicKey|safe }}', '{{ jsSdkUrl|safe }}', {{ config|to_json|safe }}, {{ isLazy|safe|lower }}); diff --git a/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl b/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl index 5709a35b13ee95..39b0f855f22bea 100644 --- a/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl +++ b/src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl @@ -1,4 +1,4 @@ {% load sentry_helpers %}(function(c,w,C,q,r,k,D,E,x,l){function t(a){if(!y){y=!0;var f=w.scripts[0],d=w.createElement(C);d.src=E;d.crossOrigin="anonymous";d.addEventListener("load",function(){try{c[q]=u;c[r]=v;c.SENTRY_SDK_SOURCE="loader";var b=c[k],g=b.init;b.init=function(e){for(var h in e)Object.prototype.hasOwnProperty.call(e,h)&&(x[h]=e[h]);g(x)};F(a,b)}catch(e){console.error(e)}});f.parentNode.insertBefore(d,f)}}function F(a,f){try{for(var d=m.data,b=0;b Date: Thu, 2 Mar 2023 14:13:36 +0100 Subject: [PATCH 8/8] Remove unused config --- src/sentry/conf/server.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sentry/conf/server.py b/src/sentry/conf/server.py index d185ccc9924c64..a1009e159f8ce7 100644 --- a/src/sentry/conf/server.py +++ b/src/sentry/conf/server.py @@ -2552,8 +2552,6 @@ def build_cdc_postgres_init_db_volume(settings): JS_SDK_LOADER_CDN_URL = "" # Version of the SDK - Used in header Surrogate-Key sdk/JS_SDK_LOADER_SDK_VERSION JS_SDK_LOADER_SDK_VERSION = "" -# Version of the Dynamic Loader - Used in header Surrogate-Key sdk/JS_SDK_DYNAMIC_LOADER_SDK_VERSION -JS_SDK_DYNAMIC_LOADER_SDK_VERSION = "" # This should be the url pointing to the JS SDK. It may contain up to two "%s". # The first "%s" will be replaced with the SDK version, the second one is used # to inject a bundle modifier in the JS SDK CDN loader. e.g: