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
38 changes: 23 additions & 15 deletions src/sentry/templates/sentry/js-sdk-loader.js.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -60,37 +60,45 @@
}
// Add loader as SDK source
_window.SENTRY_SDK_SOURCE = 'loader';
var SDK = _window[_namespace];
var oldInit_1 = SDK.init;
// Add necessary integrations based on config
var integrations = [];
if (_config.tracesSampleRate) {
integrations.push(new SDK.BrowserTracing());
}
if (_config.replaysSessionSampleRate || _config.replaysOnErrorSampleRate) {
integrations.push(new SDK.Replay());
}
if (integrations.length) {
_config.integrations = integrations;
}
var SDK_1 = _window[_namespace];
var oldInit_1 = SDK_1.init;
// Configure it using provided DSN and config object
SDK.init = function (options) {
SDK_1.init = function (options) {
var target = _config;
for (var key in options) {
if (Object.prototype.hasOwnProperty.call(options, key)) {
target[key] = options[key];
}
}
setupDefaultIntegrations(target, SDK_1);
oldInit_1(target);
};
sdkLoaded(callbacks, SDK);
sdkLoaded(callbacks, SDK_1);
}
catch (o_O) {
console.error(o_O);
}
});
_currentScriptTag.parentNode.insertBefore(_newScriptTag, _currentScriptTag);
}
// We want to ensure to only add default integrations if they haven't been added by the user.
function setupDefaultIntegrations(config, SDK) {
var integrations = config.integrations || [];
// integrations can be a function, in which case we will not add any defaults
if (!Array.isArray(integrations)) {
return;
}
var integrationNames = integrations.map(function (integration) { return integration.name; });
// Add necessary integrations based on config
if (config.tracesSampleRate && integrationNames.indexOf('BrowserTracing') === -1) {
integrations.push(new SDK.BrowserTracing());
}
if ((config.replaysSessionSampleRate || config.replaysOnErrorSampleRate) &&
integrationNames.indexOf('Replay') === -1) {
integrations.push(new SDK.Replay());
}
config.integrations = integrations;
}
function sdkIsLoaded() {
var __sentry = _window.__SENTRY__;
// If there is a global __SENTRY__ that means that in any of the callbacks init() was already invoked
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/templates/sentry/js-sdk-loader.min.js.tmpl
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{% load sentry_helpers %}!function(n,e,t,r,o,a,i,c,_,p){for(var s=p,forceLoad=!1,f=0;f<document.scripts.length;f++)if(document.scripts[f].src.indexOf(i)>-1){s&&"no"===document.scripts[f].getAttribute("data-lazy")&&(s=!1);break}var u=!1,l=[],d=function(n){("e"in n||"p"in n||n.f&&n.f.indexOf("capture")>-1||n.f&&n.f.indexOf("showReportDialog")>-1)&&s&&E(l),d.data.push(n)};function E(i){if(!u){u=!0;var p=e.scripts[0],s=e.createElement(t);s.src=c,s.crossOrigin="anonymous",s.addEventListener("load",(function(){try{n[r]&&n[r].__SENTRY_LOADER__&&(n[r]=R),n[o]&&n[o].__SENTRY_LOADER__&&(n[o]=h),n.SENTRY_SDK_SOURCE="loader";var e=n[a],t=e.init,c=[];_.tracesSampleRate&&c.push(new e.BrowserTracing),(_.replaysSessionSampleRate||_.replaysOnErrorSampleRate)&&c.push(new e.Replay),c.length&&(_.integrations=c),e.init=function(n){var e=_;for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r]);t(e)},function(e,t){try{for(var a=0;a<e.length;a++)"function"==typeof e[a]&&e[a]();var i=d.data,c=!(void 0===(u=n.__SENTRY__)||!u.hub||!u.hub.getClient());i.sort((function(n){return"init"===n.f?-1:0}));var _=!1;for(a=0;a<i.length;a++)if(i[a].f){_=!0;var p=i[a];!1===c&&"init"!==p.f&&t.init(),c=!0,t[p.f].apply(t,p.a)}!1===c&&!1===_&&t.init();var s=n[r],f=n[o];for(a=0;a<i.length;a++)"e"in i[a]&&s?s.apply(n,i[a].e):"p"in i[a]&&f&&f.apply(n,[i[a].p])}catch(n){console.error(n)}var u}(i,e)}catch(n){console.error(n)}})),p.parentNode.insertBefore(s,p)}}d.data=[],n[a]=n[a]||{},n[a].onLoad=function(n){l.push(n),s&&!forceLoad||E(l)},n[a].forceLoad=function(){forceLoad=!0,s&&setTimeout((function(){E(l)}))},["init","addBreadcrumb","captureMessage","captureException","captureEvent","configureScope","withScope","showReportDialog"].forEach((function(e){n[a][e]=function(){d({f:e,a:arguments})}}));var R=n[r];n[r]=function(){d({e:[].slice.call(arguments)}),R&&R.apply(n,arguments)},n[r].__SENTRY_LOADER__=!0;var h=n[o];n[o]=function(e){d({p:"reason"in e?e.reason:"detail"in e&&"reason"in e.detail?e.detail.reason:e}),h&&h.apply(n,arguments)},n[o].__SENTRY_LOADER__=!0,s||setTimeout((function(){E(l)}))}(window,document,"script","onerror","onunhandledrejection","Sentry",'{{ publicKey|safe }}','{{ jsSdkUrl|safe }}',{{ config|to_json|safe }},{{ isLazy|safe|lower }});
{% load sentry_helpers %}!function(n,e,r,t,a,i,o,c,_,f){for(var p=f,forceLoad=!1,s=0;s<document.scripts.length;s++)if(document.scripts[s].src.indexOf(o)>-1){p&&"no"===document.scripts[s].getAttribute("data-lazy")&&(p=!1);break}var u=!1,l=[],d=function(n){("e"in n||"p"in n||n.f&&n.f.indexOf("capture")>-1||n.f&&n.f.indexOf("showReportDialog")>-1)&&p&&R(l),d.data.push(n)};function R(o){if(!u){u=!0;var f=e.scripts[0],p=e.createElement(r);p.src=c,p.crossOrigin="anonymous",p.addEventListener("load",(function(){try{n[t]&&n[t].__SENTRY_LOADER__&&(n[t]=E),n[a]&&n[a].__SENTRY_LOADER__&&(n[a]=v),n.SENTRY_SDK_SOURCE="loader";var e=n[i],r=e.init;e.init=function(n){var t=_;for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(t[a]=n[a]);!function(n,e){var r=n.integrations||[];if(!Array.isArray(r))return;var t=r.map((function(n){return n.name}));n.tracesSampleRate&&-1===t.indexOf("BrowserTracing")&&r.push(new e.BrowserTracing);(n.replaysSessionSampleRate||n.replaysOnErrorSampleRate)&&-1===t.indexOf("Replay")&&r.push(new e.Replay);n.integrations=r}(t,e),r(t)},function(e,r){try{for(var i=0;i<e.length;i++)"function"==typeof e[i]&&e[i]();var o=d.data,c=!(void 0===(u=n.__SENTRY__)||!u.hub||!u.hub.getClient());o.sort((function(n){return"init"===n.f?-1:0}));var _=!1;for(i=0;i<o.length;i++)if(o[i].f){_=!0;var f=o[i];!1===c&&"init"!==f.f&&r.init(),c=!0,r[f.f].apply(r,f.a)}!1===c&&!1===_&&r.init();var p=n[t],s=n[a];for(i=0;i<o.length;i++)"e"in o[i]&&p?p.apply(n,o[i].e):"p"in o[i]&&s&&s.apply(n,[o[i].p])}catch(n){console.error(n)}var u}(o,e)}catch(n){console.error(n)}})),f.parentNode.insertBefore(p,f)}}d.data=[],n[i]=n[i]||{},n[i].onLoad=function(n){l.push(n),p&&!forceLoad||R(l)},n[i].forceLoad=function(){forceLoad=!0,p&&setTimeout((function(){R(l)}))},["init","addBreadcrumb","captureMessage","captureException","captureEvent","configureScope","withScope","showReportDialog"].forEach((function(e){n[i][e]=function(){d({f:e,a:arguments})}}));var E=n[t];n[t]=function(){d({e:[].slice.call(arguments)}),E&&E.apply(n,arguments)},n[t].__SENTRY_LOADER__=!0;var v=n[a];n[a]=function(e){d({p:"reason"in e?e.reason:"detail"in e&&"reason"in e.detail?e.detail.reason:e}),v&&v.apply(n,arguments)},n[a].__SENTRY_LOADER__=!0,p||setTimeout((function(){R(l)}))}(window,document,"script","onerror","onunhandledrejection","Sentry",'{{ publicKey|safe }}','{{ jsSdkUrl|safe }}',{{ config|to_json|safe }},{{ isLazy|safe|lower }});
42 changes: 28 additions & 14 deletions src/sentry/templates/sentry/js-sdk-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,6 @@ declare const __LOADER__IS_LAZY__: any;

