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
42 changes: 34 additions & 8 deletions src/sentry/web/frontend/js_sdk_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@

class SdkConfig(TypedDict):
dsn: str
tracesSampleRate: Optional[float]
replaysSessionSampleRate: Optional[float]
replaysOnErrorSampleRate: Optional[float]
debug: Optional[bool]


class LoaderContext(TypedDict):
Expand All @@ -38,24 +42,28 @@ class JavaScriptSdkLoader(BaseView):
def determine_active_organization(self, request: Request, organization_slug=None) -> None:
pass

def _get_bundle_kind_modifier(self, key: ProjectKey, sdk_version: str) -> Tuple[str, bool]:
def _get_bundle_kind_modifier(
self, key: ProjectKey, sdk_version: str
) -> Tuple[str, bool, bool, bool, 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 = ""
has_replay = get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_REPLAY)
has_performance = get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_PERFORMANCE)
has_debug = get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_DEBUG)

# 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):
# We depend on fixes in the tracing bundle that are only available in v7
if is_v7_sdk and 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"
Expand All @@ -69,10 +77,10 @@ def _get_bundle_kind_modifier(self, key: ProjectKey, sdk_version: str) -> Tuple[
if is_v7_sdk and not has_replay:
bundle_kind_modifier += ".es5"

if get_dynamic_sdk_loader_option(key, DynamicSdkLoaderOption.HAS_DEBUG):
if has_debug:
bundle_kind_modifier += ".debug"

return bundle_kind_modifier, is_lazy
return bundle_kind_modifier, is_lazy, has_performance, has_replay, has_debug

def _get_context(
self, key: Optional[ProjectKey]
Expand All @@ -89,7 +97,13 @@ def _get_context(

sdk_version = get_browser_sdk_version(key)

bundle_kind_modifier, is_lazy = self._get_bundle_kind_modifier(key, sdk_version)
(
bundle_kind_modifier,
is_lazy,
has_performance,
has_replay,
has_debug,
) = 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 @@ -108,9 +122,21 @@ def _get_context(
except TypeError:
sdk_url = "" # It fails if it cannot inject the version in the string

config: SdkConfig = {"dsn": key.dsn_public}

if has_debug:
config["debug"] = True

if has_performance:
config["tracesSampleRate"] = 1

if has_replay:
config["replaysSessionSampleRate"] = 0.1
config["replaysOnErrorSampleRate"] = 1

return (
{
"config": {"dsn": key.dsn_public},
"config": config,
"jsSdkUrl": sdk_url,
"publicKey": key.public_key,
"isLazy": is_lazy,
Expand Down
36 changes: 34 additions & 2 deletions tests/sentry/web/frontend/test_js_sdk_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from sentry.loader.dynamic_sdk_options import DynamicSdkLoaderOption
from sentry.testutils import TestCase
from sentry.utils import json


class JavaScriptSdkLoaderTest(TestCase):
Expand Down Expand Up @@ -113,14 +114,17 @@ def test_bundle_kind_modifiers(self, load_version_from_file, get_selected_browse
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 [
dsn = self.projectkey.get_dsn(public=True)

for data, expected_bundle, expected_options in [
(
{
"dynamicSdkLoaderOptions": {
DynamicSdkLoaderOption.HAS_PERFORMANCE.value: True,
}
},
b"/7.37.0/bundle.tracing.es5.min.js",
{"dsn": dsn, "tracesSampleRate": 1},
),
(
{
Expand All @@ -129,6 +133,7 @@ def test_bundle_kind_modifiers(self, load_version_from_file, get_selected_browse
}
},
b"/7.37.0/bundle.es5.debug.min.js",
{"dsn": dsn, "debug": True},
),
(
{
Expand All @@ -137,6 +142,7 @@ def test_bundle_kind_modifiers(self, load_version_from_file, get_selected_browse
}
},
b"/7.37.0/bundle.replay.min.js",
{"dsn": dsn, "replaysSessionSampleRate": 0.1, "replaysOnErrorSampleRate": 1},
),
(
{
Expand All @@ -146,6 +152,12 @@ def test_bundle_kind_modifiers(self, load_version_from_file, get_selected_browse
}
},
b"/7.37.0/bundle.tracing.replay.min.js",
{
"dsn": dsn,
"tracesSampleRate": 1,
"replaysSessionSampleRate": 0.1,
"replaysOnErrorSampleRate": 1,
},
),
(
{
Expand All @@ -155,6 +167,12 @@ def test_bundle_kind_modifiers(self, load_version_from_file, get_selected_browse
}
},
b"/7.37.0/bundle.replay.debug.min.js",
{
"dsn": dsn,
"replaysSessionSampleRate": 0.1,
"replaysOnErrorSampleRate": 1,
"debug": True,
},
),
(
{
Expand All @@ -164,6 +182,7 @@ def test_bundle_kind_modifiers(self, load_version_from_file, get_selected_browse
}
},
b"/7.37.0/bundle.tracing.es5.debug.min.js",
{"dsn": dsn, "tracesSampleRate": 1, "debug": True},
),
(
{
Expand All @@ -174,14 +193,27 @@ def test_bundle_kind_modifiers(self, load_version_from_file, get_selected_browse
}
},
b"/7.37.0/bundle.tracing.replay.debug.min.js",
{
"dsn": dsn,
"tracesSampleRate": 1,
"replaysSessionSampleRate": 0.1,
"replaysOnErrorSampleRate": 1,
"debug": True,
},
),
]:
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
assert expected_bundle in resp.content

for key in expected_options:
# Convert to e.g. "option_name": 0.1
single_option = {key: expected_options[key]}
assert bytes(json.dumps(single_option)[1:-1], "utf-8") in resp.content

self.projectkey.data = {}
self.projectkey.save()

Expand Down