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
4 changes: 0 additions & 4 deletions src/sentry/api/endpoints/project_docs_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 0 additions & 1 deletion src/sentry/api/serializers/models/project_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()},
Expand Down
2 changes: 0 additions & 2 deletions src/sentry/conf/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
11 changes: 0 additions & 11 deletions src/sentry/models/projectkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 9 additions & 4 deletions src/sentry/templates/sentry/js-sdk-loader.js.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@
_namespace,
_publicKey,
_sdkBundleUrl,
_config
_config,
_lazy
) {
var lazy = true;
var lazy = _lazy;
var forceLoad = false;

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;
}
}
Expand Down Expand Up @@ -213,4 +218,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|lower }});
8 changes: 4 additions & 4 deletions src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl
Original file line number Diff line number Diff line change
@@ -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<a.length;b++)if("function"===typeof a[b])a[b]();
var g=!1,e=c.__SENTRY__;"undefined"!==typeof e&&e.hub&&e.hub.getClient()&&(g=!0);e=!1;for(b=0;b<d.length;b++)if(d[b].f){e=!0;var h=d[b];!1===g&&"init"!==h.f&&f.init();g=!0;f[h.f].apply(f,h.a)}!1===g&&!1===e&&f.init();var z=c[p],A=c[q];for(b=0;b<d.length;b++)"e"in d[b]&&z?z.apply(c,d[b].e):"p"in d[b]&&A&&A.apply(c,[d[b].p])}catch(G){console.error(G)}}for(var m=!0,B=!1,t=0;t<document.scripts.length;t++)if(-1<document.scripts[t].src.indexOf(D)){m="no"!==document.scripts[t].getAttribute("data-lazy");
break}var y=!1,n=[],l=function(a){("e"in a||"p"in a||a.f&&-1<a.f.indexOf("capture")||a.f&&-1<a.f.indexOf("showReportDialog"))&&m&&r(n);l.data.push(a)};l.data=[];c[k]=c[k]||{};c[k].onLoad=function(a){n.push(a);m&&!B||r(n)};c[k].forceLoad=function(){B=!0;m&&setTimeout(function(){r(n)})};"init addBreadcrumb captureMessage captureException captureEvent configureScope withScope showReportDialog".split(" ").forEach(function(a){c[k][a]=function(){l({f:a,a:arguments})}});var u=c[p];c[p]=function(a,f,d,b,
g){l({e:[].slice.call(arguments)});u&&u.apply(c,arguments)};var v=c[q];c[q]=function(a){l({p:"reason"in a?a.reason:"detail"in a&&"reason"in a.detail?a.detail.reason:a});v&&v.apply(c,arguments)};m||setTimeout(function(){r(n)})})(window,document,"script","onerror","onunhandledrejection","Sentry","{{ publicKey|safe }}","{{ jsSdkUrl|safe }}",{{ config|to_json|safe }});
{% 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<a.length;b++)if("function"===typeof a[b])a[b]();
var g=!1,e=c.__SENTRY__;"undefined"!==typeof e&&e.hub&&e.hub.getClient()&&(g=!0);e=!1;for(b=0;b<d.length;b++)if(d[b].f){e=!0;var h=d[b];!1===g&&"init"!==h.f&&f.init();g=!0;f[h.f].apply(f,h.a)}!1===g&&!1===e&&f.init();var z=c[q],A=c[r];for(b=0;b<d.length;b++)"e"in d[b]&&z?z.apply(c,d[b].e):"p"in d[b]&&A&&A.apply(c,[d[b].p])}catch(G){console.error(G)}}var n=l,B=!1;for(l=0;l<document.scripts.length;l++)if(-1<document.scripts[l].src.indexOf(D)){n&&"no"===document.scripts[l].getAttribute("data-lazy")&&
(n=!1);break}var y=!1,p=[],m=function(a){("e"in a||"p"in a||a.f&&-1<a.f.indexOf("capture")||a.f&&-1<a.f.indexOf("showReportDialog"))&&n&&t(p);m.data.push(a)};m.data=[];c[k]=c[k]||{};c[k].onLoad=function(a){p.push(a);n&&!B||t(p)};c[k].forceLoad=function(){B=!0;n&&setTimeout(function(){t(p)})};"init addBreadcrumb captureMessage captureException captureEvent configureScope withScope showReportDialog".split(" ").forEach(function(a){c[k][a]=function(){m({f:a,a:arguments})}});var u=c[q];c[q]=function(a,
f,d,b,g){m({e:[].slice.call(arguments)});u&&u.apply(c,arguments)};var v=c[r];c[r]=function(a){m({p:"reason"in a?a.reason:"detail"in a&&"reason"in a.detail?a.detail.reason:a});v&&v.apply(c,arguments)};n||setTimeout(function(){t(p)})})(window,document,"script","onerror","onunhandledrejection","Sentry","{{ publicKey|safe }}","{{ jsSdkUrl|safe }}",{{ config|to_json|safe }},{{ isLazy|safe|lower }});
105 changes: 0 additions & 105 deletions src/sentry/web/frontend/js_sdk_dynamic_loader.py

This file was deleted.

70 changes: 62 additions & 8 deletions src/sentry/web/frontend/js_sdk_loader.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import time
from typing import Optional, Tuple, TypedDict

from django.conf import settings
from packaging.version import Version
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.utils import metrics
from sentry.web.frontend.base import BaseView
Expand All @@ -16,6 +18,17 @@
)


class SdkConfig(TypedDict):
dsn: str


class LoaderContext(TypedDict):
config: SdkConfig
jsSdkUrl: Optional[str]
publicKey: Optional[str]
isLazy: bool


class JavaScriptSdkLoader(BaseView):
auth_required = False

Expand All @@ -25,18 +38,58 @@ 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) -> Tuple[str, bool]:
"""Returns a string that is used to modify the bundle name"""

is_v7_sdk = sdk_version >= Version("7.0.0")

is_lazy = True
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"
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 is_v7_sdk and has_replay:
bundle_kind_modifier += ".replay"
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.
#
# If we are loading replay, do not add the es5 modifier, as those bundles are
# ES6 only.
if is_v7_sdk 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, is_lazy

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)

# 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, 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")
Expand All @@ -60,12 +113,13 @@ def _get_context(self, key):
"config": {"dsn": key.dsn_public},
"jsSdkUrl": sdk_url,
"publicKey": key.public_key,
"isLazy": is_lazy,
},
sdk_version,
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
Expand Down
7 changes: 0 additions & 7 deletions src/sentry/web/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -117,12 +116,6 @@
JavaScriptSdkLoader.as_view(),
name="sentry-js-sdk-loader",
),
# JavaScript SDK Dynamic Loader
url(
r"^js-sdk-loader/dynamic/(?P<public_key>[^/\.]+)(?:(?P<minified>\.min))?\.js$",
JavaScriptSdkDynamicLoader.as_view(),
name="sentry-js-sdk-dynamic-loader",
),
# Versioned API
url(r"^api/0/", include("sentry.api.urls")),
# Legacy unversioned endpoints
Expand Down
13 changes: 0 additions & 13 deletions tests/sentry/models/test_projectkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"):
Expand Down
41 changes: 0 additions & 41 deletions tests/sentry/web/frontend/test_js_sdk_dynamic_loader.py

This file was deleted.

Loading