const oldInit = SDK.init;

// Add necessary integrations based on config
const integrations: unknown[] = [];
if (_config.tracesSampleRate) {
integrations.push(new SDK.BrowserTracing());
}

if (_config.replaysSessionSampleRate || _config.replaysOnErrorSampleRate) {
integrations.push(new SDK.Replay());
}

if (integrations.length) {
_config.integrations = integrations;
}

// Configure it using provided DSN and config object
SDK.init = function (options) {
const target = _config;
Expand All @@ -114,6 +100,8 @@ declare const __LOADER__IS_LAZY__: any;
target[key] = options[key];
}
}

setupDefaultIntegrations(target, SDK);
oldInit(target);
};

Expand All @@ -126,6 +114,32 @@ declare const __LOADER__IS_LAZY__: any;
_currentScriptTag.parentNode!.insertBefore(_newScriptTag, _currentScriptTag);
}

// We want to ensure to only add default integrations if they haven't been added by the user.
function setupDefaultIntegrations(config: any, SDK: any) {
Copy link
Member

Choose a reason for hiding this comment

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

not a blocker but isn't there a better type that we could use here?

Copy link
Member Author

Choose a reason for hiding this comment

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

IMHO We'd need to port all the types from JS-SDK into here to make this meaningful. It may be worthwhile to generally add more types here, but we'd need to start at the top there - I'd keep this for a follow up PR :)

const integrations: {name: string}[] = config.integrations || [];
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
const integrations: {name: string}[] = config.integrations || [];
const integrations: {name: string}[] = config.integrations ?? [];

Copy link
Member Author

Choose a reason for hiding this comment

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

This transpiles into a slightly more verbose form, which we generally try to avoid for ES5 code, as it adds a few - in this case unnecessary - bytes. In this case, I think || is fine. (Working on the JS SDK burns this into your brain xD)


// integrations can be a function, in which case we will not add any defaults
if (!Array.isArray(integrations)) {
return;
}

const integrationNames = integrations.map(integration => integration.name);

// Add necessary integrations based on config
if (config.tracesSampleRate && integrationNames.indexOf('BrowserTracing') === -1) {
Copy link
Member

Choose a reason for hiding this comment

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

integrations can be an function 😢 - we'll have to account for that use case as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

hmmm, good point! I would tend to ignore this case for now (=do not register default integrations if this is a function). WDYT? I think everything else would be a bit tricky, probably...

Copy link
Member

Choose a reason for hiding this comment

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

yup i think its fine to ignore! it is pretty advanced config, so we can add a note in the docs about it.

Copy link
Member Author

Choose a reason for hiding this comment

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

👍 updated this, also updating the script in sentry-javascript PR and adding a test for this here: getsentry/sentry-javascript@386cd2b

integrations.push(new SDK.BrowserTracing());
}

if (
(config.replaysSessionSampleRate || config.replaysOnErrorSampleRate) &&
integrationNames.indexOf('Replay') === -1
) {
integrations.push(new SDK.Replay());
}

config.integrations = integrations;
}

function sdkIsLoaded() {
const __sentry = _window.__SENTRY__;
// If there is a global __SENTRY__ that means that in any of the callbacks init() was already invoked
Expand Down