Skip to content

Instantly share code, notes, and snippets.

@bripkens
Created August 19, 2020 15:16
Show Gist options
  • Save bripkens/909540fe7194f6b4bd4a1f5d827f6ee6 to your computer and use it in GitHub Desktop.
Save bripkens/909540fe7194f6b4bd4a1f5d827f6ee6 to your computer and use it in GitHub Desktop.
(function () {
'use strict';
var pageLoad = 'pl';
// aliasing globals for improved minifications
var win = window;
var doc = win.document;
var nav = navigator;
var encodeURIComponent = win.encodeURIComponent;
var XMLHttpRequest = win.XMLHttpRequest;
var originalFetch = win.fetch;
var localStorage = function () {
try {
return win.localStorage;
} catch (e) {
// localStorage access is not permitted in certain security modes, e.g.
// when cookies are completely disabled in web browsers.
return null;
}
}();
/**
* Leverage's browser behavior to load image sources. Exposed via this module
* to enable testing.
*/
function executeImageRequest(url) {
var image = new Image();
image.src = url;
}
/**
* Exposed via this module to enable testing.
*/
function sendBeacon(url, data) {
return nav.sendBeacon(url, data);
}
// protection against hasOwnProperty overrides.
var globalHasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwnProperty(obj, key) {
return globalHasOwnProperty.call(obj, key);
}
function now() {
return new Date().getTime();
}
function noop() {} // We are trying to stay close to common tracing architectures and use
// a hex encoded 64 bit random ID.
var validIdCharacters = '0123456789abcdef'.split('');
var generateUniqueIdImpl = function generateUniqueIdViaRandom() {
var result = '';
for (var i = 0; i < 16; i++) {
result += validIdCharacters[Math.round(Math.random() * 15)];
}
return result;
};
if (win.crypto && win.crypto.getRandomValues && win.Uint32Array) {
generateUniqueIdImpl = function generateUniqueIdViaCrypto() {
var array = new win.Uint32Array(2);
win.crypto.getRandomValues(array);
return array[0].toString(16) + array[1].toString(16);
};
}
var generateUniqueId = generateUniqueIdImpl;
function addEventListener(target, eventType, callback) {
if (target.addEventListener) {
target.addEventListener(eventType, callback, false);
} else if (target.attachEvent) {
target.attachEvent('on' + eventType, callback);
}
}
function removeEventListener(target, eventType, callback) {
if (target.removeEventListener) {
target.removeEventListener(eventType, callback, false);
} else if (target.detachEvent) {
target.detachEvent('on' + eventType, callback);
}
}
function matchesAny(regexp, s) {
for (var i = 0, len = regexp.length; i < len; i++) {
if (regexp[i].test(s)) {
return true;
}
}
return false;
}
/* eslint-disable no-console */
// $FlowFixMe The function is never going to be used when it is a bool
var log = createLogger('log'); // $FlowFixMe The function is never going to be used when it is a bool
var info = createLogger('info'); // $FlowFixMe The function is never going to be used when it is a bool
var warn = createLogger('warn'); // $FlowFixMe The function is never going to be used when it is a bool
var error = createLogger('error'); // $FlowFixMe The function is never going to be used when it is a bool
var debug = createLogger('debug');
function createLogger(method) {
if (typeof console === 'undefined' || typeof console.log !== 'function' || typeof console.log.apply !== 'function') {
return noop;
}
if (console[method] && typeof console[method].apply === 'function') {
return function () {
console[method].apply(console, arguments);
};
}
return function () {
console.log.apply(console, arguments);
};
}
// ensure that execution of timers happens outside of any Angular specific zones. This in turn
// means that this script will never disturb Angular's stabilization phase.
// https://angular.io/api/core/ApplicationRef#isStable
// Please note that it may sometimes be necessary to deliberately execute code inside of
// Angular's Zones. Always take care to make a deliberate decision when to use and when not to
// use these wrappers.
// We take a copy of all globals to ensure that no other script will change them all of a sudden.
// This ensures that when we register a timeout/interval on one global, that we will be able to
// de-register it again in all cases.
var globals = {
'setTimeout': win.setTimeout,
'clearTimeout': win.clearTimeout,
'setInterval': win.setInterval,
'clearInterval': win.clearInterval
}; // If the globals don't exist at execution time of this file, then we know that the globals stored
// above are not wrapped by Zone.js. This in turn can mean better performance for Angular users.
var isRunningZoneJs = win['Zone'] != null && win['Zone']['root'] != null && typeof win['Zone']['root']['run'] === 'function';
if (isRunningZoneJs) {
info('Discovered Zone.js globals. Will attempt to register all timers inside the root Zone.');
}
function setTimeout() {
return executeGlobally.apply('setTimeout', arguments);
}
function clearTimeout() {
return executeGlobally.apply('clearTimeout', arguments);
}
function setInterval() {
return executeGlobally.apply('setInterval', arguments);
}
function executeGlobally() {
// We don't want to incur a performance penalty for all users just because some
// users are relying on zone.js. This API looks quite ridiculous, but it
// allows for concise and efficient code, e.g. arguments does not need to be
// translated into an array.
var globalFunctionName = this;
if (isRunningZoneJs) {
try {
// Incurr a performance overhead for Zone.js users that we just cannot avoid:
// Copy the arguments passed in here so that we can use them inside the root
// zone.
var args = Array.prototype.slice.apply(arguments);
return win['Zone']['root']['run'](globals[globalFunctionName], win, args);
} catch (e) {
{
warn('Failed to execute %s inside of zone (via Zone.js). Falling back to execution inside currently ' + 'active zone.', globalFunctionName, e);
} // failure – maybe zone js not properly initialized? Fall back to execution
// outside of Zone.js as a last resort (outside of try/catch and if)
}
} // Note: Explicitly passing win as 'this' even though we are getting the function from 'globals'
return globals[globalFunctionName].apply(win, arguments);
}
var bus = {};
function on(name, fn) {
var listeners = bus[name] = bus[name] || [];
listeners.push(fn);
}
function emit(name, value) {
var listeners = bus[name];
if (!listeners) {
return;
}
for (var i = 0, length = listeners.length; i < length; i++) {
listeners[i](value);
}
}
var event = {
name: 'e:onLoad',
time: null,
initialize: function () {
if (document.readyState === 'complete') {
return onReady();
}
addEventListener(win, 'load', function () {
// we want to get timing data for loadEventEnd,
// so asynchronously process this
setTimeout(onReady, 0);
});
}
};
function onReady() {
event.time = now();
emit(event.name, event.time);
}
var states = {};
var currentStateName;
function registerState(name, impl) {
states[name] = impl;
}
function transitionTo(nextStateName) {
{
info('Transitioning from %s to %s', currentStateName || '<no state>', nextStateName);
}
currentStateName = nextStateName;
states[nextStateName].onEnter();
}
function getActiveTraceId() {
return states[currentStateName].getActiveTraceId();
}
function getActivePhase() {
return states[currentStateName].getActivePhase();
}
var performance = win.performance || win.webkitPerformance || win.msPerformance || win.mozPerformance;
var isTimingAvailable = performance && performance.timing;
var isResourceTimingAvailable = performance && performance.getEntriesByType;
var isPerformanceObserverAvailable = performance && typeof win['PerformanceObserver'] === 'function' && typeof performance['now'] === 'function';
var defaultVars = {
nameOfLongGlobal: 'InstanaEumObject',
trackingSnippetVersion: null,
pageLoadTraceId: generateUniqueId(),
pageLoadBackendTraceId: null,
serverTimingBackendTraceIdEntryName: 'intid',
referenceTimestamp: now(),
highResTimestampReference: performance && performance.now ? performance.now() : 0,
initializerExecutionTimestamp: now(),
reportingUrl: 'https://eum.instana.io',
beaconBatchingTime: 2000,
maxWaitForResourceTimingsMillis: 10000,
maxMaitForPageLoadMetricsMillis: 5000,
apiKey: null,
meta: {},
ignoreUrls: [],
ignorePings: true,
ignoreErrorMessages: [],
xhrTransmissionTimeout: 20000,
whitelistedOrigins: [],
page: undefined,
wrapEventHandlers: false,
wrappedEventHandlersOriginalFunctionStorageKey: '__instanaOriginalFunctions__',
wrapTimers: false,
secretPropertyKey: '__instanaSecretData__',
userId: undefined,
userName: undefined,
userEmail: undefined,
sessionId: undefined,
sessionStorageKey: 'in-session',
defaultSessionInactivityTimeoutMillis: 1000 * 60 * 60 * 3,
defaultSessionTerminationTimeoutMillis: 1000 * 60 * 60 * 6,
maxAllowedSessionTimeoutMillis: 1000 * 60 * 60 * 24,
// The default ignore rules cover specific React and Angular patterns:
//
// React has a whole lot of user timings. Luckily all of them start with
// the emojis for easy filtering. Let's ignore them by default as most of
// them won't be valuable to many of our users (in production).
//
// Similar for Angular which uses zones with a ton of custom user
// timings. https://angular.io/guide/zone
//
// We have also seen people use 'start xyz' / 'end xyz' as a common pattern to
// name marks used to create measures. This is surely not a comprehensive
// solution to identify these cases, but should for now be sufficient.
ignoreUserTimings: [/^\u269B/, /^\u26D4/, /^Zone(:|$)/, /^start /i, /^end /i],
urlsToCheckForGraphQlInsights: [/\/graphql/i]
};
var state = {
onEnter: function () {
on(event.name, onLoad);
event.initialize();
},
getActiveTraceId: function () {
return defaultVars.pageLoadTraceId;
},
getActivePhase: function () {
return pageLoad;
}
};
function onLoad() {
transitionTo('pageLoaded');
}
var maximumNumberOfMetaDataFields = 25;
var maximumLengthPerMetaDataField = 1024;
var languages = determineLanguages();
function addCommonBeaconProperties(beacon) {
beacon['k'] = defaultVars.apiKey;
beacon['sv'] = defaultVars.trackingSnippetVersion;
beacon['r'] = defaultVars.referenceTimestamp;
beacon['p'] = defaultVars.page;
beacon['l'] = win.location.href;
beacon['pl'] = defaultVars.pageLoadTraceId;
beacon['ui'] = defaultVars.userId;
beacon['un'] = defaultVars.userName;
beacon['ue'] = defaultVars.userEmail;
beacon['ul'] = languages;
beacon['ph'] = getActivePhase();
beacon['sid'] = defaultVars.sessionId;
beacon['ww'] = win.innerWidth;
beacon['wh'] = win.innerHeight; // Google Closure compiler is not yet aware of these globals. Make sure it doesn't
// mangle them.
if (nav['connection'] && nav['connection']['effectiveType']) {
beacon['ct'] = nav['connection']['effectiveType'];
}
if (doc.visibilityState) {
beacon['h'] = doc.visibilityState === 'hidden' ? 1 : 0;
}
addMetaDataToBeacon(beacon, defaultVars.meta);
}
function determineLanguages() {
if (nav.languages && nav.languages.length > 0) {
return nav.languages.slice(0, 5).join(',');
}
if (typeof nav.userLanguage === 'string') {
return [nav.userLanguage].join(',');
}
return undefined;
}
function addMetaDataToBeacon(beacon, meta) {
var i = 0;
for (var key in meta) {
if (hasOwnProperty(meta, key)) {
i++;
if (i > maximumNumberOfMetaDataFields) {
{
warn('Maximum number of meta data fields exceeded. Not all meta data fields will be transmitted.');
}
return;
}
var serializedValue = null;
if (typeof meta[key] === 'string') {
serializedValue = meta[key];
} else if (meta[key] === undefined) {
serializedValue = 'undefined';
} else if (meta[key] === null) {
serializedValue = 'null';
} else if (win.JSON) {
try {
serializedValue = win.JSON.stringify(meta[key]);
} catch (e) {
{
warn('JSON serialization of meta data', key, meta[key], 'failed due to', e, '. This value will not be transmitted.');
}
continue;
}
} else {
serializedValue = String(meta[key]);
}
beacon['m_' + key] = serializedValue.substring(0, maximumLengthPerMetaDataField);
}
}
}
var urlMaxLength = 255;
var initiatorTypes = {
'other': 0,
'img': 1,
// IMAGE element inside a SVG
'image': 1,
'link': 2,
'script': 3,
'css': 4,
'xmlhttprequest': 5,
'fetch': 5,
'beacon': 5,
'html': 6,
'navigation': 6
};
var cachingTypes = {
unknown: 0,
cached: 1,
validated: 2,
fullLoad: 3
};
function serializeEntryToArray(entry) {
var result = [Math.round(entry['startTime'] - defaultVars.highResTimestampReference), Math.round(entry['duration']), initiatorTypes[entry['initiatorType']] || initiatorTypes['other']]; // When timing data is available, we can provide additional information about
// caching and resource sizes.
if (typeof entry['transferSize'] === 'number' && typeof entry['encodedBodySize'] === 'number' && // All this information may not be available due to the timing allow origin check.
entry['encodedBodySize'] > 0) {
if (entry['transferSize'] === 0) {
result.push(cachingTypes.cached);
} else if (entry['transferSize'] > 0 && (entry['encodedBodySize'] === 0 || entry['transferSize'] < entry['encodedBodySize'])) {
result.push(cachingTypes.validated);
} else {
result.push(cachingTypes.fullLoad);
}
if (entry['encodedBodySize'] != null) {
result.push(entry['encodedBodySize']);
} else {
result.push('');
}
if (entry['decodedBodySize'] != null) {
result.push(entry['decodedBodySize']);
} else {
result.push('');
}
if (entry['transferSize'] != null) {
result.push(entry['transferSize']);
} else {
result.push('');
}
} else {
result.push('');
result.push('');
result.push('');
result.push('');
}
var hasValidTimings = entry['responseStart'] != null && // timing allow origin check may have failed
entry['responseStart'] >= entry['fetchStart'];
if (hasValidTimings) {
result.push(calculateTiming(entry['redirectEnd'], entry['redirectStart']));
result.push(calculateTiming(entry['domainLookupStart'], entry['fetchStart']));
result.push(calculateTiming(entry['domainLookupEnd'], entry['domainLookupStart']));
if (entry['connectStart'] > 0 && entry['connectEnd'] > 0) {
if (entry['secureConnectionStart'] != null && entry['secureConnectionStart'] > 0) {
result.push(calculateTiming(entry['secureConnectionStart'], entry['connectStart']));
result.push(calculateTiming(entry['connectEnd'], entry['secureConnectionStart']));
} else {
result.push(calculateTiming(entry['connectEnd'], entry['connectStart']));
result.push('');
}
} else {
result.push('');
result.push('');
}
result.push(calculateTiming(entry['responseStart'], entry['requestStart']));
result.push(calculateTiming(entry['responseEnd'], entry['responseStart']));
}
var backendTraceId = '';
try {
var serverTimings = entry['serverTiming'];
if (serverTimings instanceof Array) {
for (var i = 0; i < serverTimings.length; i++) {
var serverTiming = serverTimings[i];
if (serverTiming['name'] === defaultVars.serverTimingBackendTraceIdEntryName) {
backendTraceId = serverTiming['description'];
}
}
}
} catch (e) {// Some browsers may not grant access to the field when the Timing-Allow-Origin
// check fails. Better be safe than sorry here.
}
result.push(backendTraceId);
if (hasValidTimings) {
result.push(calculateTiming(entry['responseStart'], entry['startTime']));
} else {
result.push('');
}
return result;
}
function serializeEntry(entry) {
return serializeEntryToArray(entry).join(',') // remove empty trailing timings
.replace(/,+$/, '');
}
function calculateTiming(a, b) {
if (a == null || b == null || // the values being equal indicates for example that a network connection didn't need
// to be established. Do not report a timing of '0' as this will skew the statistics.
a === b) {
return '';
}
var diff = Math.round(a - b);
if (diff < 0) {
return '';
}
return diff;
}
var dataUrlPrefix = 'data:';
var ignorePingsRegex = /.*\/ping(\/?$|\?.*)/i;
function isUrlIgnored(url) {
if (!url) {
return true;
} // Force string conversion. During runtime we have seen that some URLs passed into this code path aren't actually
// strings. Reason currently unknown.
url = String(url);
if (!url) {
return true;
} // We never want to track data URLs. Instead of matching these via regular expressions (which might be expensive),
// we are explicitly doing a startsWith ignore case check
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
if (url.substring == null || url.substring(0, dataUrlPrefix.length).toLowerCase() === dataUrlPrefix) {
return true;
}
if (defaultVars.ignorePings && ignorePingsRegex.test(url)) {
return true;
}
return matchesAny(defaultVars.ignoreUrls, url);
}
function isErrorMessageIgnored(message) {
return !message || matchesAny(defaultVars.ignoreErrorMessages, message);
}
var INTERNAL_END_MARKER = '<END>';
function createTrie() {
return new Trie();
}
function Trie() {
this.root = {};
}
Trie.prototype.addItem = function addItem(key, value) {
this.insertItem(this.root, key.split(''), 0, value);
return this;
};
Trie.prototype.insertItem = function insertItem(node, keyCharacters, keyCharacterIndex, value) {
var character = keyCharacters[keyCharacterIndex]; // Characters exhausted, add value to node
if (character == null) {
var values = node[INTERNAL_END_MARKER] = node[INTERNAL_END_MARKER] || [];
values.push(value);
return;
}
var nextNode = node[character] = node[character] || {};
this.insertItem(nextNode, keyCharacters, keyCharacterIndex + 1, value);
};
Trie.prototype.toJs = function toJs(node) {
node = node || this.root;
var keys = getKeys(node);
if (keys.length === 1 && keys[0] === INTERNAL_END_MARKER) {
return node[INTERNAL_END_MARKER].slice();
}
var result = {};
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i];
var value = node[key];
if (key === INTERNAL_END_MARKER) {
result['$'] = value.slice();
continue;
}
var combinedKeys = key;
var child = node[key];
var childKeys = getKeys(child);
while (childKeys.length === 1 && childKeys[0] !== INTERNAL_END_MARKER) {
combinedKeys += childKeys[0];
child = child[childKeys[0]];
childKeys = getKeys(child);
}
result[combinedKeys] = this.toJs(child);
}
return result;
};
function getKeys(obj) {
var result = [];
for (var key in obj) {
if (hasOwnProperty(obj, key)) {
result.push(key);
}
}
return result;
}
// See https://www.w3.org/TR/hr-time/
function addResourceTimings(beacon, minStartTime) {
if (isResourceTimingAvailable && win.JSON) {
var entries = getEntriesTransferFormat(performance.getEntriesByType('resource'), minStartTime);
beacon['res'] = win.JSON.stringify(entries);
} else {
info('Resource timing not supported.');
}
}
function getEntriesTransferFormat(performanceEntries, minStartTime) {
var trie = createTrie();
var lowerCaseReportingUrl = defaultVars.reportingUrl != null ? defaultVars.reportingUrl.toLowerCase() : null;
for (var i = 0, len = performanceEntries.length; i < len; i++) {
var entry = performanceEntries[i];
if (minStartTime != null && entry['startTime'] - defaultVars.highResTimestampReference + defaultVars.referenceTimestamp < minStartTime) {
continue;
} else if (entry['duration'] < 0) {
// Some old browsers do not properly implement resource timing. They report negative durations.
// Ignore instead of reporting these, as the data isn't usable.
continue;
}
var url = entry.name;
if (isUrlIgnored(url)) {
{
info('Will not include data about resource because resource URL is ignored via ignore rules.', entry);
}
continue;
}
var lowerCaseUrl = url.toLowerCase();
var initiatorType = entry['initiatorType'];
if (lowerCaseUrl === 'about:blank' || lowerCaseUrl.indexOf('javascript:') === 0 || // some iframe cases
// Data transmission can be visible as a resource. Do not report it.
lowerCaseReportingUrl != null && lowerCaseUrl.indexOf(lowerCaseReportingUrl) === 0) {
continue;
}
if (url.length > urlMaxLength) {
url = url.substring(0, urlMaxLength);
} // We provide more detailed XHR insights via our XHR instrumentation.
// The XHR instrumentation is available once the initialization was executed
// (which is completely synchronous).
if (initiatorType !== 'xmlhttprequest' || entry['startTime'] < defaultVars.highResTimestampReference) {
trie.addItem(url, serializeEntry(entry));
}
}
return trie.toJs();
}
// https://www.w3.org/TR/navigation-timing/
var pageLoadStartTimestamp = getPageLoadStartTimestamp();
function getPageLoadStartTimestamp() {
if (!isTimingAvailable) {
return defaultVars.initializerExecutionTimestamp;
}
return performance.timing.navigationStart;
}
function addTimingToPageLoadBeacon(beacon) {
if (!isTimingAvailable) {
// This is our absolute fallback mode where we only have
// approximations for speed information.
beacon['ts'] = pageLoadStartTimestamp - defaultVars.referenceTimestamp;
beacon['d'] = Number(event.time) - defaultVars.initializerExecutionTimestamp; // We add this as an extra property to the beacon so that
// a backend can decide whether it should include timing
// information in aggregated metrics. Since they are only
// approximations, this is not always desirable.
if (!isTimingAvailable) {
beacon['tim'] = '0';
}
return;
}
var timing = performance.timing;
var redirectTime = timing.redirectEnd - timing.redirectStart; // We don't use navigationStart since that includes unload times for the previous page.
var start = pageLoadStartTimestamp;
beacon['ts'] = start - defaultVars.referenceTimestamp; // This can happen when the user aborts the page load. In this case, the load event
// timing information is not available and will have the default value of "0".
if (timing.loadEventStart > 0) {
beacon['d'] = timing.loadEventStart - (timing.fetchStart || timing.navigationStart);
} else {
beacon['d'] = Number(event.time) - defaultVars.initializerExecutionTimestamp; // We have partial timing information, but since the load was aborted, we will
// mark it as missing to indicate that the information should be ignored in
// statistics.
beacon['tim'] = '0';
}
beacon['t_unl'] = timing.unloadEventEnd - timing.unloadEventStart;
beacon['t_red'] = redirectTime;
beacon['t_apc'] = timing.domainLookupStart - (timing.fetchStart || timing.redirectEnd || timing.unloadEventEnd || timing.navigationStart);
beacon['t_dns'] = timing.domainLookupEnd - timing.domainLookupStart;
if (timing.connectStart > 0 && timing.connectEnd > 0) {
if (timing.secureConnectionStart != null && timing.secureConnectionStart > 0 // Issue in the navigation timing spec: Secure connection start does not take
// connection reuse into consideration. At the time of writing (2020-07-11)
// the latest W3C Navigation Timing recommendation still contains this issue.
// The latest editor draft has these fixed (by linking to the resource timing
// spec instead of duplicating the information).
// For now a workaround to avoid these wrong timings seems to be the following.
&& timing.secureConnectionStart >= timing.connectStart) {
beacon['t_tcp'] = timing.secureConnectionStart - timing.connectStart;
beacon['t_ssl'] = timing.connectEnd - timing.secureConnectionStart;
} else {
beacon['t_tcp'] = timing.connectEnd - timing.connectStart;
beacon['t_ssl'] = 0;
}
}
beacon['t_req'] = timing.responseStart - timing.requestStart;
beacon['t_rsp'] = timing.responseEnd - timing.responseStart;
beacon['t_dom'] = timing.domContentLoadedEventStart - timing.domLoading;
beacon['t_chi'] = timing.loadEventEnd - timing.domContentLoadedEventStart;
beacon['t_bac'] = timing.responseStart - start;
beacon['t_fro'] = timing.loadEventEnd - timing.responseStart;
beacon['t_pro'] = timing.loadEventStart - timing.domLoading;
beacon['t_loa'] = timing.loadEventEnd - timing.loadEventStart;
beacon['t_ttfb'] = timing.responseStart - start;
addFirstPaintTimings(beacon, start);
}
function addFirstPaintTimings(beacon, start) {
if (!isResourceTimingAvailable) {
addFirstPaintFallbacks(beacon, start);
return;
}
var paintTimings = performance.getEntriesByType('paint');
var firstPaintFound = false;
for (var i = 0; i < paintTimings.length; i++) {
var paintTiming = paintTimings[i];
switch (paintTiming.name) {
case 'first-paint':
beacon['t_fp'] = paintTiming.startTime | 0;
firstPaintFound = true;
break;
case 'first-contentful-paint':
beacon['t_fcp'] = paintTiming.startTime | 0;
break;
}
}
if (!firstPaintFound) {
addFirstPaintFallbacks(beacon, start);
}
}
function addFirstPaintFallbacks(beacon, start) {
var firstPaint = null; // Chrome
if (win.chrome && win.chrome.loadTimes) {
// Convert to ms
firstPaint = win.chrome.loadTimes()['firstPaintTime'] * 1000;
} // IE
else if (typeof win.performance.timing['msFirstPaint'] === 'number') {
firstPaint = win.performance.timing['msFirstPaint'];
} // standard
else if (typeof win.performance.timing['firstPaint'] === 'number') {
firstPaint = win.performance.timing['firstPaint'];
} // First paint may not be available -OR- the browser may have never
// painted anything and thereby kept this value at 0.
if (firstPaint != null && firstPaint !== 0) {
beacon['t_fp'] = Math.round(firstPaint - start);
}
}
var isUnloading = false;
function onLastChance(fn) {
if (isUnloading) {
fn();
}
addEventListener(doc, 'visibilitychange', function () {
if (doc.visibilityState !== 'visible') {
fn();
}
}); // $FlowFixMe The type is correct, but flow doesn't think so. Ignore for now.
addEventListener(win, 'pagehide', function (event) {
if (event.persisted) {
isUnloading = true;
fn();
}
}); // Unload is needed to fix this bug:
// https://bugs.chromium.org/p/chromium/issues/detail?id=987409
addEventListener(win, 'unload', function () {}); // According to the spec visibilitychange should be a replacement for
// beforeunload, but the reality is different (as of 2019-04-17). Chrome will
// close tabs without firing visibilitychange. beforeunload on the other hand
// is fired.
addEventListener(win, 'beforeunload', function () {
isUnloading = true;
fn();
});
}
/*
* This file exists to resolve circular dependencies between
* lib/transmission/index.js -> lib/transmission/batched.js -> lib/hooks/XMLHttpRequest.js -> lib/transmission/index.js
*/
function disableMonitoringForXMLHttpRequest(xhr) {
var state = xhr[defaultVars.secretPropertyKey] = xhr[defaultVars.secretPropertyKey] || {};
state.ignored = true;
}
function addResourceTiming(beacon, resource) {
var timings = serializeEntryToArray(resource);
beacon['s_ty'] = getTimingValue(timings[3]);
beacon['s_eb'] = getTimingValue(timings[4]);
beacon['s_db'] = getTimingValue(timings[5]);
beacon['s_ts'] = getTimingValue(timings[6]);
beacon['t_red'] = getTimingValue(timings[7]);
beacon['t_apc'] = getTimingValue(timings[8]);
beacon['t_dns'] = getTimingValue(timings[9]);
beacon['t_tcp'] = getTimingValue(timings[10]);
beacon['t_ssl'] = getTimingValue(timings[11]);
beacon['t_req'] = getTimingValue(timings[12]);
beacon['t_rsp'] = getTimingValue(timings[13]);
if (timings[14]) {
beacon['bt'] = timings[14];
beacon['bc'] = 1;
}
beacon['t_ttfb'] = getTimingValue(timings[15]);
}
function getTimingValue(timing) {
if (typeof timing === 'number') {
return timing;
}
return undefined;
}
function addCorrelationHttpHeaders(fn, ctx, traceId) {
fn.call(ctx, 'X-INSTANA-T', traceId);
fn.call(ctx, 'X-INSTANA-S', traceId);
fn.call(ctx, 'X-INSTANA-L', '1,correlationType=web;correlationId=' + traceId);
}
// very easy to parse in a streaming fashion on the server-side. This format is a basic
// line-based encoding of key/value pairs. Each line contains a key/value pair.
//
// In contrast to form encoding, this encoding handles JSON much better.
function encode(beacons) {
var str = '';
for (var i = 0; i < beacons.length; i++) {
var beacon = beacons[i]; // Multiple beacons are separated by an empty line
str += '\n';
for (var key in beacon) {
if (hasOwnProperty(beacon, key)) {
var value = beacon[key];
if (value != null) {
str += '\n' + encodePart(key) + '\t' + encodePart(value);
}
}
}
}
return str.substring(2);
}
function encodePart(part) {
return String(part).replace(/\\/g, '\\\\').replace(/\n/g, '\\n').replace(/\t/g, '\\t');
}
var maxBatchedBeacons = 15;
var pendingBeacons = [];
var pendingBeaconTransmittingTimeout;
var isVisibilityApiSupported = typeof doc.visibilityState === 'string';
var isSupported = !!XMLHttpRequest && isVisibilityApiSupported && isSendBeaconApiSupported();
function isEnabled() {
return isSupported && defaultVars.beaconBatchingTime > 0;
} // We attempt batching of messages to be more efficient on the client, network and
// server-side. While the connection is either a persistent HTTP 2 connection or
// a HTTP 1.1 connection with keep-alive, there is still some overhead involved
// in having many small messages.
//
// For this reason we attempt batching. When batching we must be careful to
// force a transmission when the document is unloaded.
if (isSupported) {
onLastChance(transmit);
}
function sendBeacon$1(beacon) {
pendingBeacons.push(beacon);
if (pendingBeacons.length >= maxBatchedBeacons) {
transmit();
} else if (!isWindowHidden() && defaultVars.beaconBatchingTime > 0) {
// We cannot guarantee that we will ever get time to transmit data in a batched
// format when the window is hidden, as this might occur while the document is
// being unloaded. Immediately force a transmission in these cases.
if (pendingBeaconTransmittingTimeout == null) {
pendingBeaconTransmittingTimeout = setTimeout(transmit, defaultVars.beaconBatchingTime);
}
} else {
transmit();
}
}
function transmit() {
if (pendingBeaconTransmittingTimeout != null) {
clearTimeout(pendingBeaconTransmittingTimeout);
pendingBeaconTransmittingTimeout = null;
}
if (pendingBeacons.length === 0) {
return;
}
var serializedBeacons = encode(pendingBeacons); // clear the array
pendingBeacons.length = 0; // Empty beacons. Should never happen, but better be safe.
if (serializedBeacons.length === 0) {
return;
} // This will transmit a text/plain;charset=UTF-8 content type. This may not be what we
// want, but changing the content type via the Blob constructor currently
// breaks for cross-origin requests.
// https://bugs.chromium.org/p/chromium/issues/detail?id=490015
var sendBeaconState = isSendBeaconApiSupported() && sendBeacon(String(defaultVars.reportingUrl), serializedBeacons); // There are limits to the amount of data transmittable via the sendBeacon API.
// If it doesn't work via the sendBeacon, try it via plain old AJAX APIs
// as a last resort.
if (sendBeaconState === false) {
var xhr = new XMLHttpRequest();
disableMonitoringForXMLHttpRequest(xhr);
xhr.open('POST', String(defaultVars.reportingUrl), true);
xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8'); // Ensure that browsers do not try to automatically parse the response.
xhr.responseType = 'text';
xhr.timeout = defaultVars.xhrTransmissionTimeout;
xhr.send(serializedBeacons);
}
}
function isWindowHidden() {
return doc.visibilityState !== 'visible';
}
function isSendBeaconApiSupported() {
return typeof nav.sendBeacon === 'function';
}
function createExcessiveUsageIdentifier(opts) {
var maxCalls = opts.maxCalls || 4096;
var maxCallsPerTenMinutes = opts.maxCallsPerTenMinutes || 128;
var maxCallsPerTenSeconds = opts.maxCallsPerTenSeconds || 32;
var totalCalls = 0;
var totalCallsInLastTenMinutes = 0;
var totalCallsInLastTenSeconds = 0;
setInterval(function () {
totalCallsInLastTenMinutes = 0;
}, 1000 * 60 * 10);
setInterval(function () {
totalCallsInLastTenSeconds = 0;
}, 1000 * 10);
return function isExcessiveUsage() {
return ++totalCalls > maxCalls || ++totalCallsInLastTenMinutes > maxCallsPerTenMinutes || ++totalCallsInLastTenSeconds > maxCallsPerTenSeconds;
};
}
var maxLengthForImgRequest = 2000;
function sendBeacon$2(data) {
var str = stringify(data);
if (str.length === 0) {
return;
}
if (XMLHttpRequest && str.length > maxLengthForImgRequest) {
var xhr = new XMLHttpRequest();
disableMonitoringForXMLHttpRequest(xhr);
xhr.open('POST', String(defaultVars.reportingUrl), true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded;charset=UTF-8'); // Ensure that browsers do not try to automatically parse the response.
xhr.responseType = 'text';
xhr.timeout = defaultVars.xhrTransmissionTimeout;
xhr.send(str);
} else {
// Older browsers do not support the XMLHttpRequest API. This sucks and may
// result in a variety of issues, e.g. URL length restrictions. "Luckily", older
// browsers also lack support for advanced features such as resource timing.
// This should make this transmission via a GET request possible.
executeImageRequest(String(defaultVars.reportingUrl) + '?' + str);
}
}
function stringify(data) {
var str = '';
for (var key in data) {
if (hasOwnProperty(data, key)) {
var value = data[key];
if (value != null) {
str += '&' + encodeURIComponent(key) + '=' + encodeURIComponent(String(data[key]));
}
}
}
return str.substring(1);
}
var isExcessiveUsage = createExcessiveUsageIdentifier({
maxCalls: 8096,
maxCallsPerTenMinutes: 4096,
maxCallsPerTenSeconds: 128
});
function sendBeacon$3(data) {
if (isUrlIgnored(data['l'])) {
// data['l'] is a standardized property across all beacons to ensure that we do not accidentally transmit data
// about a page such as this.
{
info('Skipping transmission of beacon because document URL associated to the beacon is ignored by ignore rule.', data);
}
return;
}
{
info('Transmitting beacon', data);
}
if (isExcessiveUsage()) {
{
info('Reached the maximum number of beacons to transmit.');
}
return;
}
try {
if (isEnabled()) {
sendBeacon$1(data);
} else {
sendBeacon$2(data);
}
} catch (e) {
{
error('Failed to transmit beacon', e);
}
}
}
// $FlowFixMe: Find a way to define all properties beforehand so that flow doesn't complain about missing props.
var beacon = {
'ty': 'pl'
};
var state$1 = {
onEnter: function () {
addCommonBeaconProperties(beacon);
beacon['t'] = defaultVars.pageLoadTraceId;
beacon['bt'] = defaultVars.pageLoadBackendTraceId;
beacon['u'] = win.location.href;
beacon['ph'] = pageLoad;
addTimingToPageLoadBeacon(beacon);
addResourceTimings(beacon);
var beaconSent = false;
if (doc.visibilityState !== 'visible') {
{
info('Will not wait for additional page load beacon data because document.visibilityState is', doc.visibilityState);
}
sendPageLoadBeacon();
return;
}
setTimeout(sendPageLoadBeacon, defaultVars.maxMaitForPageLoadMetricsMillis);
onLastChance(sendPageLoadBeacon);
function sendPageLoadBeacon() {
if (!beaconSent) {
beaconSent = true;
sendBeacon$3(beacon);
}
}
},
getActiveTraceId: function () {
return null;
},
getActivePhase: function () {
return undefined;
}
};
var maxErrorsToReport = 100;
var maxStackSize = 30;
var reportedErrors = 0;
var maxSeenErrorsTracked = 20;
var numberOfDifferentErrorsSeen = 0;
var seenErrors = {};
var scheduledTransmissionTimeoutHandle; // We are wrapping global listeners. In these, we are catching and rethrowing errors.
// In older browsers, rethrowing errors actually manipulates the error objects. As a
// result, it is not possible to just mark an error as reported. The simplest way to
// avoid double reporting is to temporarily disable the global onError handler…
var ignoreNextOnError = false;
function ignoreNextOnErrorEvent() {
ignoreNextOnError = true;
}
function hookIntoGlobalErrorEvent() {
var globalOnError = win.onerror;
win.onerror = function (message, fileName, lineNumber, columnNumber, error) {
if (ignoreNextOnError) {
ignoreNextOnError = false;
if (typeof globalOnError === 'function') {
return globalOnError.apply(this, arguments);
}
return;
}
var stack = error && error.stack;
if (!stack) {
stack = 'at ' + fileName + ' ' + lineNumber;
if (columnNumber != null) {
stack += ':' + columnNumber;
}
}
onUnhandledError(message, stack);
if (typeof globalOnError === 'function') {
return globalOnError.apply(this, arguments);
}
};
}
function reportError(error, opts) {
if (!error) {
return;
}
if (typeof error === 'string') {
onUnhandledError(error, '', opts);
} else {
onUnhandledError(error['message'], error['stack'], opts);
}
}
function onUnhandledError(message, stack, opts) {
if (!message || reportedErrors > maxErrorsToReport) {
return;
}
if (isErrorMessageIgnored(message)) {
return;
}
if (numberOfDifferentErrorsSeen >= maxSeenErrorsTracked) {
seenErrors = {};
numberOfDifferentErrorsSeen = 0;
}
message = String(message).substring(0, 300);
stack = shortenStackTrace(stack);
var location = win.location.href;
var parentId = getActiveTraceId();
var key = message + stack + location + (parentId || '');
var trackedError = seenErrors[key];
if (trackedError) {
trackedError.seenCount++;
} else {
var componentStack = undefined;
if (opts && opts['componentStack']) {
componentStack = String(opts['componentStack']).substring(0, 4096);
}
trackedError = seenErrors[key] = {
message: message,
stack: stack,
componentStack: componentStack,
// $FlowFixMe Flow assumes that this value can be a string due to the bracket notation.
meta: opts ? opts['meta'] : undefined,
location: location,
parentId: parentId,
seenCount: 1,
transmittedCount: 0
};
numberOfDifferentErrorsSeen++;
}
scheduleTransmission();
}
function shortenStackTrace(stack) {
return String(stack || '').split('\n').slice(0, maxStackSize).join('\n');
}
function scheduleTransmission() {
if (scheduledTransmissionTimeoutHandle) {
return;
}
scheduledTransmissionTimeoutHandle = setTimeout(send, 1000);
}
function send() {
clearTimeout(scheduledTransmissionTimeoutHandle);
scheduledTransmissionTimeoutHandle = null;
for (var _key in seenErrors) {
if (seenErrors.hasOwnProperty(_key)) {
var seenError = seenErrors[_key];
if (seenError.seenCount > seenError.transmittedCount) {
sendBeaconForError(seenError);
reportedErrors++;
}
}
}
seenErrors = {};
numberOfDifferentErrorsSeen = 0;
}
function sendBeaconForError(error) {
var spanId = generateUniqueId();
var traceId = error.parentId || spanId; // $FlowFixMe
var beacon = {
'ty': 'err',
's': spanId,
't': traceId,
'ts': now(),
// error beacon specific data
'l': error.location,
'e': error.message,
'st': error.stack,
'cs': error.componentStack,
'c': error.seenCount - error.transmittedCount
};
addCommonBeaconProperties(beacon);
if (error.meta) {
addMetaDataToBeacon(beacon, error.meta);
}
sendBeacon$3(beacon);
}
var messagePrefix = 'Unhandled promise rejection: ';
var stackUnavailableMessage = '<unavailable because Promise wasn\'t rejected with an Error object>';
function hookIntoGlobalUnhandledRejectionEvent() {
if (typeof win.addEventListener === 'function') {
win.addEventListener('unhandledrejection', onUnhandledRejection);
}
}
function onUnhandledRejection(event) {
if (event.reason == null) {
reportError({
message: messagePrefix + '<no reason defined>',
stack: stackUnavailableMessage
});
} else if (typeof event.reason.message === 'string') {
reportError({
message: messagePrefix + event.reason.message,
stack: typeof event.reason.stack === 'string' ? event.reason.stack : stackUnavailableMessage
});
} else if (typeof event.reason !== 'object') {
reportError({
message: messagePrefix + event.reason,
stack: stackUnavailableMessage
});
}
}
var ONE_DAY_IN_MILLIS = 1000 * 60 * 60 * 24;
// Implements the capability to observe the performance data for a single entry on the performance timeline.
// This is especially useful to make a connection between our beacon data and the performance timeline data.
// Also see https://w3c.github.io/performance-timeline/#dom-performanceentrylist
function observeResourcePerformance(opts) {
if (!isPerformanceObserverAvailable) {
return observeWithoutPerformanceObserverSupport(opts.onEnd);
} // Used to calculate the duration when no resource was found.
var startTime;
var endTime; // The identified resource. To be used when calling opts.onEnd
var resource; // global resources that will need to be disposed
var observer;
var fallbackNoResourceFoundTimerHandle;
var fallbackEndNeverCalledTimerHandle;
return {
onBeforeResourceRetrieval: onBeforeResourceRetrieval,
onAfterResourceRetrieved: onAfterResourceRetrieved,
cancel: disposeGlobalResources
};
function onBeforeResourceRetrieval() {
startTime = performance.now();
try {
observer = new win['PerformanceObserver'](onResource);
observer['observe']({
'entryTypes': opts.entryTypes
});
} catch (e) {// Some browsers may not support the passed entryTypes and decide to throw an error.
// This would then result in an error with a message like:
//
// entryTypes only contained unsupported types
//
// Swallow and ignore the error. Treat it like unavailable performance observer data.
}
fallbackEndNeverCalledTimerHandle = setTimeout(disposeGlobalResources, 1000 * 60 * 10);
}
function onAfterResourceRetrieved() {
endTime = performance.now();
cancelFallbackEndNeverCalledTimerHandle();
if (resource || !isWaitingAcceptable()) {
end();
} else {
addEventListener(doc, 'visibilitychange', onVisibilityChanged);
fallbackNoResourceFoundTimerHandle = setTimeout(end, opts.maxWaitForResourceMillis);
}
}
function end() {
disposeGlobalResources();
var duration;
if (resource && resource.duration != null && // In some old web browsers, e.g. Chrome 31, the value provided as the duration
// can be very wrong. We have seen cases where this value is measured in years.
// If this does seem be the case, then we will ignore the duration property and
// instead prefer our approximation.
resource.duration < ONE_DAY_IN_MILLIS) {
duration = Math.round(resource.duration);
} else {
duration = Math.round(endTime - startTime);
}
opts.onEnd({
resource: resource,
duration: duration
});
}
function onResource(list) {
var entries = list.getEntries();
for (var i = 0; i < entries.length; i++) {
var entry = entries[i];
if (entry.startTime >= startTime && (!endTime || endTime >= entry.responseEnd) && opts.resourceMatcher(entry)) {
resource = entry;
disconnectResourceObserver();
if (endTime) {
// End as quickly as possible to ensure that the data is transmitted to the server.
end();
}
return;
}
}
}
function onVisibilityChanged() {
if (!isWaitingAcceptable()) {
end();
}
}
function disposeGlobalResources() {
disconnectResourceObserver();
cancelFallbackNoResourceFoundTimer();
cancelFallbackEndNeverCalledTimerHandle();
stopVisibilityObservation();
}
function disconnectResourceObserver() {
if (observer) {
try {
observer['disconnect']();
} catch (e) {// Observer disconnect may throw when connect attempt wasn't successful. Ignore this.
}
observer = null;
}
}
function cancelFallbackNoResourceFoundTimer() {
if (fallbackNoResourceFoundTimerHandle) {
clearTimeout(fallbackNoResourceFoundTimerHandle);
fallbackNoResourceFoundTimerHandle = null;
}
}
function cancelFallbackEndNeverCalledTimerHandle() {
if (fallbackEndNeverCalledTimerHandle) {
clearTimeout(fallbackEndNeverCalledTimerHandle);
fallbackEndNeverCalledTimerHandle = null;
}
}
function stopVisibilityObservation() {
removeEventListener(doc, 'visibilitychange', onVisibilityChanged);
}
} // This variant of the performance observer is only used when the performance-timeline features
// are not supported. See isPerformanceObserverAvailable
function observeWithoutPerformanceObserverSupport(onEnd) {
var start;
return {
onBeforeResourceRetrieval: onBeforeResourceRetrieval,
onAfterResourceRetrieved: onAfterResourceRetrieved,
cancel: noop
};
function onBeforeResourceRetrieval() {
start = now();
}
function onAfterResourceRetrieved() {
var end = now();
onEnd({
duration: end - start
});
}
} // We may only wait for resource data to arrive as long as the document is visible or in the process
// of becoming visible. In all other cases we might lose data when waiting, e.g. when the document
// is in the process of being disposed.
function isWaitingAcceptable() {
return doc.visibilityState === 'visible' || doc.visibilityState === 'prerender';
}
function isWhitelistedOrigin(url) {
return matchesAny(defaultVars.whitelistedOrigins, url);
}
var maximumHttpRequestUrlLength = 4096; // Asynchronously created a tag.
var urlAnalysisElement = null;
try {
urlAnalysisElement = document.createElement('a');
} catch (e) {
{
debug('Failed to create URL analysis element. Will not be able to normalize URLs.', e);
}
}
function normalizeUrl(url) {
if (urlAnalysisElement) {
try {
// "a"-elements normalize the URL when setting a relative URL or URLs
// that are missing a scheme
urlAnalysisElement.href = url;
url = urlAnalysisElement.href;
} catch (e) {
{
debug('Failed to normalize URL' + url);
}
}
} // Hashes are never transmitted to the server and they are also not included in resource
// timings. Do not include them in the normalized URL.
var hashIndex = url.indexOf('#');
if (hashIndex >= 0) {
url = url.substring(0, hashIndex);
}
if (url.length > maximumHttpRequestUrlLength) {
url = url.substring(0, maximumHttpRequestUrlLength);
}
return url;
}
// document.createElement('a')
var urlAnalysisElement$1 = null;
var documentOriginAnalysisElement = null;
try {
urlAnalysisElement$1 = document.createElement('a');
documentOriginAnalysisElement = document.createElement('a');
documentOriginAnalysisElement.href = win.location.href;
} catch (e) {
{
debug('Failed to create URL analysis elements. Will not be able to execute same-origin check, i.e. all same-origin checks will fail.', e);
}
}
function isSameOrigin(url) {
if (!urlAnalysisElement$1 || !documentOriginAnalysisElement) {
return false;
}
try {
urlAnalysisElement$1.href = url;
return (// Most browsers support this fallback logic out of the box. Not so the Internet explorer.
// To make it work in Internet explorer, we need to add the fallback manually.
// IE 9 uses a colon as the protocol when no protocol is defined
(urlAnalysisElement$1.protocol && urlAnalysisElement$1.protocol !== ':' ? urlAnalysisElement$1.protocol : documentOriginAnalysisElement.protocol) === documentOriginAnalysisElement.protocol && (urlAnalysisElement$1.hostname || documentOriginAnalysisElement.hostname) === documentOriginAnalysisElement.hostname && (urlAnalysisElement$1.port || documentOriginAnalysisElement.port) === documentOriginAnalysisElement.port
);
} catch (e) {
return false;
}
}
var isExcessiveUsage$1 = createExcessiveUsageIdentifier({
maxCallsPerTenMinutes: 256,
maxCallsPerTenSeconds: 32
}); // In addition to the common HTTP status codes, a bunch of
// additional outcomes are possible. Mainly errors, the following
// status codes denote internal codes which are used for beacons
// to describe the XHR result.
var additionalStatuses = {
// https://xhr.spec.whatwg.org/#the-timeout-attribute
timeout: -100,
// Used when the request is aborted:
// https://xhr.spec.whatwg.org/#the-abort()-method
abort: -101,
// Errors may occur when opening an XHR object for a variety of
// reasons.
// https://xhr.spec.whatwg.org/#the-open()-method
openError: -102,
// Non-HTTP errors, e.g. failed to establish connection.
// https://xhr.spec.whatwg.org/#events
error: -103
};
var traceIdHeaderRegEx = /^X-INSTANA-T$/i;
function instrumentXMLHttpRequest() {
if (!XMLHttpRequest || !new XMLHttpRequest().addEventListener) {
{
info('Browser does not support the features required for XHR instrumentation.');
}
return;
}
var originalOpen = XMLHttpRequest.prototype.open;
var originalSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
var originalSend = XMLHttpRequest.prototype.send;
if (!originalOpen || !originalSetRequestHeader || !originalSend) {
{
warn('The XMLHttpRequest prototype is in an unsupported state due to some missing XMLHttpRequest.prototype ' + 'properties. This is most likely caused by third-party libraries that are instrumenting/changing the ' + 'XMLHttpRequest API in a specification incompliant way.');
}
return;
}
XMLHttpRequest.prototype.open = function open(method, url, async) {
var xhr = this;
if (isExcessiveUsage$1()) {
{
info('Reached the maximum number of XMLHttpRequests to monitor.');
}
return originalOpen.apply(xhr, arguments);
}
var state = xhr[defaultVars.secretPropertyKey] = xhr[defaultVars.secretPropertyKey] || {}; // probably ignored due to disableMonitoringForXMLHttpRequest calls
if (state.ignored) {
return originalOpen.apply(xhr, arguments);
}
state.ignored = isUrlIgnored(url);
if (state.ignored) {
{
debug('Not generating XHR beacon because it should be ignored according to user configuration. URL: ' + url);
}
return originalOpen.apply(xhr, arguments);
}
state.spanAndTraceId = generateUniqueId();
state.setBackendCorrelationHeaders = isSameOrigin(url) || isWhitelistedOrigin(url); // $FlowFixMe: Some properties deliberately left our for js file size reasons.
var beacon = {
'ty': 'xhr',
// general beacon data
't': state.spanAndTraceId,
's': state.spanAndTraceId,
'ts': 0,
'd': 0,
// xhr beacon specific data
// 's': '',
'm': method,
'u': normalizeUrl(url),
'a': async === undefined || async ? 1 : 0,
'st': 0,
'e': undefined,
'bc': state.setBackendCorrelationHeaders ? 1 : 0
};
state.beacon = beacon;
state.performanceObserver = observeResourcePerformance({
entryTypes: ['resource'],
resourceMatcher: function resourceMatcher(resource) {
return (resource.initiatorType === 'fetch' || resource.initiatorType === 'xmlhttprequest') && // $FlowFixMe We know that beacon['u'] is now set
!!resource.name && resource.name.indexOf(beacon['u']) === 0;
},
maxWaitForResourceMillis: defaultVars.maxWaitForResourceTimingsMillis,
onEnd: function onEnd(args) {
beacon['d'] = args.duration;
if (args.resource) {
addResourceTiming(beacon, args.resource);
}
sendBeacon$3(beacon);
}
});
try {
var result = originalOpen.apply(xhr, arguments);
xhr.addEventListener('timeout', onTimeout);
xhr.addEventListener('error', onError);
xhr.addEventListener('abort', onAbort);
xhr.addEventListener('readystatechange', onReadystatechange);
return result;
} catch (e) {
state.performanceObserver.cancel();
beacon['ts'] = now() - defaultVars.referenceTimestamp;
beacon['st'] = additionalStatuses.openError;
beacon['e'] = e.message;
addCommonBeaconProperties(beacon);
sendBeacon$3(beacon);
xhr[defaultVars.secretPropertyKey] = null;
throw e;
}
function onFinish(status) {
if (state.ignored) {
return;
}
if (beacon['st'] !== 0) {
// Multiple finish events. Should only happen when we setup the event handlers
// in a wrong way or when the XHR object is reused. We don't support this use
// case.
return;
}
beacon['st'] = status; // When accessing object properties as object['property'] instead of
// object.property flow does not know the type and assumes string.
// Arithmetic operations like addition are only allowed on numbers. OTOH,
// we can not safely use beacon.property as the compilation/minification
// step will rename the properties which results in JSON payloads with
// wrong property keys.
// $FlowFixMe: see above
beacon['d'] = Math.max(0, now() - (beacon['ts'] + defaultVars.referenceTimestamp));
if (state.performanceObserver && status > 0) {
state.performanceObserver.onAfterResourceRetrieved();
} else {
if (state.performanceObserver) {
state.performanceObserver.cancel();
}
sendBeacon$3(beacon);
}
}
function onTimeout() {
onFinish(additionalStatuses.timeout);
}
function onError(e) {
if (state.ignored) {
return;
}
var message = e && (e.error && e.error.message || e.message);
if (typeof message === 'string') {
beacon['e'] = message.substring(0, 300);
}
onFinish(additionalStatuses.error);
}
function onAbort() {
onFinish(additionalStatuses.abort);
}
function onReadystatechange() {
if (xhr.readyState === 4) {
var status;
try {
status = xhr.status;
} catch (e) {
// IE 9 will throw errors when trying to access the status property
// on aborted requests and timeouts. We can swallow the error
// since we have separate event listeners for these types of
// situations.
onFinish(additionalStatuses.error);
return;
}
if (status !== 0) {
onFinish(status);
}
}
}
};
XMLHttpRequest.prototype.setRequestHeader = function setRequestHeader(header) {
var state = this[defaultVars.secretPropertyKey]; // If this request was initiated by a fetch polyfill, the Instana headers
// will be set before xhr.send is called (by the fetch polyfill,
// translating the headers from the request definition object into
// XHR.setRequestHeader calls). We need to keep track of this so we can
// set this XHR to ignored in xhr.send.
if (state && traceIdHeaderRegEx.test(header)) {
{
debug('Not generating XHR beacon because correlation header is already set (possibly fetch polyfill applied).');
}
state.ignored = true;
if (state.performanceObserver) {
state.performanceObserver.cancel();
state.performanceObserver = null;
}
}
return originalSetRequestHeader.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function send() {
var state = this[defaultVars.secretPropertyKey];
if (!state || state.ignored) {
return originalSend.apply(this, arguments);
}
if (state.setBackendCorrelationHeaders) {
addCorrelationHttpHeaders(originalSetRequestHeader, this, state.spanAndTraceId);
}
state.beacon['ts'] = now() - defaultVars.referenceTimestamp;
addCommonBeaconProperties(state.beacon);
state.performanceObserver.onBeforeResourceRetrieval();
return originalSend.apply(this, arguments);
};
}
function getPageLoadBackendTraceId() {
if (!isResourceTimingAvailable) {
return null;
}
var entries = performance.getEntriesByType('navigation');
for (var i = 0; i < entries.length; i++) {
var entry = entries[i];
if (entry['serverTiming'] != null) {
for (var j = 0; j < entry['serverTiming'].length; j++) {
var serverTiming = entry['serverTiming'][j];
if (serverTiming['name'] === defaultVars.serverTimingBackendTraceIdEntryName) {
{
info('Found page load backend trace ID %s in Server-Timing header.', serverTiming['description']);
}
return serverTiming['description'];
}
}
}
}
return null;
}
// https://github.com/facebook/flow/blob/master/lib/dom.js
// Asynchronous function wrapping: The process of wrapping a listener which goes into one function, e.g.
//
// - EventTarget#addEventListener
// - EventEmitter#on
//
// and is removed via another function, e.g.
//
// - EventTarget#removeEventListener
// - EventEmitter#off
//
// What is complicated about this, is that these methods identify registered listeners by function reference.
// When we wrap a function, we naturally change the reference. We must therefore keep track of which
// original function belongs to what wrapped function.
//
// This file provides helpers that help in the typical cases. It is removed from all browser specific APIs
// in order to allow simple unit test execution.
//
// Note that this file follows the behavior outlined in DOM specification. Among others, this means that it is not
// possible to register the same listener twice.
// http://dom.spec.whatwg.org
function addWrappedFunction(storageTarget, wrappedFunction, valuesForEqualityCheck) {
var storage = storageTarget[defaultVars.wrappedEventHandlersOriginalFunctionStorageKey] = storageTarget[defaultVars.wrappedEventHandlersOriginalFunctionStorageKey] || [];
var index = findInStorage(storageTarget, valuesForEqualityCheck);
if (index !== -1) {
// already registered. Do not allow re-registration
return storage[index].wrappedFunction;
}
storage.push({
wrappedFunction: wrappedFunction,
valuesForEqualityCheck: valuesForEqualityCheck
});
return wrappedFunction;
}
function findInStorage(storageTarget, valuesForEqualityCheck) {
var storage = storageTarget[defaultVars.wrappedEventHandlersOriginalFunctionStorageKey];
for (var i = 0; i < storage.length; i++) {
var storageItem = storage[i];
if (matchesEqualityCheck(storageItem.valuesForEqualityCheck, valuesForEqualityCheck)) {
return i;
}
}
return -1;
}
function popWrappedFunction(storageTarget, valuesForEqualityCheck, fallback) {
var storage = storageTarget[defaultVars.wrappedEventHandlersOriginalFunctionStorageKey];
if (storage == null) {
return fallback;
}
var index = findInStorage(storageTarget, valuesForEqualityCheck);
if (index === -1) {
return fallback;
}
var storageItem = storage[index];
storage.splice(index, 1);
return storageItem.wrappedFunction;
}
function matchesEqualityCheck(valuesForEqualityCheckA, valuesForEqualityCheckB) {
if (valuesForEqualityCheckA.length !== valuesForEqualityCheckB.length) {
return false;
}
for (var i = 0; i < valuesForEqualityCheckA.length; i++) {
if (valuesForEqualityCheckA[i] !== valuesForEqualityCheckB[i]) {
return false;
}
}
return true;
}
function addWrappedDomEventListener(storageTarget, wrappedFunction, eventName, eventListener, optionsOrCapture) {
return addWrappedFunction(storageTarget, wrappedFunction, getDomEventListenerValuesForEqualityCheck(eventName, eventListener, optionsOrCapture));
}
function getDomEventListenerValuesForEqualityCheck(eventName, eventListener, optionsOrCapture) {
return [eventName, eventListener, getDomEventListenerCaptureValue(optionsOrCapture)];
}
function getDomEventListenerCaptureValue(optionsOrCapture) {
// > Let capture, passive, and once be the result of flattening more options.
// https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener
//
// > To flatten more options, run these steps:
// > 1. Let capture be the result of flattening options.
// https://dom.spec.whatwg.org/#event-flatten-more
//
// > To flatten options, run these steps:
// > 1. If options is a boolean, then return options.
// > 2. Return options’s capture.
// https://dom.spec.whatwg.org/#concept-flatten-options
//
// > dictionary EventListenerOptions {
// > boolean capture = false;
// > };
// https://dom.spec.whatwg.org/#dom-eventlisteneroptions-capture
if (optionsOrCapture == null) {
return false;
} else if (typeof optionsOrCapture === 'object') {
return Boolean(optionsOrCapture.capture);
}
return Boolean(optionsOrCapture);
}
function popWrappedDomEventListener(storageTarget, eventName, eventListener, optionsOrCapture, fallback) {
return popWrappedFunction(storageTarget, getDomEventListenerValuesForEqualityCheck(eventName, eventListener, optionsOrCapture), fallback);
}
function wrapEventHandlers() {
if (defaultVars.wrapEventHandlers) {
wrapEventTarget(win.EventTarget);
}
}
function wrapEventTarget(EventTarget) {
if (!EventTarget || typeof EventTarget.prototype.addEventListener !== 'function' || typeof EventTarget.prototype.removeEventListener !== 'function') {
return;
}
var originalAddEventListener = EventTarget.prototype.addEventListener;
var originalRemoveEventListener = EventTarget.prototype.removeEventListener;
EventTarget.prototype.addEventListener = function wrappedAddEventListener(eventName, fn, optionsOrCapture) {
if (typeof fn !== 'function') {
return originalAddEventListener.apply(this, arguments);
} // non-deopt arguments copy
var args = new Array(arguments.length);
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
args[1] = function wrappedEventListener() {
try {
return fn.apply(this, arguments);
} catch (e) {
reportError(e);
ignoreNextOnErrorEvent();
throw e;
}
};
args[1] = addWrappedDomEventListener(this, args[1], eventName, fn, optionsOrCapture);
return originalAddEventListener.apply(this, args);
};
EventTarget.prototype.removeEventListener = function wrappedRemoveEventListener(eventName, fn, optionsOrCapture) {
if (typeof fn !== 'function') {
return originalRemoveEventListener.apply(this, arguments);
} // non-deopt arguments copy
var args = new Array(arguments.length);
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
args[1] = popWrappedDomEventListener(this, eventName, fn, optionsOrCapture, fn);
return originalRemoveEventListener.apply(this, args);
};
}
var isExcessiveUsage$2 = createExcessiveUsageIdentifier({
maxCallsPerTenMinutes: 128,
maxCallsPerTenSeconds: 32
});
function reportCustomEvent(eventName, opts) {
if (isExcessiveUsage$2()) {
{
info('Reached the maximum number of custom events to monitor');
}
return;
}
var traceId = getActiveTraceId();
var spanId = generateUniqueId();
if (!traceId) {
traceId = spanId;
} // $FlowFixMe: Some properties deliberately left our for js file size reasons.
var beacon = {
'ty': 'cus',
's': spanId,
't': traceId,
'ts': now(),
'n': eventName
};
addCommonBeaconProperties(beacon);
if (opts) {
enrich(beacon, opts);
}
sendBeacon$3(beacon);
}
function enrich(beacon, opts) {
if (opts['meta']) {
addMetaDataToBeacon(beacon, opts['meta']);
}
if (typeof opts['duration'] === 'number' && !isNaN(opts['duration'])) {
beacon['d'] = opts['duration']; // $FlowFixMe: We know that both properties are numbers. Flow thinks they are strings because we access them via […].
beacon['ts'] = beacon['ts'] - opts['duration'];
}
if (typeof opts['timestamp'] === 'number' && !isNaN(opts['timestamp'])) {
beacon['ts'] = opts['timestamp'];
}
if (typeof opts['backendTraceId'] === 'string') {
beacon['bt'] = opts['backendTraceId'].substring(0, 64);
}
if (opts['error']) {
beacon['e'] = String(opts['error']['message']).substring(0, 300);
beacon['st'] = shortenStackTrace(opts['error']['stack']);
}
if (typeof opts['componentStack'] === 'string') {
beacon['cs'] = opts['componentStack'].substring(0, 4096);
}
}
function hookIntoUserTimings() {
if (performance && performance['timeOrigin'] && isResourceTimingAvailable) {
drainExistingPerformanceEntries();
observeNewUserTimings();
}
}
function drainExistingPerformanceEntries() {
onUserTimings(performance.getEntriesByType('mark'));
onUserTimings(performance.getEntriesByType('measure'));
}
function onUserTimings(performanceEntries) {
for (var i = 0; i < performanceEntries.length; i++) {
onUserTiming(performanceEntries[i]);
}
}
function onUserTiming(performanceEntry) {
if (matchesAny(defaultVars.ignoreUserTimings, performanceEntry.name)) {
{
info('Ignoring user timing "%s" because it is ignored via the configuration.', performanceEntry.name);
}
return;
}
var duration;
if (performanceEntry.entryType !== 'mark') {
duration = Math.round(performanceEntry.duration);
} // $FlowFixMe: Flow cannot detect that this is a proper usage of the function. We have to write it this way because of the Closure compiler advanced mode.
reportCustomEvent(performanceEntry.name, {
// Do not allow the timestamp to be before our Notion of page load start.
'timestamp': Math.max(pageLoadStartTimestamp, Math.round(performance['timeOrigin'] + performanceEntry.startTime)),
'duration': duration,
'meta': {
'userTimingType': performanceEntry.entryType
}
});
}
function observeNewUserTimings() {
if (isPerformanceObserverAvailable) {
try {
var observer = new win['PerformanceObserver'](onObservedPerformanceEntries);
observer['observe']({
'entryTypes': ['mark', 'measure']
});
} catch (e) {// Some browsers may not support the passed entryTypes and decide to throw an error.
// This would then result in an error with a message like:
//
// entryTypes only contained unsupported types
//
// Swallow and ignore the error. Treat it like unavailable performance observer data.
}
}
}
function onObservedPerformanceEntries(list) {
onUserTimings(list.getEntries());
}
var isExcessiveUsage$3 = createExcessiveUsageIdentifier({
maxCallsPerTenMinutes: 256,
maxCallsPerTenSeconds: 32
});
function instrumentFetch() {
if (!win.fetch || !win.Request) {
{
info('Browser does not support the Fetch API.');
}
return;
}
win.fetch = function (input, init) {
var request = new Request(input, init);
if (isExcessiveUsage$3()) {
{
info('Reached the maximum number of fetch calls to monitor.');
}
return originalFetch(request);
}
var url = request.url;
if (isUrlIgnored(url)) {
{
debug('Not generating XHR beacon for fetch call because it is to be ignored according to user configuration. URL: ' + url);
}
return originalFetch(request);
} // $FlowFixMe: Some properties deliberately left our for js file size reasons.
var beacon = {
'ty': 'xhr',
// 't': '',
'ts': now() - defaultVars.referenceTimestamp,
'd': 0,
// xhr beacon specific data
// 's': '',
'm': '',
'u': '',
'a': 1,
'st': 0,
'e': undefined
};
addCommonBeaconProperties(beacon);
addGraphQlProperties(beacon, input, init);
var spanAndTraceId = generateUniqueId();
var setBackendCorrelationHeaders = isSameOrigin(url) || isWhitelistedOrigin(url);
beacon['t'] = spanAndTraceId;
beacon['s'] = spanAndTraceId;
beacon['m'] = request.method;
beacon['u'] = normalizeUrl(url);
beacon['a'] = 1;
beacon['bc'] = setBackendCorrelationHeaders ? 1 : 0;
if (setBackendCorrelationHeaders) {
addCorrelationHttpHeaders(request.headers.append, request.headers, spanAndTraceId);
}
var performanceObserver = observeResourcePerformance({
entryTypes: ['resource'],
resourceMatcher: resourceMatcher,
maxWaitForResourceMillis: defaultVars.maxWaitForResourceTimingsMillis,
onEnd: onEnd
});
performanceObserver.onBeforeResourceRetrieval();
return originalFetch(request).then(function (response) {
beacon['st'] = response.status; // When accessing object properties as object['property'] instead of
// object.property flow does not know the type and assumes string.
// Arithmetic operations like addition are only allowed on numbers. OTOH,
// we can not safely use beacon.property as the compilation/minification
// step will rename the properties which results in JSON payloads with
// wrong property keys.
// $FlowFixMe: see above
performanceObserver.onAfterResourceRetrieved();
return response;
}, function (e) {
performanceObserver.cancel(); // $FlowFixMe: see above
beacon['d'] = now() - (beacon['ts'] + defaultVars.referenceTimestamp);
beacon['e'] = e.message;
beacon['st'] = -103;
sendBeacon$3(beacon);
throw e;
});
function resourceMatcher(resource) {
return (resource.initiatorType === 'fetch' || resource.initiatorType === 'xmlhttprequest') && // $FlowFixMe We know that beacon['u'] is now set
Boolean(resource.name) && resource.name.indexOf(beacon['u']) === 0;
}
function onEnd(args) {
beacon['d'] = args.duration;
if (args.resource) {
addResourceTiming(beacon, args.resource);
}
sendBeacon$3(beacon);
}
};
}
var queryIdentification = /^\s*query(\s|\{)/i;
var mutationIdentification = /^\s*mutation(\s|\{)/i;
function addGraphQlProperties(beacon, input, init) {
try {
if (typeof input !== 'string' || !init || init.method !== 'POST' || typeof init.body !== 'string' || !matchesAny(defaultVars.urlsToCheckForGraphQlInsights, input)) {
return;
}
var body = JSON.parse(init.body);
if (typeof body['operationName'] === 'string') {
beacon['gon'] = body['operationName'];
}
if (typeof body['query'] === 'string') {
if (queryIdentification.test(body['query'])) {
beacon['got'] = 'query';
} else if (mutationIdentification.test(body['query'])) {
beacon['got'] = 'mutation';
} else if (body['query'].indexOf('{') === 0 && body['operationName'] === null) {
beacon['got'] = 'query';
}
}
} catch (e) {
{
debug('Failed to analyze request for GraphQL insights.', input, init);
}
}
}
// localStorage API re-exposed to allow testing.
var isSupported$1 = localStorage != null && typeof localStorage.getItem === 'function' && typeof localStorage.setItem === 'function';
function getItem(k) {
if (isSupported$1 && localStorage) {
return localStorage.getItem(k);
}
}
function setItem(k, v) {
if (isSupported$1 && localStorage) {
localStorage.setItem(k, v);
}
}
function removeItem(k) {
if (isSupported$1 && localStorage) {
localStorage.removeItem(k);
}
}
var storageSeparatorKey = '#';
function trackSessions(sessionInactivityTimeoutMillis, sessionTerminationTimeoutMillis) {
if (!isSupported$1) {
{
info('Storage API is not available and session tracking is therefore not supported.');
}
return;
}
if (!sessionInactivityTimeoutMillis) {
sessionInactivityTimeoutMillis = defaultVars.defaultSessionInactivityTimeoutMillis;
}
if (!sessionTerminationTimeoutMillis) {
sessionTerminationTimeoutMillis = defaultVars.defaultSessionTerminationTimeoutMillis;
}
sessionInactivityTimeoutMillis = Math.min(sessionInactivityTimeoutMillis, defaultVars.maxAllowedSessionTimeoutMillis);
sessionTerminationTimeoutMillis = Math.min(sessionTerminationTimeoutMillis, defaultVars.maxAllowedSessionTimeoutMillis);
try {
var storedValue = getItem(defaultVars.sessionStorageKey);
var session = parseSession(storedValue);
if (session && !isSessionValid(session, sessionInactivityTimeoutMillis, sessionTerminationTimeoutMillis)) {
session = null;
}
if (session) {
session.lastActivityTime = now();
} else {
session = {
id: generateUniqueId(),
startTime: now(),
lastActivityTime: now()
};
}
setItem(defaultVars.sessionStorageKey, serializeSession(session));
defaultVars.sessionId = session.id;
} catch (e) {
{
warn('Failed to record session information', e);
}
}
}
function terminateSession() {
defaultVars.sessionId = undefined;
if (!isSupported$1) {
return;
}
try {
removeItem(defaultVars.sessionStorageKey);
} catch (e) {
{
info('Failed to terminate session', e);
}
}
}
function parseSession(storedValue) {
if (!storedValue) {
return null;
}
var values = storedValue.split(storageSeparatorKey);
if (values.length < 3) {
return null;
}
var id = values[0];
var startTime = parseInt(values[1], 10);
var lastActivityTime = parseInt(values[2], 10);
if (!id || isNaN(startTime) || isNaN(lastActivityTime)) {
return null;
}
return {
id: id,
startTime: startTime,
lastActivityTime: lastActivityTime
};
}
function serializeSession(session) {
return session.id + storageSeparatorKey + session.startTime + storageSeparatorKey + session.lastActivityTime;
}
function isSessionValid(session, sessionInactivityTimeoutMillis, sessionTerminationTimeoutMillis) {
var minAllowedLastActivityTime = now() - sessionInactivityTimeoutMillis;
if (session.lastActivityTime < minAllowedLastActivityTime) {
return false;
}
var minAllowedStartTime = now() - sessionTerminationTimeoutMillis;
if (session.startTime < minAllowedStartTime) {
return false;
}
return true;
}
var isExcessiveUsage$4 = createExcessiveUsageIdentifier({
maxCallsPerTenMinutes: 128,
maxCallsPerTenSeconds: 32
});
function setPage(page) {
var previousPage = defaultVars.page;
defaultVars.page = page;
var isInitialPageDefinition = getActivePhase() === pageLoad && previousPage == null;
if (!isInitialPageDefinition && previousPage !== page) {
if (isExcessiveUsage$4()) {
{
info('Reached the maximum number of page changes to monitor.');
}
} else {
reportPageChange();
}
}
}
function reportPageChange() {
// $FlowFixMe: Some properties deliberately left our for js file size reasons.
var beacon = {
'ty': 'pc',
'ts': now()
};
addCommonBeaconProperties(beacon);
sendBeacon$3(beacon);
}
function processCommand(command) {
switch (command[0]) {
case 'apiKey':
defaultVars.apiKey = command[1];
break;
case 'key':
defaultVars.apiKey = command[1];
break;
case 'reportingUrl':
defaultVars.reportingUrl = command[1];
break;
case 'meta':
defaultVars.meta[command[1]] = command[2];
break;
case 'traceId':
defaultVars.pageLoadBackendTraceId = command[1];
break;
case 'ignoreUrls':
{
validateRegExpArray('ignoreUrls', command[1]);
}
defaultVars.ignoreUrls = command[1];
break;
case 'ignoreErrorMessages':
{
validateRegExpArray('ignoreErrorMessages', command[1]);
}
defaultVars.ignoreErrorMessages = command[1];
break;
case 'whitelistedOrigins':
{
validateRegExpArray('whitelistedOrigins', command[1]);
}
defaultVars.whitelistedOrigins = command[1];
break;
case 'ignoreUserTimings':
{
validateRegExpArray('ignoreUserTimings', command[1]);
}
defaultVars.ignoreUserTimings = command[1];
break;
case 'xhrTransmissionTimeout':
defaultVars.xhrTransmissionTimeout = command[1];
break;
case 'page':
setPage(command[1]);
break;
case 'ignorePings':
defaultVars.ignorePings = command[1];
break;
case 'reportError':
reportError(command[1], command[2]);
break;
case 'wrapEventHandlers':
defaultVars.wrapEventHandlers = command[1];
break;
case 'wrapTimers':
defaultVars.wrapTimers = command[1];
break;
case 'getPageLoadId':
return defaultVars.pageLoadTraceId;
case 'user':
if (command[1]) {
defaultVars.userId = String(command[1]).substring(0, 128);
}
if (command[2]) {
defaultVars.userName = String(command[2]).substring(0, 128);
}
if (command[3]) {
defaultVars.userEmail = String(command[3]).substring(0, 128);
}
break;
case 'reportEvent':
reportCustomEvent(command[1], command[2]);
break;
case 'beaconBatchingTime':
defaultVars.beaconBatchingTime = command[1];
break;
case 'maxWaitForResourceTimingsMillis':
defaultVars.maxWaitForResourceTimingsMillis = command[1];
break;
case 'maxMaitForPageLoadMetricsMillis':
defaultVars.maxMaitForPageLoadMetricsMillis = command[1];
break;
case 'trackSessions':
trackSessions(command[1], command[2]);
break;
case 'terminateSession':
terminateSession();
break;
case 'urlsToCheckForGraphQlInsights':
{
validateRegExpArray('urlsToCheckForGraphQlInsights', command[1]);
}
defaultVars.urlsToCheckForGraphQlInsights = command[1];
break;
default:
{
warn('Unsupported command: ' + command[0]);
}
break;
}
}
function validateRegExpArray(name, arr) {
if (!(arr instanceof Array)) {
return warn(name + ' is not an array. This will result in errors.');
}
for (var i = 0, len = arr.length; i < len; i++) {
if (!(arr[i] instanceof RegExp)) {
return warn(name + '[' + i + '] is not a RegExp. This will result in errors.');
}
}
}
function wrapTimers() {
if (defaultVars.wrapTimers) {
if (isRunningZoneJs) {
{
warn('We discovered a usage of Zone.js. In order to avoid any incompatibility issues timer wrapping is not going to be enabled.');
}
return;
}
wrapTimer('setTimeout');
wrapTimer('setInterval');
}
}
function wrapTimer(name) {
var original = win[name];
if (typeof original !== 'function') {
// cannot wrap because fn is not a function – should actually never happen
return;
}
win[name] = function wrappedTimerSetter(fn) {
// non-deopt arguments copy
var args = new Array(arguments.length);
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
args[0] = wrap(fn);
return original.apply(this, args);
};
}
function wrap(fn) {
if (typeof fn !== 'function') {
// cannot wrap because fn is not a function
return fn;
}
return function wrappedTimerHandler() {
try {
return fn.apply(this, arguments);
} catch (e) {
reportError(e);
ignoreNextOnErrorEvent();
throw e;
}
};
}
// $FlowFixMe Flow doesn't find the file. Let's ignore this for now.
function addWebVitals(beacon) {}
var state$2 = {
onEnter: function () {
if (!fulfillsPrerequisites()) {
warn('Browser does not have all the required features for web monitoring.');
}
var globalObjectName = win[defaultVars.nameOfLongGlobal];
var globalObject = win[globalObjectName];
if (!globalObject) {
{
warn('global ' + defaultVars.nameOfLongGlobal + ' not found. Did you use the initializer?');
}
return;
}
if (!globalObject.q) {
{
warn('Command queue not defined. Did you add the tracking script multiple times to your website?');
}
return;
}
if (typeof globalObject['l'] !== 'number') {
{
warn('Reference timestamp not set via EUM initializer. Was the initializer modified?');
}
return;
}
if (typeof globalObject['v'] === 'number') {
var version = String(Math.round(globalObject['v']));
{
info('Identified version of snippet to be:', version);
}
defaultVars.trackingSnippetVersion = version;
} // Start observing web vitals as early as possible as it registers performance observers.
try {
addWebVitals(beacon);
} catch (e) {
{
warn('Failed to capture web vitals. Will continue without web vitals', e);
}
}
processCommands(globalObject.q); // prefer the backend trace ID which was explicitly set
defaultVars.pageLoadBackendTraceId = defaultVars.pageLoadBackendTraceId || getPageLoadBackendTraceId();
defaultVars.initializerExecutionTimestamp = globalObject['l'];
addCommandAfterInitializationSupport();
if (!defaultVars.reportingUrl) {
{
error('No reporting URL configured. Aborting EUM initialization.');
}
return;
}
hookIntoUserTimings();
instrumentXMLHttpRequest();
instrumentFetch();
hookIntoGlobalErrorEvent();
wrapTimers();
wrapEventHandlers();
hookIntoGlobalUnhandledRejectionEvent();
transitionTo('waitForPageLoad');
},
getActiveTraceId: function () {
return defaultVars.pageLoadTraceId;
},
getActivePhase: function () {
return pageLoad;
}
};
function processCommands(commands) {
for (var i = 0, len = commands.length; i < len; i++) {
processCommand(commands[i]);
}
}
function addCommandAfterInitializationSupport() {
var globalObjectName = win[defaultVars.nameOfLongGlobal];
win[globalObjectName] = function () {
return processCommand(arguments);
};
}
function fulfillsPrerequisites() {
return win.XMLHttpRequest && win.JSON;
}
registerState('init', state$2);
registerState('waitForPageLoad', state);
registerState('pageLoaded', state$1);
transitionTo('init');
}());
//# sourceMappingURL=eum.debug.js.map
(function(){function va(){for(var a='',b=0;16>b;b++)a+=Ua[Math.round(15*Math.random())];return a}function u(){return(new Date).getTime()}function Va(){}function K(a,b,c){a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent&&a.attachEvent('on'+b,c)}function L(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c].test(b))return!0;return!1}function M(){return ia.apply('setTimeout',arguments)}function R(){return ia.apply('clearTimeout',arguments)}function wa(){return ia.apply('setInterval',arguments)}function ia(){if(xa)try{return h.Zone.root.run(ya[this],
h,Array.prototype.slice.apply(arguments))}catch(a){}return ya[this].apply(h,arguments)}function za(){H.time=u();var a=H.time,b=ja[H.name];if(b)for(var c=0,d=b.length;c<d;c++)b[c](a)}function ka(a,b){N[a]=b}function la(a){S=a;N[a].S()}function Wa(){la('pageLoaded')}function I(a){a.k=f.L;a.sv=f.na;a.r=f.f;a.p=f.page;a.l=h.location.href;a.pl=f.B;a.ui=f.ra;a.un=f.userName;a.ue=f.qa;a.ul=Xa;a.ph=N[S].D();a.sid=f.sessionId;a.ww=h.innerWidth;a.wh=h.innerHeight;y.connection&&y.connection.effectiveType&&(a.ct=
y.connection.effectiveType);z.visibilityState&&(a.h='hidden'===z.visibilityState?1:0);ma(a,f.A)}function ma(a,b){var c=0,d;for(d in b)if(Y.call(b,d)){c++;if(25<c)break;var e=null;if('string'===typeof b[d])e=b[d];else if(void 0===b[d])e='undefined';else if(null===b[d])e='null';else if(h.JSON)try{e=h.JSON.stringify(b[d])}catch(g){continue}else e=String(b[d]);a['m_'+d]=e.substring(0,1024)}}function Aa(a){var b=[Math.round(a.startTime-f.M),Math.round(a.duration),Ba[a.initiatorType]||Ba.other];'number'===
typeof a.transferSize&&'number'===typeof a.encodedBodySize&&0<a.encodedBodySize?(0===a.transferSize?b.push(na.wa):0<a.transferSize&&(0===a.encodedBodySize||a.transferSize<a.encodedBodySize)?b.push(na.Ha):b.push(na.Aa),null!=a.encodedBodySize?b.push(a.encodedBodySize):b.push(''),null!=a.decodedBodySize?b.push(a.decodedBodySize):b.push(''),null!=a.transferSize?b.push(a.transferSize):b.push('')):(b.push(''),b.push(''),b.push(''),b.push(''));var c=null!=a.responseStart&&a.responseStart>=a.fetchStart;
c&&(b.push(C(a.redirectEnd,a.redirectStart)),b.push(C(a.domainLookupStart,a.fetchStart)),b.push(C(a.domainLookupEnd,a.domainLookupStart)),0<a.connectStart&&0<a.connectEnd?null!=a.secureConnectionStart&&0<a.secureConnectionStart?(b.push(C(a.secureConnectionStart,a.connectStart)),b.push(C(a.connectEnd,a.secureConnectionStart))):(b.push(C(a.connectEnd,a.connectStart)),b.push('')):(b.push(''),b.push('')),b.push(C(a.responseStart,a.requestStart)),b.push(C(a.responseEnd,a.responseStart)));var d='';try{var e=
a.serverTiming;if(e instanceof Array)for(var g=0;g<e.length;g++){var k=e[g];k.name===f.ka&&(d=k.description)}}catch(l){}b.push(d);c?b.push(C(a.responseStart,a.startTime)):b.push('');return b}function C(a,b){if(null==a||null==b||a===b)return'';var c=Math.round(a-b);return 0>c?'':c}function Z(a){if(!a)return!0;a=String(a);return!a||null==a.substring||'data:'===a.substring(0,5).toLowerCase()||f.ba&&Ya.test(a)?!0:L(f.ca,a)}function aa(){this.root={}}function oa(a){var b=[],c;for(c in a)Y.call(a,c)&&b.push(c);
return b}function Za(a,b){if(ba&&h.JSON){var c=t.getEntriesByType('resource');for(var d=new aa,e=null!=f.g?f.g.toLowerCase():null,g=0,k=c.length;g<k;g++){var l=c[g];if(!(null!=b&&l.startTime-f.M+f.f<b||0>l.duration)){var m=l.name;if(!Z(m)){var v=m.toLowerCase(),A=l.initiatorType;'about:blank'===v||0===v.indexOf('javascript:')||null!=e&&0===v.indexOf(e)||(255<m.length&&(m=m.substring(0,255)),('xmlhttprequest'!==A||l.startTime<f.M)&&d.va(m,Aa(l).join(',').replace(/,+$/,'')))}}}c=d.ma();a.res=h.JSON.stringify(c)}}
function $a(a){if(pa){var b=t.timing,c=b.redirectEnd-b.redirectStart,d=qa;a.ts=d-f.f;0<b.loadEventStart?a.d=b.loadEventStart-(b.fetchStart||b.navigationStart):(a.d=Number(H.time)-f.G,a.tim='0');a.t_unl=b.unloadEventEnd-b.unloadEventStart;a.t_red=c;a.t_apc=b.domainLookupStart-(b.fetchStart||b.redirectEnd||b.unloadEventEnd||b.navigationStart);a.t_dns=b.domainLookupEnd-b.domainLookupStart;0<b.connectStart&&0<b.connectEnd&&(null!=b.secureConnectionStart&&0<b.secureConnectionStart&&b.secureConnectionStart>=
b.connectStart?(a.t_tcp=b.secureConnectionStart-b.connectStart,a.t_ssl=b.connectEnd-b.secureConnectionStart):(a.t_tcp=b.connectEnd-b.connectStart,a.t_ssl=0));a.t_req=b.responseStart-b.requestStart;a.t_rsp=b.responseEnd-b.responseStart;a.t_dom=b.domContentLoadedEventStart-b.domLoading;a.t_chi=b.loadEventEnd-b.domContentLoadedEventStart;a.t_bac=b.responseStart-d;a.t_fro=b.loadEventEnd-b.responseStart;a.t_pro=b.loadEventStart-b.domLoading;a.t_loa=b.loadEventEnd-b.loadEventStart;a.t_ttfb=b.responseStart-
d;if(ba){b=t.getEntriesByType('paint');c=!1;for(var e=0;e<b.length;e++){var g=b[e];switch(g.name){case 'first-paint':a.t_fp=g.startTime|0;c=!0;break;case 'first-contentful-paint':a.t_fcp=g.startTime|0}}c||Ca(a,d)}else Ca(a,d)}else a.ts=qa-f.f,a.d=Number(H.time)-f.G,pa||(a.tim='0')}function Ca(a,b){var c=null;h.Z&&h.Z.Ca?c=1E3*h.Z.Ca().firstPaintTime:'number'===typeof h.performance.timing.msFirstPaint?c=h.performance.timing.msFirstPaint:'number'===typeof h.performance.timing.firstPaint&&(c=h.performance.timing.firstPaint);
null!=c&&0!==c&&(a.t_fp=Math.round(c-b))}function Da(a){ra&&a();K(z,'visibilitychange',function(){'visible'!==z.visibilityState&&a()});K(h,'pagehide',function(b){b.persisted&&(ra=!0,a())});K(h,'unload',function(){});K(h,'beforeunload',function(){ra=!0;a()})}function Ea(a){(a[f.j]=a[f.j]||{}).i=!0}function Fa(a,b){var c=Aa(b);a.s_ty=w(c[3]);a.s_eb=w(c[4]);a.s_db=w(c[5]);a.s_ts=w(c[6]);a.t_red=w(c[7]);a.t_apc=w(c[8]);a.t_dns=w(c[9]);a.t_tcp=w(c[10]);a.t_ssl=w(c[11]);a.t_req=w(c[12]);a.t_rsp=w(c[13]);
c[14]&&(a.bt=c[14],a.bc=1);a.t_ttfb=w(c[15])}function w(a){if('number'===typeof a)return a}function Ga(a,b,c){a.call(b,'X-INSTANA-T',c);a.call(b,'X-INSTANA-S',c);a.call(b,'X-INSTANA-L','1,correlationType=web;correlationId='+c)}function Ha(a){return String(a).replace(/\\/g,'\\\\').replace(/\n/g,'\\n').replace(/\t/g,'\\t')}function ca(){null!=T&&(R(T),T=null);if(0!==U.length){var a=U;for(var b='',c=0;c<a.length;c++){var d=a[c];b+='\n';for(var e in d)if(Y.call(d,e)){var g=d[e];null!=g&&(b+='\n'+Ha(e)+
'\t'+Ha(g))}}a=b.substring(2);U.length=0;0!==a.length&&!1===('function'===typeof y.sendBeacon&&y.sendBeacon(String(f.g),a))&&(b=new x,Ea(b),b.open('POST',String(f.g),!0),b.setRequestHeader('Content-type','text/plain;charset=UTF-8'),b.responseType='text',b.timeout=f.X,b.send(a))}}function V(a){var b=a.Da||4096,c=a.o||128,d=a.w||32,e=0,g=0,k=0;wa(function(){g=0},6E5);wa(function(){k=0},1E4);return function(){return++e>b||++g>c||++k>d}}function D(a){if(!Z(a.l)&&!ab())try{if(Ia&&0<f.C)U.push(a),15<=U.length?
ca():'visible'===z.visibilityState&&0<f.C?null==T&&(T=M(ca,f.C)):ca();else{var b='',c;for(c in a)Y.call(a,c)&&null!=a[c]&&(b+='&'+Ja(c)+'='+Ja(String(a[c])));var d=b.substring(1);if(0!==d.length)if(x&&2E3<d.length){var e=new x;Ea(e);e.open('POST',String(f.g),!0);e.setRequestHeader('Content-type','application/x-www-form-urlencoded;charset=UTF-8');e.responseType='text';e.timeout=f.X;e.send(d)}else{var g=String(f.g)+'?'+d;(new Image).src=g}}}catch(k){}}function bb(){var a=h.onerror;h.onerror=function(b,
c,d,e,g){if(da)da=!1;else{var k=g&&g.stack;k||(k='at '+c+' '+d,null!=e&&(k+=':'+e));sa(b,k)}if('function'===typeof a)return a.apply(this,arguments)}}function O(a,b){a&&('string'===typeof a?sa(a,'',b):sa(a.message,a.stack,b))}function sa(a,b,c){if(a&&!(100<Ka)&&a&&!L(f.aa,a)){20<=ea&&(J={},ea=0);a=String(a).substring(0,300);b=String(b||'').split('\n').slice(0,30).join('\n');var d=h.location.href,e=N[S].F(),g=a+b+d+(e||''),k=J[g];k?k.T++:(k=void 0,c&&c.componentStack&&(k=String(c.componentStack).substring(0,
4096)),J[g]={message:a,stack:b,xa:k,A:c?c.meta:void 0,location:d,Fa:e,T:1,oa:0},ea++);fa||(fa=M(cb,1E3))}}function cb(){R(fa);fa=null;for(var a in J)if(J.hasOwnProperty(a)){var b=J[a];if(b.T>b.oa){var c=P();c={ty:'err',s:c,t:b.Fa||c,ts:u(),l:b.location,e:b.message,st:b.stack,cs:b.xa,c:b.T-b.oa};I(c);b.A&&ma(c,b.A);D(c);Ka++}}J={};ea=0}function db(a){null==a.reason?O({message:'Unhandled promise rejection: <no reason defined>',stack:"<unavailable because Promise wasn't rejected with an Error object>"}):
'string'===typeof a.reason.message?O({message:'Unhandled promise rejection: '+a.reason.message,stack:'string'===typeof a.reason.stack?a.reason.stack:"<unavailable because Promise wasn't rejected with an Error object>"}):'object'!==typeof a.reason&&O({message:'Unhandled promise rejection: '+a.reason,stack:"<unavailable because Promise wasn't rejected with an Error object>"})}function La(a){function b(){e();a.R({J:m,duration:m&&null!=m.duration&&864E5>m.duration?Math.round(m.duration):Math.round(l-
k)})}function c(n){n=n.getEntries();for(var q=0;q<n.length;q++){var Q=n[q];if(Q.startTime>=k&&(!l||l>=Q.responseEnd)&&a.ja(Q)){m=Q;g();l&&b();break}}}function d(){Ma()||b()}function e(){g();A&&(R(A),A=null);r&&(R(r),r=null);var n=z,q=d;n.removeEventListener?n.removeEventListener('visibilitychange',q,!1):n.detachEvent&&n.detachEvent('onvisibilitychange',q)}function g(){if(v){try{v.disconnect()}catch(n){}v=null}}if(!Na)return eb(a.R);var k,l,m,v,A,r;return{P:function(){k=t.now();try{v=new h.PerformanceObserver(c),
v.observe({entryTypes:a.entryTypes})}catch(n){}r=M(e,6E5)},O:function(){l=t.now();r&&(R(r),r=null);m||!Ma()?b():(K(z,'visibilitychange',d),A=M(b,a.ha))},cancel:e}}function eb(a){var b;return{P:function(){b=u()},O:function(){var c=u();a({duration:c-b})},cancel:Va}}function Ma(){return'visible'===z.visibilityState||'prerender'===z.visibilityState}function Oa(a){if(ha)try{ha.href=a,a=ha.href}catch(c){}var b=a.indexOf('#');0<=b&&(a=a.substring(0,b));4096<a.length&&(a=a.substring(0,4096));return a}function Pa(a){if(!F||
!E)return!1;try{return F.href=a,(F.protocol&&':'!==F.protocol?F.protocol:E.protocol)===E.protocol&&(F.hostname||E.hostname)===E.hostname&&(F.port||E.port)===E.port}catch(b){return!1}}function fb(){if(x&&(new x).addEventListener){var a=x.prototype.open,b=x.prototype.setRequestHeader,c=x.prototype.send;a&&b&&c&&(x.prototype.open=function(d,e,g){function k(p){n.i||0!==q.st||(q.st=p,q.d=Math.max(0,u()-(q.ts+f.f)),n.b&&0<p?n.b.O():(n.b&&n.b.cancel(),D(q)))}function l(){k(W.timeout)}function m(p){n.i||
(p=p&&(p.error&&p.error.message||p.message),'string'===typeof p&&(q.e=p.substring(0,300)),k(W.error))}function v(){k(W.abort)}function A(){if(4===r.readyState){try{var p=r.status}catch(wb){k(W.error);return}0!==p&&k(p)}}var r=this;if(gb())return a.apply(r,arguments);var n=r[f.j]=r[f.j]||{};if(n.i)return a.apply(r,arguments);n.i=Z(e);if(n.i)return a.apply(r,arguments);n.V=P();n.la=Pa(e)||L(f.W,e);var q={ty:'xhr',t:n.V,s:n.V,ts:0,d:0,m:d,u:Oa(e),a:void 0===g||g?1:0,st:0,e:void 0,bc:n.la?1:0};n.Y=q;
n.b=La({entryTypes:['resource'],ja:function(p){return('fetch'===p.initiatorType||'xmlhttprequest'===p.initiatorType)&&!!p.name&&0===p.name.indexOf(q.u)},ha:f.N,R:function(p){q.d=p.duration;p.J&&Fa(q,p.J);D(q)}});try{var Q=a.apply(r,arguments);r.addEventListener('timeout',l);r.addEventListener('error',m);r.addEventListener('abort',v);r.addEventListener('readystatechange',A);return Q}catch(p){throw n.b.cancel(),q.ts=u()-f.f,q.st=W.Ea,q.e=p.message,I(q),D(q),r[f.j]=null,p;}},x.prototype.setRequestHeader=
function(d){var e=this[f.j];e&&hb.test(d)&&(e.i=!0,e.b&&(e.b.cancel(),e.b=null));return b.apply(this,arguments)},x.prototype.send=function(){var d=this[f.j];if(!d||d.i)return c.apply(this,arguments);d.la&&Ga(b,this,d.V);d.Y.ts=u()-f.f;I(d.Y);d.b.P();return c.apply(this,arguments)})}}function ib(){if(!ba)return null;for(var a=t.getEntriesByType('navigation'),b=0;b<a.length;b++){var c=a[b];if(null!=c.serverTiming)for(var d=0;d<c.serverTiming.length;d++){var e=c.serverTiming[d];if(e.name===f.ka)return e.description}}return null}
function jb(a,b,c){var d=a[f.K]=a[f.K]||[];a=Qa(a,c);if(-1!==a)return d[a].ua;d.push({ua:b,Ia:c});return b}function Qa(a,b){for(var c=a[f.K],d=0;d<c.length;d++){a:{var e=c[d].Ia;if(e.length!==b.length)e=!1;else{for(var g=0;g<e.length;g++)if(e[g]!==b[g]){e=!1;break a}e=!0}}if(e)return d}return-1}function kb(a){if(a&&'function'===typeof a.prototype.addEventListener&&'function'===typeof a.prototype.removeEventListener){var b=a.prototype.addEventListener,c=a.prototype.removeEventListener;a.prototype.addEventListener=
function(d,e,g){if('function'!==typeof e)return b.apply(this,arguments);for(var k=Array(arguments.length),l=0;l<arguments.length;l++)k[l]=arguments[l];k[1]=function(){try{return e.apply(this,arguments)}catch(m){throw O(m),da=!0,m;}};k[1]=jb(this,k[1],[d,e,null==g?!1:'object'===typeof g?!!g.capture:!!g]);return b.apply(this,k)};a.prototype.removeEventListener=function(d,e,g){if('function'!==typeof e)return c.apply(this,arguments);for(var k=Array(arguments.length),l=0;l<arguments.length;l++)k[l]=arguments[l];
var m=[d,e,null==g?!1:'object'===typeof g?!!g.capture:!!g],v=e;l=this[f.K];null==l?l=v:(m=Qa(this,m),-1===m?l=v:(v=l[m],l.splice(m,1),l=v.ua));k[1]=l;return c.apply(this,k)}}}function Ra(a,b){if(!lb()){var c=N[S].F(),d=P();c||(c=d);c={ty:'cus',s:d,t:c,ts:u(),n:a};I(c);b&&(b.meta&&ma(c,b.meta),'number'!==typeof b.duration||isNaN(b.duration)||(c.d=b.duration,c.ts-=b.duration),'number'!==typeof b.timestamp||isNaN(b.timestamp)||(c.ts=b.timestamp),'string'===typeof b.backendTraceId&&(c.bt=b.backendTraceId.substring(0,
64)),b.error&&(c.e=String(b.error.message).substring(0,300),c.st=String(b.error.stack||'').split('\n').slice(0,30).join('\n')),'string'===typeof b.componentStack&&(c.cs=b.componentStack.substring(0,4096)));D(c)}}function ta(a){for(var b=0;b<a.length;b++){var c=void 0,d=a[b];L(f.da,d.name)||('mark'!==d.entryType&&(c=Math.round(d.duration)),Ra(d.name,{timestamp:Math.max(qa,Math.round(t.timeOrigin+d.startTime)),duration:c,meta:{userTimingType:d.entryType}}))}}function mb(a){ta(a.getEntries())}function nb(){h.fetch&&
h.Request&&(h.fetch=function(a,b){var c=new Request(a,b);if(ob())return ua(c);var d=c.url;if(Z(d))return ua(c);var e={ty:'xhr',ts:u()-f.f,d:0,m:'',u:'',a:1,st:0,e:void 0};I(e);pb(e,a,b);var g=P(),k=Pa(d)||L(f.W,d);e.t=g;e.s=g;e.m=c.method;e.u=Oa(d);e.a=1;e.bc=k?1:0;k&&Ga(c.headers.append,c.headers,g);var l=La({entryTypes:['resource'],ja:function(m){return('fetch'===m.initiatorType||'xmlhttprequest'===m.initiatorType)&&!!m.name&&0===m.name.indexOf(e.u)},ha:f.N,R:function(m){e.d=m.duration;m.J&&Fa(e,
m.J);D(e)}});l.P();return ua(c).then(function(m){e.st=m.status;l.O();return m},function(m){l.cancel();e.d=u()-(e.ts+f.f);e.e=m.message;e.st=-103;D(e);throw m;})})}function pb(a,b,c){try{if('string'===typeof b&&c&&'POST'===c.method&&'string'===typeof c.body&&L(f.pa,b)){var d=JSON.parse(c.body);'string'===typeof d.operationName&&(a.gon=d.operationName);'string'===typeof d.query&&(qb.test(d.query)?a.got='query':rb.test(d.query)?a.got='mutation':0===d.query.indexOf('{')&&null===d.operationName&&(a.got=
'query'))}}catch(e){}}function Sa(a){switch(a[0]){case 'apiKey':f.L=a[1];break;case 'key':f.L=a[1];break;case 'reportingUrl':f.g=a[1];break;case 'meta':f.A[a[1]]=a[2];break;case 'traceId':f.I=a[1];break;case 'ignoreUrls':f.ca=a[1];break;case 'ignoreErrorMessages':f.aa=a[1];break;case 'whitelistedOrigins':f.W=a[1];break;case 'ignoreUserTimings':f.da=a[1];break;case 'xhrTransmissionTimeout':f.X=a[1];break;case 'page':var b=a[1],c=f.page;f.page=b;'pl'===N[S].D()&&null==c||c===b||sb()||(b={ty:'pc',ts:u()},
I(b),D(b));break;case 'ignorePings':f.ba=a[1];break;case 'reportError':O(a[1],a[2]);break;case 'wrapEventHandlers':f.sa=a[1];break;case 'wrapTimers':f.ta=a[1];break;case 'getPageLoadId':return f.B;case 'user':a[1]&&(f.ra=String(a[1]).substring(0,128));a[2]&&(f.userName=String(a[2]).substring(0,128));a[3]&&(f.qa=String(a[3]).substring(0,128));break;case 'reportEvent':Ra(a[1],a[2]);break;case 'beaconBatchingTime':f.C=a[1];break;case 'maxWaitForResourceTimingsMillis':f.N=a[1];break;case 'maxMaitForPageLoadMetricsMillis':f.ga=
a[1];break;case 'trackSessions':var d=a[1];a=a[2];if(X){d||(d=f.ya);a||(a=f.za);d=Math.min(d,f.fa);a=Math.min(a,f.fa);try{var e=X&&B?B.getItem(f.U):void 0;if(e){var g=e.split('#');if(3>g.length)b=null;else{var k=g[0],l=parseInt(g[1],10),m=parseInt(g[2],10);b=!k||isNaN(l)||isNaN(m)?null:{id:k,startTime:l,H:m}}}else b=null;if(c=b){e=b;var v=u()-d;if(e.H<v)var A=!1;else{var r=u()-a;A=e.startTime<r?!1:!0}c=!A}c&&(b=null);b?b.H=u():b={id:P(),startTime:u(),H:u()};X&&B&&B.setItem(f.U,b.id+'#'+b.startTime+
'#'+b.H);f.sessionId=b.id}catch(n){}}break;case 'terminateSession':f.sessionId=void 0;if(X)try{X&&B&&B.removeItem(f.U)}catch(n){}break;case 'urlsToCheckForGraphQlInsights':f.pa=a[1]}}function Ta(a){var b=h[a];'function'===typeof b&&(h[a]=function(c){for(var d=Array(arguments.length),e=0;e<arguments.length;e++)d[e]=arguments[e];d[0]=tb(c);return b.apply(this,d)})}function tb(a){return'function'!==typeof a?a:function(){try{return a.apply(this,arguments)}catch(b){throw O(b),da=!0,b;}}}function ub(){h[h[f.ia]]=
function(){return Sa(arguments)}}var h=window,z=h.document,y=navigator,Ja=h.encodeURIComponent,x=h.XMLHttpRequest,ua=h.fetch;try{var B=h.localStorage}catch(a){B=null}var Y=Object.prototype.hasOwnProperty,Ua='0123456789abcdef'.split('');h.crypto&&h.crypto.getRandomValues&&h.Uint32Array&&(va=function(){var a=new h.Uint32Array(2);h.crypto.getRandomValues(a);return a[0].toString(16)+a[1].toString(16)});var P=va,ya={setTimeout:h.setTimeout,clearTimeout:h.clearTimeout,setInterval:h.setInterval,clearInterval:h.clearInterval},
xa=null!=h.Zone&&null!=h.Zone.root&&'function'===typeof h.Zone.root.run,ja={},H={name:'e:onLoad',time:null,Ba:function(){if('complete'===document.readyState)return za();K(h,'load',function(){M(za,0)})}},N={},S,t=h.performance||h.Ma||h.Ka||h.Ja,pa=t&&t.timing,ba=t&&t.getEntriesByType,Na=t&&'function'===typeof h.PerformanceObserver&&'function'===typeof t.now,f={ia:'InstanaEumObject',na:null,B:P(),I:null,ka:'intid',f:u(),M:t&&t.now?t.now():0,G:u(),g:'https://eum.instana.io',C:2E3,N:1E4,ga:5E3,L:null,
A:{},ca:[],ba:!0,aa:[],X:2E4,W:[],page:void 0,sa:!1,K:'__instanaOriginalFunctions__',ta:!1,j:'__instanaSecretData__',ra:void 0,userName:void 0,qa:void 0,sessionId:void 0,U:'in-session',ya:108E5,za:216E5,fa:864E5,da:[/^\u269B/,/^\u26D4/,/^Zone(:|$)/,/^start /i,/^end /i],pa:[/\/graphql/i]};var Xa=y.languages&&0<y.languages.length?y.languages.slice(0,5).join(','):'string'===typeof y.Ga?[y.Ga].join():void 0;var Ba={other:0,img:1,image:1,link:2,script:3,css:4,xmlhttprequest:5,fetch:5,beacon:5,html:6,navigation:6},
na={La:0,wa:1,Ha:2,Aa:3},Ya=/.*\/ping(\/?$|\?.*)/i;aa.prototype.va=function(a,b){this.ea(this.root,a.split(''),0,b)};aa.prototype.ea=function(a,b,c,d){var e=b[c];null==e?(a['<END>']=a['<END>']||[]).push(d):(a=a[e]=a[e]||{},this.ea(a,b,c+1,d))};aa.prototype.ma=function(a){a=a||this.root;var b=oa(a);if(1===b.length&&'<END>'===b[0])return a['<END>'].slice();for(var c={},d=0,e=b.length;d<e;d++){var g=b[d],k=a[g];if('<END>'===g)c.$=k.slice();else{k=g;g=a[g];for(var l=oa(g);1===l.length&&'<END>'!==l[0];)k+=
l[0],g=g[l[0]],l=oa(g);c[k]=this.ma(g)}}return c};var qa=pa?t.timing.navigationStart:f.G,ra=!1,U=[],T,vb='string'===typeof z.visibilityState,Ia=!!x&&vb&&'function'===typeof y.sendBeacon;Ia&&Da(ca);var ab=V({Da:8096,o:4096,w:128}),G={ty:'pl'},Ka=0,ea=0,J={},fa,da=!1,ha=null;try{ha=document.createElement('a')}catch(a){}var F=null,E=null;try{F=document.createElement('a'),E=document.createElement('a'),E.href=h.location.href}catch(a){}var gb=V({o:256,w:32}),W={timeout:-100,abort:-101,Ea:-102,error:-103},
hb=/^X-INSTANA-T$/i,lb=V({o:128,w:32}),ob=V({o:256,w:32}),qb=/^\s*query(\s|\{)/i,rb=/^\s*mutation(\s|\{)/i,X=null!=B&&'function'===typeof B.getItem&&'function'===typeof B.setItem,sb=V({o:128,w:32});ka('init',{S:function(){var a=h[h[f.ia]];if(a&&a.q&&'number'===typeof a.l){'number'===typeof a.v&&(f.na=String(Math.round(a.v)));for(var b=a.q,c=0,d=b.length;c<d;c++)Sa(b[c]);f.I=f.I||ib();f.G=a.l;ub();if(f.g){if(t&&t.timeOrigin&&ba&&(ta(t.getEntriesByType('mark')),ta(t.getEntriesByType('measure')),Na))try{(new h.PerformanceObserver(mb)).observe({entryTypes:['mark',
'measure']})}catch(e){}fb();nb();bb();f.ta&&!xa&&(Ta('setTimeout'),Ta('setInterval'));f.sa&&kb(h.EventTarget);'function'===typeof h.addEventListener&&h.addEventListener('unhandledrejection',db);la('waitForPageLoad')}}},F:function(){return f.B},D:function(){return'pl'}});ka('waitForPageLoad',{S:function(){var a=H.name;(ja[a]=ja[a]||[]).push(Wa);H.Ba()},F:function(){return f.B},D:function(){return'pl'}});ka('pageLoaded',{S:function(){function a(){b||(b=!0,D(G))}I(G);G.t=f.B;G.bt=f.I;G.u=h.location.href;
G.ph='pl';$a(G);Za(G);var b=!1;'visible'!==z.visibilityState?a():(M(a,f.ga),Da(a))},F:function(){return null},D:function(){}});la('init')})();
//# sourceMappingURL=eum.min.js.map
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment