@pendo/agent 2.291.3 → 2.292.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/debugger-plugin.min.js +1 -1
- package/dist/dom.esm.js +1 -1
- package/dist/pendo.debugger.min.js +9 -8
- package/dist/pendo.module.js +405 -283
- package/dist/pendo.module.min.js +9 -9
- package/dist/pendo.preview.min.js +3 -3
- package/package.json +1 -1
package/dist/pendo.module.js
CHANGED
|
@@ -463,6 +463,9 @@ function shouldUseUnminifiedAgent(config, debuggingEnabled) {
|
|
|
463
463
|
return !isExtension(config) && isMinifiedAgent(config) && debuggingEnabled;
|
|
464
464
|
}
|
|
465
465
|
function findAgentScriptTag(scripts = [], apiKey) {
|
|
466
|
+
if (document.currentScript) {
|
|
467
|
+
return document.currentScript;
|
|
468
|
+
}
|
|
466
469
|
const regex = /^https:\/\/[\w\-.]*cdn[\w\-.]*\.(pendo-dev\.com|pendo\.io)\/agent\/static\/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}|PENDO_API_KEY)\/pendo\.js$/g;
|
|
467
470
|
for (let i = 0; i < scripts.length; i++) {
|
|
468
471
|
const script = scripts[i];
|
|
@@ -3687,6 +3690,10 @@ function globalBucket(env) {
|
|
|
3687
3690
|
}
|
|
3688
3691
|
|
|
3689
3692
|
function isNativeCode(fn) { return /native/.test(fn); }
|
|
3693
|
+
const detectNativeBrowserAPI = (name) => {
|
|
3694
|
+
const fn = _.get(window, name);
|
|
3695
|
+
return (fn && isNativeCode(fn));
|
|
3696
|
+
};
|
|
3690
3697
|
|
|
3691
3698
|
var isOldIE = function (olderThan, tVersion) {
|
|
3692
3699
|
olderThan = olderThan || 10;
|
|
@@ -3904,8 +3911,8 @@ var SERVER = '';
|
|
|
3904
3911
|
var ASSET_HOST = '';
|
|
3905
3912
|
var ASSET_PATH = '';
|
|
3906
3913
|
var DESIGNER_SERVER = '';
|
|
3907
|
-
var VERSION = '2.
|
|
3908
|
-
var PACKAGE_VERSION = '2.
|
|
3914
|
+
var VERSION = '2.292.0_';
|
|
3915
|
+
var PACKAGE_VERSION = '2.292.0';
|
|
3909
3916
|
var LOADER = 'xhr';
|
|
3910
3917
|
/* eslint-enable agent-eslint-rules/no-gulp-env-references */
|
|
3911
3918
|
/**
|
|
@@ -12196,6 +12203,92 @@ class LocalStorageEventBuffer {
|
|
|
12196
12203
|
}
|
|
12197
12204
|
var localStorageEventBuffer = new LocalStorageEventBuffer();
|
|
12198
12205
|
|
|
12206
|
+
class PerformanceMonitor {
|
|
12207
|
+
constructor() {
|
|
12208
|
+
this._isPerformanceApiAvailable = this._checkPerformanceApi();
|
|
12209
|
+
this._measuringPerformance = false;
|
|
12210
|
+
this._marks = {};
|
|
12211
|
+
this._measures = {};
|
|
12212
|
+
}
|
|
12213
|
+
initialize() {
|
|
12214
|
+
this._measuringPerformance = true;
|
|
12215
|
+
this._markPerformance('initialize');
|
|
12216
|
+
// temporary clear interval while working on send implementation
|
|
12217
|
+
this.interval = setInterval(() => {
|
|
12218
|
+
this._clearMarksAndMeasures();
|
|
12219
|
+
}, 1000 * 60 * 10);
|
|
12220
|
+
return () => {
|
|
12221
|
+
this.teardown();
|
|
12222
|
+
};
|
|
12223
|
+
}
|
|
12224
|
+
teardown() {
|
|
12225
|
+
this._measuringPerformance = false;
|
|
12226
|
+
this._markPerformance('teardown');
|
|
12227
|
+
this._clearMarksAndMeasures();
|
|
12228
|
+
clearInterval(this.interval);
|
|
12229
|
+
}
|
|
12230
|
+
startTimer(name) {
|
|
12231
|
+
this._markPerformance(`${name}-start`);
|
|
12232
|
+
}
|
|
12233
|
+
stopTimer(name) {
|
|
12234
|
+
this._markPerformance(`${name}-stop`);
|
|
12235
|
+
this._measurePerformance(name);
|
|
12236
|
+
}
|
|
12237
|
+
track(name) {
|
|
12238
|
+
this._markPerformance(name);
|
|
12239
|
+
}
|
|
12240
|
+
send() {
|
|
12241
|
+
performance.getEntries();
|
|
12242
|
+
// TODO: implement filter/send process
|
|
12243
|
+
this._clearMarksAndMeasures();
|
|
12244
|
+
}
|
|
12245
|
+
_checkPerformanceApi() {
|
|
12246
|
+
return detectNativeBrowserAPI('performance.mark') &&
|
|
12247
|
+
detectNativeBrowserAPI('performance.measure') &&
|
|
12248
|
+
detectNativeBrowserAPI('performance.getEntries') &&
|
|
12249
|
+
detectNativeBrowserAPI('performance.clearMarks') &&
|
|
12250
|
+
detectNativeBrowserAPI('performance.clearMeasures');
|
|
12251
|
+
}
|
|
12252
|
+
_shouldMeasurePerformance() {
|
|
12253
|
+
return this._isPerformanceApiAvailable && this._measuringPerformance;
|
|
12254
|
+
}
|
|
12255
|
+
_markPerformance(name) {
|
|
12256
|
+
if (!this._shouldMeasurePerformance())
|
|
12257
|
+
return;
|
|
12258
|
+
name = `pendo-${name}`;
|
|
12259
|
+
performance.mark(name);
|
|
12260
|
+
this._count(this._marks, name);
|
|
12261
|
+
}
|
|
12262
|
+
_measurePerformance(name) {
|
|
12263
|
+
if (!this._shouldMeasurePerformance())
|
|
12264
|
+
return;
|
|
12265
|
+
name = `pendo-${name}`;
|
|
12266
|
+
const startMark = `${name}-start`;
|
|
12267
|
+
const stopMark = `${name}-stop`;
|
|
12268
|
+
performance.measure(name, startMark, stopMark);
|
|
12269
|
+
this._count(this._measures, name);
|
|
12270
|
+
}
|
|
12271
|
+
_count(registry, name) {
|
|
12272
|
+
if (!registry[name]) {
|
|
12273
|
+
registry[name] = 1;
|
|
12274
|
+
}
|
|
12275
|
+
else {
|
|
12276
|
+
registry[name]++;
|
|
12277
|
+
}
|
|
12278
|
+
}
|
|
12279
|
+
_clearMarksAndMeasures() {
|
|
12280
|
+
_.each(this._marks, (count, name) => {
|
|
12281
|
+
performance.clearMarks(name);
|
|
12282
|
+
});
|
|
12283
|
+
_.each(this._measures, (count, name) => {
|
|
12284
|
+
performance.clearMeasures(name);
|
|
12285
|
+
});
|
|
12286
|
+
this._marks = {};
|
|
12287
|
+
this._measures = {};
|
|
12288
|
+
}
|
|
12289
|
+
}
|
|
12290
|
+
var PerformanceMonitor$1 = new PerformanceMonitor();
|
|
12291
|
+
|
|
12199
12292
|
var defaultTrackName = '_PENDO_UNNAMED_';
|
|
12200
12293
|
var SILO_AVG_COMPRESSION_RATIO = 5;
|
|
12201
12294
|
/**
|
|
@@ -12257,21 +12350,7 @@ function collectEvent(type, props, url, name, eventProperties, context) {
|
|
|
12257
12350
|
agenticEventQueue.push(event);
|
|
12258
12351
|
return;
|
|
12259
12352
|
}
|
|
12260
|
-
eventQueue.push(
|
|
12261
|
-
}
|
|
12262
|
-
function attachMonitoringData(store, event) {
|
|
12263
|
-
try {
|
|
12264
|
-
if (!store.getters['monitoring/shouldFlush']())
|
|
12265
|
-
return event;
|
|
12266
|
-
var payload = store.getters['monitoring/payload']();
|
|
12267
|
-
store.dispatch('monitoring/flush');
|
|
12268
|
-
if (!_.isEmpty(payload)) {
|
|
12269
|
-
event.ops = payload;
|
|
12270
|
-
}
|
|
12271
|
-
}
|
|
12272
|
-
catch (e) {
|
|
12273
|
-
}
|
|
12274
|
-
return event;
|
|
12353
|
+
eventQueue.push(event);
|
|
12275
12354
|
}
|
|
12276
12355
|
// @const {Event.type[]}
|
|
12277
12356
|
var WHITELIST_FREE_NPS = ['load', 'meta', 'identify'];
|
|
@@ -12710,7 +12789,7 @@ function createSendQueue(options, send, guaranteedSend) {
|
|
|
12710
12789
|
}
|
|
12711
12790
|
});
|
|
12712
12791
|
queue.onTimeout = function () {
|
|
12713
|
-
|
|
12792
|
+
PerformanceMonitor$1.track(`${options.beacon}-gif-failure`);
|
|
12714
12793
|
};
|
|
12715
12794
|
queue.retryPending = true;
|
|
12716
12795
|
return queue;
|
|
@@ -13002,7 +13081,7 @@ var handleEmbeddedData = function (src) {
|
|
|
13002
13081
|
return src + '';
|
|
13003
13082
|
};
|
|
13004
13083
|
function getAttributeValue(element, attrName) {
|
|
13005
|
-
return
|
|
13084
|
+
return store.getters['nodeAttr/getAttribute']()(element, attrName);
|
|
13006
13085
|
}
|
|
13007
13086
|
var extractAttribute = function (element, attrName, type) {
|
|
13008
13087
|
if (!element || !element.nodeName)
|
|
@@ -21054,10 +21133,6 @@ class UpdateRunner {
|
|
|
21054
21133
|
}
|
|
21055
21134
|
}
|
|
21056
21135
|
complete(time) {
|
|
21057
|
-
store.commit('monitoring/setTimer', {
|
|
21058
|
-
name: 'guideUpdateTimeMS',
|
|
21059
|
-
time: this.updateTotalTime
|
|
21060
|
-
});
|
|
21061
21136
|
store.commit('guideUpdate/completeUpdate', time);
|
|
21062
21137
|
this.cancel();
|
|
21063
21138
|
}
|
|
@@ -26540,6 +26615,11 @@ var EventRouter = function () {
|
|
|
26540
26615
|
var config = configParam.value;
|
|
26541
26616
|
var cases = casesParam.value;
|
|
26542
26617
|
var conditionResult = evaluateCondition(conditionType, config);
|
|
26618
|
+
Events.trigger('appUsage', {
|
|
26619
|
+
type: 'conditionalSplitResult',
|
|
26620
|
+
elementId: evt.srcElement.id,
|
|
26621
|
+
conditionResult
|
|
26622
|
+
});
|
|
26543
26623
|
var matchingCase = _.find(cases, function (caseItem) {
|
|
26544
26624
|
return caseItem.value === conditionResult;
|
|
26545
26625
|
});
|
|
@@ -26607,16 +26687,27 @@ var GuideActivity = (function () {
|
|
|
26607
26687
|
var isObject = _.isObject;
|
|
26608
26688
|
var findWhere = _.findWhere;
|
|
26609
26689
|
const _guideResolvers = [];
|
|
26690
|
+
var conditionalSplitEventQueue = [];
|
|
26610
26691
|
return {
|
|
26611
26692
|
type: GA_TYPE,
|
|
26612
26693
|
handler(evtData) {
|
|
26613
26694
|
var appData = evtData.data[0];
|
|
26695
|
+
if (appData && appData.type === 'conditionalSplitResult') {
|
|
26696
|
+
finalizeConditionalSplitEvent(appData);
|
|
26697
|
+
return;
|
|
26698
|
+
}
|
|
26614
26699
|
var browserEvt = evtData.data[1];
|
|
26615
26700
|
if (!shouldHandleEvent(appData, browserEvt))
|
|
26616
26701
|
return;
|
|
26617
26702
|
var activityEvent = transformToGuideActivity(appData);
|
|
26618
26703
|
if (activityEvent) {
|
|
26619
|
-
|
|
26704
|
+
const firstAction = _.get(activityEvent, ['props', 'ui_element_actions', 0, 'action']);
|
|
26705
|
+
if (firstAction === 'conditionalSplit') {
|
|
26706
|
+
conditionalSplitEventQueue.push(activityEvent);
|
|
26707
|
+
}
|
|
26708
|
+
else {
|
|
26709
|
+
stageGuideEvent(activityEvent);
|
|
26710
|
+
}
|
|
26620
26711
|
}
|
|
26621
26712
|
},
|
|
26622
26713
|
registerGuideResolver(callBack) {
|
|
@@ -26629,6 +26720,22 @@ var GuideActivity = (function () {
|
|
|
26629
26720
|
}
|
|
26630
26721
|
}
|
|
26631
26722
|
};
|
|
26723
|
+
function finalizeConditionalSplitEvent(evtData) {
|
|
26724
|
+
const { conditionResult, elementId } = evtData;
|
|
26725
|
+
const matchingEventIndex = _.findIndex(conditionalSplitEventQueue, (event) => {
|
|
26726
|
+
return event.props.ui_element_id === elementId;
|
|
26727
|
+
});
|
|
26728
|
+
if (matchingEventIndex === -1)
|
|
26729
|
+
return;
|
|
26730
|
+
const matchingEvent = conditionalSplitEventQueue.splice(matchingEventIndex, 1)[0];
|
|
26731
|
+
const conditionalSplitAction = matchingEvent.props.ui_element_actions[0];
|
|
26732
|
+
conditionalSplitAction.condition_result = conditionResult;
|
|
26733
|
+
const cases = conditionalSplitAction.cases;
|
|
26734
|
+
const resultCase = cases[conditionResult];
|
|
26735
|
+
matchingEvent.props.ui_element_actions = matchingEvent.props.ui_element_actions.concat(resultCase);
|
|
26736
|
+
delete conditionalSplitAction.cases;
|
|
26737
|
+
stageGuideEvent(matchingEvent);
|
|
26738
|
+
}
|
|
26632
26739
|
function isClickEvent(browserEvt) {
|
|
26633
26740
|
return browserEvt && browserEvt.type === 'click';
|
|
26634
26741
|
}
|
|
@@ -26745,58 +26852,7 @@ var GuideActivity = (function () {
|
|
|
26745
26852
|
];
|
|
26746
26853
|
}
|
|
26747
26854
|
if (element.actions !== undefined) {
|
|
26748
|
-
return _.map(element.actions,
|
|
26749
|
-
switch (action.action) {
|
|
26750
|
-
case 'automation':
|
|
26751
|
-
var automationIds = findWhere(action.parameters, { name: 'automationIds' });
|
|
26752
|
-
return {
|
|
26753
|
-
action: action.action,
|
|
26754
|
-
automationIds
|
|
26755
|
-
};
|
|
26756
|
-
case 'openLink':
|
|
26757
|
-
var url = findWhere(action.parameters, { name: 'url' });
|
|
26758
|
-
var target = findWhere(action.parameters, { name: 'target' });
|
|
26759
|
-
return {
|
|
26760
|
-
action: action.action,
|
|
26761
|
-
url: sanitizeUrl(url.value),
|
|
26762
|
-
target: target.value
|
|
26763
|
-
};
|
|
26764
|
-
case 'submitPollAndGoToStep':
|
|
26765
|
-
case 'goToStep':
|
|
26766
|
-
var guideStepId = findWhere(action.parameters, { name: 'goToStepId' });
|
|
26767
|
-
return {
|
|
26768
|
-
action: action.action,
|
|
26769
|
-
guideStepId: guideStepId.value
|
|
26770
|
-
};
|
|
26771
|
-
case 'guideSnoozed':
|
|
26772
|
-
var duration = findWhere(action.parameters, { name: 'snooze_duration' });
|
|
26773
|
-
var timeUnit = findWhere(action.parameters, { name: 'time_unit' });
|
|
26774
|
-
return {
|
|
26775
|
-
action: action.action,
|
|
26776
|
-
duration: duration.value,
|
|
26777
|
-
timeUnit: timeUnit.value
|
|
26778
|
-
};
|
|
26779
|
-
case 'showGuide':
|
|
26780
|
-
case 'launchGuide':
|
|
26781
|
-
var guideId = action.parameters[0];
|
|
26782
|
-
var stepId = action.parameters[1] || {};
|
|
26783
|
-
return {
|
|
26784
|
-
action: action.action,
|
|
26785
|
-
guideId: guideId.value,
|
|
26786
|
-
stepId: stepId.value
|
|
26787
|
-
};
|
|
26788
|
-
case 'advanceGuide':
|
|
26789
|
-
case 'previousStep':
|
|
26790
|
-
case 'submitPoll':
|
|
26791
|
-
case 'dismissGuide':
|
|
26792
|
-
case 'confirmation':
|
|
26793
|
-
return {
|
|
26794
|
-
action: action.action
|
|
26795
|
-
};
|
|
26796
|
-
default:
|
|
26797
|
-
return {};
|
|
26798
|
-
}
|
|
26799
|
-
});
|
|
26855
|
+
return _.map(element.actions, processAction);
|
|
26800
26856
|
}
|
|
26801
26857
|
if (uiElement.templateName === 'pendo_task_list_item') {
|
|
26802
26858
|
if (_.isArray(element.templateChildren) && element.templateChildren[uiElement.templateChildIndex]) {
|
|
@@ -26808,6 +26864,79 @@ var GuideActivity = (function () {
|
|
|
26808
26864
|
}
|
|
26809
26865
|
return [];
|
|
26810
26866
|
}
|
|
26867
|
+
function processAction(action) {
|
|
26868
|
+
switch (action.action) {
|
|
26869
|
+
case 'automation':
|
|
26870
|
+
var automationIds = findWhere(action.parameters, { name: 'automationIds' });
|
|
26871
|
+
return {
|
|
26872
|
+
action: action.action,
|
|
26873
|
+
automationIds
|
|
26874
|
+
};
|
|
26875
|
+
case 'openLink':
|
|
26876
|
+
var url = findWhere(action.parameters, { name: 'url' });
|
|
26877
|
+
var target = findWhere(action.parameters, { name: 'target' });
|
|
26878
|
+
return {
|
|
26879
|
+
action: action.action,
|
|
26880
|
+
url: sanitizeUrl(url.value),
|
|
26881
|
+
target: target.value
|
|
26882
|
+
};
|
|
26883
|
+
case 'submitPollAndGoToStep':
|
|
26884
|
+
case 'goToStep':
|
|
26885
|
+
var guideStepId = findWhere(action.parameters, { name: 'goToStepId' });
|
|
26886
|
+
return {
|
|
26887
|
+
action: action.action,
|
|
26888
|
+
guideStepId: guideStepId.value
|
|
26889
|
+
};
|
|
26890
|
+
case 'guideSnoozed':
|
|
26891
|
+
var duration = findWhere(action.parameters, { name: 'snooze_duration' });
|
|
26892
|
+
var timeUnit = findWhere(action.parameters, { name: 'time_unit' });
|
|
26893
|
+
return {
|
|
26894
|
+
action: action.action,
|
|
26895
|
+
duration: duration.value,
|
|
26896
|
+
timeUnit: timeUnit.value
|
|
26897
|
+
};
|
|
26898
|
+
case 'showGuide':
|
|
26899
|
+
case 'launchGuide':
|
|
26900
|
+
var guideId = action.parameters[0];
|
|
26901
|
+
var stepId = action.parameters[1] || {};
|
|
26902
|
+
return {
|
|
26903
|
+
action: action.action,
|
|
26904
|
+
guideId: guideId.value,
|
|
26905
|
+
stepId: stepId.value
|
|
26906
|
+
};
|
|
26907
|
+
case 'conditionalSplit':
|
|
26908
|
+
var name = findWhere(action.parameters, { name: 'name' });
|
|
26909
|
+
var conditionType = findWhere(action.parameters, { name: 'conditionType' });
|
|
26910
|
+
var config = findWhere(action.parameters, { name: 'config' });
|
|
26911
|
+
var cases = findWhere(action.parameters, { name: 'cases' });
|
|
26912
|
+
var processedCases = _.reduce(cases.value, function (acc, c) {
|
|
26913
|
+
acc[c.value] = _.map(c.actions, function (a) {
|
|
26914
|
+
var processedAction = processAction(a);
|
|
26915
|
+
processedAction.source = a.source;
|
|
26916
|
+
return processedAction;
|
|
26917
|
+
});
|
|
26918
|
+
return acc;
|
|
26919
|
+
}, {});
|
|
26920
|
+
return {
|
|
26921
|
+
action: action.action,
|
|
26922
|
+
name: name.value,
|
|
26923
|
+
condition_type: conditionType.value,
|
|
26924
|
+
element_selector: config.value.elementSelector,
|
|
26925
|
+
feature_id: config.value.featureId,
|
|
26926
|
+
cases: processedCases // will be removed in finalizeConditionalSplitEvent
|
|
26927
|
+
};
|
|
26928
|
+
case 'advanceGuide':
|
|
26929
|
+
case 'previousStep':
|
|
26930
|
+
case 'submitPoll':
|
|
26931
|
+
case 'dismissGuide':
|
|
26932
|
+
case 'confirmation':
|
|
26933
|
+
return {
|
|
26934
|
+
action: action.action
|
|
26935
|
+
};
|
|
26936
|
+
default:
|
|
26937
|
+
return {};
|
|
26938
|
+
}
|
|
26939
|
+
}
|
|
26811
26940
|
function transformToGuideActivity(appData) {
|
|
26812
26941
|
var activeGuideObj = getGuideForEvent(appData);
|
|
26813
26942
|
if (!activeGuideObj)
|
|
@@ -27006,14 +27135,14 @@ var didAccountIdentityChange = function (props) {
|
|
|
27006
27135
|
function initIdentityEvents() {
|
|
27007
27136
|
if (initialized)
|
|
27008
27137
|
return;
|
|
27009
|
-
|
|
27138
|
+
const collectIdentifyEvent = function (event) {
|
|
27010
27139
|
var props = event.data[0];
|
|
27011
27140
|
if (wasAnonymousVisitorIdentified(props) || didAccountIdentityChange(props)) {
|
|
27012
27141
|
collectEvent('identify', props);
|
|
27013
27142
|
flushLater(); // unconditionally on next tick
|
|
27014
27143
|
}
|
|
27015
|
-
}
|
|
27016
|
-
|
|
27144
|
+
};
|
|
27145
|
+
const collectMetadataEvent = function (event) {
|
|
27017
27146
|
// Check to see if this Application is sending metadata to the backend using
|
|
27018
27147
|
// different mechanism (like Segment webhooks)
|
|
27019
27148
|
var blockAgentMetadata = isMetadataBlocked();
|
|
@@ -27024,9 +27153,17 @@ function initIdentityEvents() {
|
|
|
27024
27153
|
flushLater(); // unconditionally on next tick
|
|
27025
27154
|
}
|
|
27026
27155
|
}
|
|
27027
|
-
}
|
|
27156
|
+
};
|
|
27157
|
+
Events.identify.on(collectIdentifyEvent);
|
|
27158
|
+
Events.metadata.on(collectMetadataEvent);
|
|
27028
27159
|
Events.identify.on(handleIdentifyEvent);
|
|
27029
27160
|
initialized = true;
|
|
27161
|
+
return function () {
|
|
27162
|
+
Events.identify.off(collectIdentifyEvent);
|
|
27163
|
+
Events.metadata.off(collectMetadataEvent);
|
|
27164
|
+
Events.identify.off(handleIdentifyEvent);
|
|
27165
|
+
initialized = false;
|
|
27166
|
+
};
|
|
27030
27167
|
}
|
|
27031
27168
|
|
|
27032
27169
|
/*
|
|
@@ -27237,7 +27374,7 @@ class ShadowDomManager extends EventTarget {
|
|
|
27237
27374
|
}
|
|
27238
27375
|
initialize() {
|
|
27239
27376
|
this.unpatchAttachShadow = this.patchAttachShadow(Element);
|
|
27240
|
-
this.findShadowRoots(document);
|
|
27377
|
+
this.findShadowRoots(document, 5000, (shadowRoot) => this.triggerAttachShadow(shadowRoot));
|
|
27241
27378
|
}
|
|
27242
27379
|
triggerAttachShadow(shadowRoot) {
|
|
27243
27380
|
this.cache.add(shadowRoot);
|
|
@@ -27246,7 +27383,7 @@ class ShadowDomManager extends EventTarget {
|
|
|
27246
27383
|
shadowRoot
|
|
27247
27384
|
});
|
|
27248
27385
|
}
|
|
27249
|
-
findShadowRoots(document, maxPerSearch = 5000) {
|
|
27386
|
+
findShadowRoots(document, maxPerSearch = 5000, onShadowRootFound) {
|
|
27250
27387
|
if (!_.isFunction(document.createNodeIterator))
|
|
27251
27388
|
return;
|
|
27252
27389
|
let nodesChecked = 0;
|
|
@@ -27262,7 +27399,7 @@ class ShadowDomManager extends EventTarget {
|
|
|
27262
27399
|
while ((currentNode = iterator.nextNode())) {
|
|
27263
27400
|
nodesChecked++;
|
|
27264
27401
|
if (currentNode && currentNode.shadowRoot) {
|
|
27265
|
-
|
|
27402
|
+
onShadowRootFound(currentNode.shadowRoot);
|
|
27266
27403
|
queue.push(currentNode.shadowRoot);
|
|
27267
27404
|
this.foundShadowRoots = true;
|
|
27268
27405
|
}
|
|
@@ -27383,7 +27520,8 @@ function registerEventHandlers({ events = [] }) {
|
|
|
27383
27520
|
let initializeCounter = 0;
|
|
27384
27521
|
const initializeImmediately = 'initializeImmediately';
|
|
27385
27522
|
/**
|
|
27386
|
-
* Initializes the Pendo
|
|
27523
|
+
* Initializes the Pendo agent in a browser window. This function only needs to be called once per page load. Any subsequent calls, without first having called `teardown`, will be ignored.
|
|
27524
|
+
* Once the agent has been initialized, any updates to identity or metadata should be done using `identify` or `updateOptions`.
|
|
27387
27525
|
*
|
|
27388
27526
|
* @access public
|
|
27389
27527
|
* @function
|
|
@@ -27529,13 +27667,14 @@ const initialize = makeSafe(function (options) {
|
|
|
27529
27667
|
teardownFns.push(forwardInternalEvents(Events));
|
|
27530
27668
|
registerEventHandlers(options);
|
|
27531
27669
|
teardownFns.push(initGuides(observer)); // this is safe. loadGuides actually does the loading.
|
|
27532
|
-
initIdentityEvents(); // setup identify and meta event listeners
|
|
27670
|
+
teardownFns.push(initIdentityEvents()); // setup identify and meta event listeners
|
|
27533
27671
|
teardownFns.push(wirePage());
|
|
27534
27672
|
teardownFns.push(initializePlugins());
|
|
27535
27673
|
teardownFns.push(launchDesignerOrPreview(options));
|
|
27536
27674
|
Events.appUsage.on(GuideActivity.handler);
|
|
27537
27675
|
Events.appUsage.on(ResourceCenterActivity.handler);
|
|
27538
27676
|
teardownFns.push(flushEvery(SEND_INTERVAL));
|
|
27677
|
+
teardownFns.push(PerformanceMonitor$1.initialize());
|
|
27539
27678
|
}
|
|
27540
27679
|
Events.appHidden.on(() => {
|
|
27541
27680
|
flushNow(true, { hidden: true });
|
|
@@ -29028,11 +29167,14 @@ var attrActionEnum = {
|
|
|
29028
29167
|
href: ['Replace', 'ForceSecure'],
|
|
29029
29168
|
protocol: ['ForceSecure']
|
|
29030
29169
|
};
|
|
29031
|
-
|
|
29170
|
+
const TARGETS = ['location', 'attribute', 'both'];
|
|
29171
|
+
const DEFAULT_TARGET = 'location';
|
|
29172
|
+
function UrlTransform(attr, action, data, target) {
|
|
29032
29173
|
if (_.isObject(attr)) {
|
|
29033
29174
|
action = attr.action;
|
|
29034
29175
|
data = attr.data;
|
|
29035
29176
|
attr = attr.attr;
|
|
29177
|
+
target = attr.target;
|
|
29036
29178
|
}
|
|
29037
29179
|
if (!attrActionEnum[attr]) {
|
|
29038
29180
|
var validAttrs = _.keys(attrActionEnum).join(', ');
|
|
@@ -29042,11 +29184,16 @@ function UrlAttrTransform(attr, action, data) {
|
|
|
29042
29184
|
var validActions = attrActionEnum[attr].join(', ');
|
|
29043
29185
|
throw new Error('Invalid transform action: "' + action + '" for attribute "' + attr + '". Valid actions for "' + attr + '" are: ' + validActions + '. Example: {attr: "' + attr + '", action: "' + attrActionEnum[attr][0] + '", data: ...}');
|
|
29044
29186
|
}
|
|
29187
|
+
// validate 'target'
|
|
29188
|
+
if (TARGETS.indexOf(target) < 0) {
|
|
29189
|
+
target = DEFAULT_TARGET;
|
|
29190
|
+
}
|
|
29045
29191
|
this.attr = attr;
|
|
29046
29192
|
this.action = action;
|
|
29047
29193
|
this.data = data;
|
|
29194
|
+
this.target = target || DEFAULT_TARGET;
|
|
29048
29195
|
}
|
|
29049
|
-
|
|
29196
|
+
UrlTransform.prototype.applyTo = function (url) {
|
|
29050
29197
|
var actionImpls = {
|
|
29051
29198
|
AllowOnlyKeys(url, attr, data) {
|
|
29052
29199
|
if (_.isFunction(data)) {
|
|
@@ -29119,26 +29266,26 @@ UrlAttrTransform.prototype.applyToURL = function (url) {
|
|
|
29119
29266
|
};
|
|
29120
29267
|
return actionImpls[this.action](url, this.attr, this.data);
|
|
29121
29268
|
};
|
|
29122
|
-
|
|
29269
|
+
UrlTransform.prototype.toString = function () {
|
|
29123
29270
|
return this.attr + ' - ' + this.action + ' - ' + JSON.stringify(this.data);
|
|
29124
29271
|
};
|
|
29125
29272
|
// Static method, not on the instance
|
|
29126
|
-
|
|
29127
|
-
if (obj instanceof
|
|
29273
|
+
UrlTransform.fromJSON = function (obj) {
|
|
29274
|
+
if (obj instanceof UrlTransform) {
|
|
29128
29275
|
return obj;
|
|
29129
29276
|
}
|
|
29130
29277
|
// Validate input is an object
|
|
29131
29278
|
if (!_.isObject(obj)) {
|
|
29132
|
-
throw new Error('
|
|
29279
|
+
throw new Error('UrlTransform.fromJSON expects an object. Received: ' + typeof obj + '. Example: {attr: "search", action: "AddTo", data: {key: "value"}}');
|
|
29133
29280
|
}
|
|
29134
29281
|
// Validate required properties
|
|
29135
29282
|
if (!obj.attr) {
|
|
29136
29283
|
var allValidAttrs = _.keys(attrActionEnum).join(', ');
|
|
29137
|
-
throw new Error('
|
|
29284
|
+
throw new Error('UrlTransform is missing required "attr" property. Valid attributes are: ' + allValidAttrs + '. Example: {attr: "search", action: "AddTo", data: {key: "value"}}');
|
|
29138
29285
|
}
|
|
29139
29286
|
if (!obj.action) {
|
|
29140
29287
|
var attrValidActions = attrActionEnum[obj.attr] ? attrActionEnum[obj.attr].join(', ') : 'AllowOnlyKeys, ExcludeKeys, AddTo, Replace, Clear';
|
|
29141
|
-
throw new Error('
|
|
29288
|
+
throw new Error('UrlTransform is missing required "action" property. Valid actions depend on the attribute. For "' + obj.attr + '" attribute, valid actions are: ' + attrValidActions + '. Example: {attr: "' + obj.attr + '", action: "AddTo", data: {key: "value"}}');
|
|
29142
29289
|
}
|
|
29143
29290
|
// Validate attribute and action combination
|
|
29144
29291
|
if (!attrActionEnum[obj.attr]) {
|
|
@@ -29177,7 +29324,7 @@ UrlAttrTransform.fromJSON = function (obj) {
|
|
|
29177
29324
|
}
|
|
29178
29325
|
}
|
|
29179
29326
|
try {
|
|
29180
|
-
return new
|
|
29327
|
+
return new UrlTransform(obj.attr, obj.action, obj.data, obj.target);
|
|
29181
29328
|
}
|
|
29182
29329
|
catch (error) {
|
|
29183
29330
|
// If it's already a detailed error from our validation, re-throw it
|
|
@@ -29186,7 +29333,7 @@ UrlAttrTransform.fromJSON = function (obj) {
|
|
|
29186
29333
|
throw error;
|
|
29187
29334
|
}
|
|
29188
29335
|
// Otherwise, wrap the original error with context
|
|
29189
|
-
throw new Error('Failed to create
|
|
29336
|
+
throw new Error('Failed to create UrlTransform: ' + error.message + '. Transform object: ' + JSON.stringify(obj));
|
|
29190
29337
|
}
|
|
29191
29338
|
};
|
|
29192
29339
|
|
|
@@ -29196,13 +29343,13 @@ function isURL(u) {
|
|
|
29196
29343
|
var LocationModule = (function (global) {
|
|
29197
29344
|
var createElectronTranforms = function (appname, resourcesPath, directory, userHome) {
|
|
29198
29345
|
return [
|
|
29199
|
-
new
|
|
29346
|
+
new UrlTransform('pathname', 'Replace', function (path) {
|
|
29200
29347
|
var newPath = path.replace(resourcesPath, appname);
|
|
29201
29348
|
newPath = newPath.replace(directory, appname);
|
|
29202
29349
|
newPath = newPath.replace(userHome, '');
|
|
29203
29350
|
return newPath;
|
|
29204
29351
|
}),
|
|
29205
|
-
new
|
|
29352
|
+
new UrlTransform('href', 'ForceSecure')
|
|
29206
29353
|
];
|
|
29207
29354
|
};
|
|
29208
29355
|
var DEFAULT_SRC_FN = function () {
|
|
@@ -29241,17 +29388,23 @@ var LocationModule = (function (global) {
|
|
|
29241
29388
|
},
|
|
29242
29389
|
addTransforms(context, transforms) {
|
|
29243
29390
|
_.each(transforms, function (f) {
|
|
29244
|
-
|
|
29391
|
+
const t = UrlTransform.fromJSON(f);
|
|
29392
|
+
if (t.target === 'location' || t.target === 'both') {
|
|
29393
|
+
context.commit('addTransform', t);
|
|
29394
|
+
}
|
|
29395
|
+
if (t.target === 'attribute' || t.target === 'both') {
|
|
29396
|
+
store.dispatch('nodeAttr/addAttrTransform', t);
|
|
29397
|
+
}
|
|
29245
29398
|
});
|
|
29246
29399
|
},
|
|
29247
29400
|
addInternalTransforms(context, transforms) {
|
|
29248
29401
|
_.each(transforms, function (f) {
|
|
29249
|
-
context.commit('addInternalTransform',
|
|
29402
|
+
context.commit('addInternalTransform', UrlTransform.fromJSON(f));
|
|
29250
29403
|
});
|
|
29251
29404
|
},
|
|
29252
29405
|
removeInternalTransforms(context, transforms) {
|
|
29253
29406
|
_.each(transforms, function (f) {
|
|
29254
|
-
context.commit('removeInternalTransform',
|
|
29407
|
+
context.commit('removeInternalTransform', UrlTransform.fromJSON(f));
|
|
29255
29408
|
});
|
|
29256
29409
|
},
|
|
29257
29410
|
startPolling(context) {
|
|
@@ -29279,6 +29432,7 @@ var LocationModule = (function (global) {
|
|
|
29279
29432
|
},
|
|
29280
29433
|
clearTransforms(state) {
|
|
29281
29434
|
state.transforms = [];
|
|
29435
|
+
store.commit('nodeAttr/clearURLTransforms');
|
|
29282
29436
|
},
|
|
29283
29437
|
clearInternalTransforms(state) {
|
|
29284
29438
|
state.internalTransforms = [];
|
|
@@ -29334,7 +29488,7 @@ var LocationModule = (function (global) {
|
|
|
29334
29488
|
};
|
|
29335
29489
|
var transformUrl = function (transforms, url) {
|
|
29336
29490
|
return _.reduce(transforms, function (tUrl, f) {
|
|
29337
|
-
return f.
|
|
29491
|
+
return f.applyTo(tUrl);
|
|
29338
29492
|
}, url);
|
|
29339
29493
|
};
|
|
29340
29494
|
var urlGetter = function (state) {
|
|
@@ -32551,10 +32705,12 @@ var GuideUpdateModule = (function () {
|
|
|
32551
32705
|
state.scheduledUpdate = scheduledUpdate;
|
|
32552
32706
|
},
|
|
32553
32707
|
startUpdate(state, time) {
|
|
32708
|
+
PerformanceMonitor$1.startTimer('guide-loop');
|
|
32554
32709
|
state.needsUpdate = false;
|
|
32555
32710
|
state.updateId = time;
|
|
32556
32711
|
},
|
|
32557
32712
|
completeUpdate(state, time) {
|
|
32713
|
+
PerformanceMonitor$1.stopTimer('guide-loop');
|
|
32558
32714
|
state.updateId = null;
|
|
32559
32715
|
state.updateCompleteTime = time;
|
|
32560
32716
|
}
|
|
@@ -32663,75 +32819,6 @@ var HealthCheckModule = (function () {
|
|
|
32663
32819
|
};
|
|
32664
32820
|
})();
|
|
32665
32821
|
|
|
32666
|
-
var MonitoringModule = (function () {
|
|
32667
|
-
var state = {
|
|
32668
|
-
lastFlush: getNow(),
|
|
32669
|
-
flushInterval: 5 * 60 * 1000,
|
|
32670
|
-
counters: {
|
|
32671
|
-
ptmGifFailures: 0,
|
|
32672
|
-
guideGifFailures: 0
|
|
32673
|
-
},
|
|
32674
|
-
timers: {}
|
|
32675
|
-
};
|
|
32676
|
-
var actions = {
|
|
32677
|
-
flush(context) {
|
|
32678
|
-
_.each(context.state.counters, function (value, counterName) {
|
|
32679
|
-
context.commit('resetCounter', counterName);
|
|
32680
|
-
});
|
|
32681
|
-
_.each(context.state.timers, function (value, timerName) {
|
|
32682
|
-
context.commit('resetTimer', timerName);
|
|
32683
|
-
});
|
|
32684
|
-
context.commit('setLastFlush', context.getters.now());
|
|
32685
|
-
}
|
|
32686
|
-
};
|
|
32687
|
-
var mutations = {
|
|
32688
|
-
setLastFlush(state, lastFlush) {
|
|
32689
|
-
state.lastFlush = lastFlush;
|
|
32690
|
-
},
|
|
32691
|
-
incrementCounter(state, counterName) {
|
|
32692
|
-
if (state.counters[counterName] === undefined)
|
|
32693
|
-
return;
|
|
32694
|
-
state.counters[counterName]++;
|
|
32695
|
-
},
|
|
32696
|
-
resetCounter(state, counterName) {
|
|
32697
|
-
if (state.counters[counterName] === undefined)
|
|
32698
|
-
return;
|
|
32699
|
-
state.counters[counterName] = 0;
|
|
32700
|
-
},
|
|
32701
|
-
setTimer(state, { name, time } = {}) {
|
|
32702
|
-
if (!name || time == null)
|
|
32703
|
-
return;
|
|
32704
|
-
state.timers[name] = time;
|
|
32705
|
-
},
|
|
32706
|
-
resetTimer(state, timerName) {
|
|
32707
|
-
delete state.timers[timerName];
|
|
32708
|
-
}
|
|
32709
|
-
};
|
|
32710
|
-
var getters = {
|
|
32711
|
-
shouldFlush(state, getters) {
|
|
32712
|
-
return (getters.now() - state.lastFlush) >= state.flushInterval;
|
|
32713
|
-
},
|
|
32714
|
-
payload(state) {
|
|
32715
|
-
var counters = _.reduce(state.counters, function (obj, value, key) {
|
|
32716
|
-
if (value > 0) {
|
|
32717
|
-
obj[key] = value;
|
|
32718
|
-
}
|
|
32719
|
-
return obj;
|
|
32720
|
-
}, {});
|
|
32721
|
-
return _.extend({}, counters, state.timers);
|
|
32722
|
-
},
|
|
32723
|
-
now() {
|
|
32724
|
-
return getNow();
|
|
32725
|
-
}
|
|
32726
|
-
};
|
|
32727
|
-
return {
|
|
32728
|
-
state,
|
|
32729
|
-
actions,
|
|
32730
|
-
mutations,
|
|
32731
|
-
getters
|
|
32732
|
-
};
|
|
32733
|
-
})();
|
|
32734
|
-
|
|
32735
32822
|
var MetadataModule = (function () {
|
|
32736
32823
|
var state = {
|
|
32737
32824
|
visitor: {},
|
|
@@ -32920,7 +33007,6 @@ const DebuggerModule = (() => {
|
|
|
32920
33007
|
context.commit('setTabId', EventTracer.getTabId());
|
|
32921
33008
|
context.commit('setInstallType', getInstallType());
|
|
32922
33009
|
const isTop = isLeader() && window.top === window; // only a leader frame that is a top window can launch debugger
|
|
32923
|
-
state.isTop !== isTop;
|
|
32924
33010
|
context.commit('setIsTop', isTop);
|
|
32925
33011
|
context.commit('isLeader', isLeader());
|
|
32926
33012
|
if (isTop) {
|
|
@@ -32971,6 +33057,8 @@ const DebuggerModule = (() => {
|
|
|
32971
33057
|
context.commit('enableEventLogging', enabled);
|
|
32972
33058
|
},
|
|
32973
33059
|
eventCaptured: (context, data) => {
|
|
33060
|
+
if (pendo$1.designerEnabled || isInPreviewMode() || isInDesignerPreviewMode())
|
|
33061
|
+
return;
|
|
32974
33062
|
if (!context.state.isTop) {
|
|
32975
33063
|
crossFrameChannel.postMessage({
|
|
32976
33064
|
action: 'debugger/receiveEventCaptured',
|
|
@@ -33209,6 +33297,68 @@ const DebuggerModule = (() => {
|
|
|
33209
33297
|
};
|
|
33210
33298
|
})();
|
|
33211
33299
|
|
|
33300
|
+
const NodeAttrModule = (function (global) {
|
|
33301
|
+
const state = {
|
|
33302
|
+
transforms: []
|
|
33303
|
+
};
|
|
33304
|
+
const actions = {
|
|
33305
|
+
addAttrTransform(context, urlTransform) {
|
|
33306
|
+
context.commit('addTransform', urlTransform);
|
|
33307
|
+
}
|
|
33308
|
+
};
|
|
33309
|
+
const mutations = {
|
|
33310
|
+
addTransform(state, transform) {
|
|
33311
|
+
state.transforms.push(transform);
|
|
33312
|
+
},
|
|
33313
|
+
clearURLTransforms(state) {
|
|
33314
|
+
// XXX if ever support non url transforms for attributes then we'll need to check the Transform type
|
|
33315
|
+
// or determine some other way how to purge only URL transforms as Location API provides a way for these to be
|
|
33316
|
+
// cleared via the API.
|
|
33317
|
+
state.transforms = [];
|
|
33318
|
+
}
|
|
33319
|
+
};
|
|
33320
|
+
const applyTransforms = (transforms, url) => {
|
|
33321
|
+
return _.reduce(transforms, function (tUrl, f) {
|
|
33322
|
+
return f.applyTo(tUrl);
|
|
33323
|
+
}, url);
|
|
33324
|
+
};
|
|
33325
|
+
const resolveAttrValueAsURL = (attrValue) => {
|
|
33326
|
+
// let's let the browser do this work for us...
|
|
33327
|
+
const a = document.createElement('a'); // this handles relative urls nicely
|
|
33328
|
+
a.href = attrValue;
|
|
33329
|
+
return new URL(a.href);
|
|
33330
|
+
};
|
|
33331
|
+
const getters = {
|
|
33332
|
+
getAttribute(state) {
|
|
33333
|
+
return function (element, attrName) {
|
|
33334
|
+
let attrValue = element.getAttribute ? element.getAttribute(attrName) : element[attrName];
|
|
33335
|
+
if (_.size(state.transforms) < 1) {
|
|
33336
|
+
return attrValue;
|
|
33337
|
+
}
|
|
33338
|
+
try {
|
|
33339
|
+
let url = resolveAttrValueAsURL(attrValue);
|
|
33340
|
+
url = _.reduce([
|
|
33341
|
+
_.partial(applyTransforms, state.transforms)
|
|
33342
|
+
], (url, fn) => {
|
|
33343
|
+
return fn(url);
|
|
33344
|
+
}, url);
|
|
33345
|
+
return url.href;
|
|
33346
|
+
}
|
|
33347
|
+
catch (e) {
|
|
33348
|
+
log.critical(e);
|
|
33349
|
+
return attrValue;
|
|
33350
|
+
}
|
|
33351
|
+
};
|
|
33352
|
+
}
|
|
33353
|
+
};
|
|
33354
|
+
return {
|
|
33355
|
+
state,
|
|
33356
|
+
actions,
|
|
33357
|
+
mutations,
|
|
33358
|
+
getters
|
|
33359
|
+
};
|
|
33360
|
+
})();
|
|
33361
|
+
|
|
33212
33362
|
function registerModules(store) {
|
|
33213
33363
|
store.registerModule('debugger', DebuggerModule);
|
|
33214
33364
|
store.registerModule('errorLog', ErrorLogModule);
|
|
@@ -33217,9 +33367,9 @@ function registerModules(store) {
|
|
|
33217
33367
|
store.registerModule('guideState', GuideStateModule);
|
|
33218
33368
|
store.registerModule('healthCheck', HealthCheckModule);
|
|
33219
33369
|
store.registerModule('location', LocationModule);
|
|
33220
|
-
store.registerModule('monitoring', MonitoringModule);
|
|
33221
33370
|
store.registerModule('metadata', MetadataModule);
|
|
33222
33371
|
store.registerModule('preview', PreviewModule);
|
|
33372
|
+
store.registerModule('nodeAttr', NodeAttrModule);
|
|
33223
33373
|
}
|
|
33224
33374
|
|
|
33225
33375
|
const IFrameMonitor = (function () {
|
|
@@ -36262,7 +36412,7 @@ const EventProperties = (function () {
|
|
|
36262
36412
|
return [];
|
|
36263
36413
|
}
|
|
36264
36414
|
return [
|
|
36265
|
-
new
|
|
36415
|
+
new UrlTransform('search', 'AddTo', function () { return collectPageEventProperties(); })
|
|
36266
36416
|
];
|
|
36267
36417
|
}
|
|
36268
36418
|
function createPageEventProperties() {
|
|
@@ -47304,6 +47454,7 @@ class SessionRecorder {
|
|
|
47304
47454
|
this.sendQueue = new SendQueue(bind(this.transport.send, this.transport));
|
|
47305
47455
|
this.sendQueue.onTimeout = bind(this.sendFailure, this, 'SEND_TIMEOUT');
|
|
47306
47456
|
this.isNewSession = false;
|
|
47457
|
+
this.isCheckingVisitorEligibility = false;
|
|
47307
47458
|
this.addConfigOptions();
|
|
47308
47459
|
this.config = configReader.get(RECORDING_CONFIG);
|
|
47309
47460
|
this.onRecordingStart = this.pendo._.isFunction(configReader.get(RECORDING_CONFIG_ON_RECORDING_START))
|
|
@@ -47406,19 +47557,32 @@ class SessionRecorder {
|
|
|
47406
47557
|
clearTimeout(this._changeIdentityTimer);
|
|
47407
47558
|
this.visitorId = options.visitor.id;
|
|
47408
47559
|
this.accountId = options.account.id;
|
|
47409
|
-
return this.
|
|
47410
|
-
if ((!visitorConfig || !visitorConfig.enable) && this.isRecording()) {
|
|
47411
|
-
this.stop();
|
|
47412
|
-
}
|
|
47413
|
-
else if (visitorConfig && visitorConfig.enable && !this.isRecording()) {
|
|
47414
|
-
this._startRecordingForVisitor(visitorConfig);
|
|
47415
|
-
}
|
|
47416
|
-
}).catch((e) => {
|
|
47417
|
-
this.api.log.critical('Failed to re-fetch recording config', { error: e });
|
|
47418
|
-
this.logStopReason('VISITOR_CONFIG_ERROR');
|
|
47419
|
-
});
|
|
47560
|
+
return this.checkVisitorEligibility();
|
|
47420
47561
|
}
|
|
47421
47562
|
}
|
|
47563
|
+
checkVisitorEligibility(continuationCallback) {
|
|
47564
|
+
if (!this.isRecording() && this.pendo._.isNull(this.visitorId) && this.pendo._.isNull(this.accountId))
|
|
47565
|
+
return;
|
|
47566
|
+
this.isCheckingVisitorEligibility = true;
|
|
47567
|
+
return this.fetchVisitorConfig().then(visitorConfig => {
|
|
47568
|
+
if ((!visitorConfig || !visitorConfig.enable) && this.isRecording()) {
|
|
47569
|
+
this.stop();
|
|
47570
|
+
}
|
|
47571
|
+
if (visitorConfig && visitorConfig.enable && this.isRecording()) {
|
|
47572
|
+
if (continuationCallback) {
|
|
47573
|
+
continuationCallback.call(this);
|
|
47574
|
+
}
|
|
47575
|
+
}
|
|
47576
|
+
if (visitorConfig && visitorConfig.enable && !this.isRecording()) {
|
|
47577
|
+
this._startRecordingForVisitor(visitorConfig);
|
|
47578
|
+
}
|
|
47579
|
+
}).catch((e) => {
|
|
47580
|
+
this.api.log.critical('Failed to re-fetch recording config', { error: e });
|
|
47581
|
+
this.logStopReason('VISITOR_CONFIG_ERROR');
|
|
47582
|
+
}).finally(() => {
|
|
47583
|
+
this.isCheckingVisitorEligibility = false;
|
|
47584
|
+
});
|
|
47585
|
+
}
|
|
47422
47586
|
snapshot() {
|
|
47423
47587
|
if (!this.isRecording())
|
|
47424
47588
|
return;
|
|
@@ -47680,13 +47844,24 @@ class SessionRecorder {
|
|
|
47680
47844
|
if ((!prevLastEmitTime && isMeta)) {
|
|
47681
47845
|
skipUserInteractionCheck = true;
|
|
47682
47846
|
}
|
|
47683
|
-
|
|
47847
|
+
// Ensures events emitted while the visitor eligibility check is in flight are compared against events emitted
|
|
47848
|
+
// before the visitor eligibility check occurred. This means these events which fall outside of the inactivity
|
|
47849
|
+
// duration will not be placed in the buffer and captured. This is ok since they occurred outside of the
|
|
47850
|
+
// inactivity period and before the next snapshot.
|
|
47851
|
+
if (!this.isCheckingVisitorEligibility) {
|
|
47852
|
+
this.storeLastUserInteractionEventInformation(event, this.visitorId, this.accountId, skipUserInteractionCheck);
|
|
47853
|
+
}
|
|
47684
47854
|
const inactivityDuration = this.pendo._.get(this.visitorConfig, 'inactivityDuration', THIRTY_MINUTES);
|
|
47685
47855
|
if (prevLastEmitTime && event.timestamp - prevLastEmitTime > inactivityDuration && !isSnapshot && !isMeta) {
|
|
47686
|
-
this.
|
|
47687
|
-
|
|
47688
|
-
|
|
47689
|
-
|
|
47856
|
+
if (!this.isCheckingVisitorEligibility) {
|
|
47857
|
+
const continuationCallback = function () {
|
|
47858
|
+
this.send();
|
|
47859
|
+
this.clearSessionInfo();
|
|
47860
|
+
this.snapshot();
|
|
47861
|
+
};
|
|
47862
|
+
this.checkVisitorEligibility(continuationCallback);
|
|
47863
|
+
}
|
|
47864
|
+
return;
|
|
47690
47865
|
}
|
|
47691
47866
|
/*
|
|
47692
47867
|
* META events and Snapshots are special and need to be packaged together. This is made possible by
|
|
@@ -47721,8 +47896,16 @@ class SessionRecorder {
|
|
|
47721
47896
|
const exceedsEventFreq = this.eventsSinceLastKeyFrame >= this.pendo._.get(this.visitorConfig, 'keyframeEventFrequency', 4548); // Defaults determined by BE originally, shouldn't really ever be used
|
|
47722
47897
|
const exceedsRecordingSizeLimit = this.currentRecordingSize >= this.pendo._.get(this.visitorConfig, 'recordingSizeLimit', ONE_HUNDRED_MB_IN_BYTES);
|
|
47723
47898
|
if (exceeds24Hours || (exceedsTimeFreq && exceedsEventFreq) || exceedsRecordingSizeLimit) {
|
|
47724
|
-
|
|
47725
|
-
|
|
47899
|
+
const continuationCallback = function () {
|
|
47900
|
+
this.currentRecordingSize = 0;
|
|
47901
|
+
this.snapshot();
|
|
47902
|
+
};
|
|
47903
|
+
if (exceeds24Hours && !this.isCheckingVisitorEligibility) {
|
|
47904
|
+
this.checkVisitorEligibility(continuationCallback);
|
|
47905
|
+
}
|
|
47906
|
+
else {
|
|
47907
|
+
continuationCallback.call(this);
|
|
47908
|
+
}
|
|
47726
47909
|
}
|
|
47727
47910
|
}
|
|
47728
47911
|
}
|
|
@@ -48961,17 +49144,14 @@ class ConsoleCaptureBuffer {
|
|
|
48961
49144
|
constructor(pendo, pluginAPI) {
|
|
48962
49145
|
this.pendo = pendo;
|
|
48963
49146
|
this.pluginAPI = pluginAPI;
|
|
48964
|
-
this.
|
|
48965
|
-
this.warnEvents = [];
|
|
48966
|
-
this.errorEvents = [];
|
|
49147
|
+
this.events = [];
|
|
48967
49148
|
this.lastEvent = null;
|
|
48968
|
-
this.devLogEvent = null;
|
|
48969
49149
|
this.tokens = TOKEN_MAX_SIZE;
|
|
48970
49150
|
this.lastRefillTime = this.pluginAPI.util.getNow();
|
|
48971
49151
|
this.nextRefillTime = this.lastRefillTime + TOKEN_REFRESH_INTERVAL;
|
|
48972
49152
|
}
|
|
48973
49153
|
isEmpty() {
|
|
48974
|
-
return this.
|
|
49154
|
+
return this.events.length === 0;
|
|
48975
49155
|
}
|
|
48976
49156
|
refillTokens() {
|
|
48977
49157
|
const now = this.pluginAPI.util.getNow();
|
|
@@ -48985,10 +49165,8 @@ class ConsoleCaptureBuffer {
|
|
|
48985
49165
|
}
|
|
48986
49166
|
}
|
|
48987
49167
|
clear() {
|
|
49168
|
+
this.events = [];
|
|
48988
49169
|
this.lastEvent = null;
|
|
48989
|
-
this.infoEvents.length = 0;
|
|
48990
|
-
this.warnEvents.length = 0;
|
|
48991
|
-
this.errorEvents.length = 0;
|
|
48992
49170
|
}
|
|
48993
49171
|
push(event) {
|
|
48994
49172
|
const { devLogLevel } = event;
|
|
@@ -48998,50 +49176,16 @@ class ConsoleCaptureBuffer {
|
|
|
48998
49176
|
if (this.tokens === 0)
|
|
48999
49177
|
return false;
|
|
49000
49178
|
this.lastEvent = event;
|
|
49001
|
-
this.
|
|
49179
|
+
this.events.push(event);
|
|
49002
49180
|
this.tokens = Math.max(this.tokens - 1, 0);
|
|
49003
49181
|
return true;
|
|
49004
49182
|
}
|
|
49005
|
-
|
|
49006
|
-
switch (event.devLogLevel) {
|
|
49007
|
-
case 'info':
|
|
49008
|
-
this.infoEvents.push(event);
|
|
49009
|
-
break;
|
|
49010
|
-
case 'warn':
|
|
49011
|
-
this.warnEvents.push(event);
|
|
49012
|
-
break;
|
|
49013
|
-
case 'error':
|
|
49014
|
-
this.errorEvents.push(event);
|
|
49015
|
-
break;
|
|
49016
|
-
}
|
|
49017
|
-
}
|
|
49018
|
-
createDevLogEventWithPayload({ events, level }) {
|
|
49019
|
-
if (events.length === 0)
|
|
49020
|
-
return;
|
|
49021
|
-
const totalCount = this.pendo._.reduce(events, (sum, event) => sum + (event.devLogCount || 1), 0);
|
|
49022
|
-
return Object.assign(Object.assign({}, this.devLogEvent), { devLogLevel: level, devLogCount: totalCount, devLogPayload: this.pendo.compress(events) });
|
|
49023
|
-
}
|
|
49024
|
-
generateJZB() {
|
|
49025
|
-
const payload = [];
|
|
49026
|
-
this.pendo._.each(DEV_LOG_LEVELS, level => {
|
|
49027
|
-
const events = this[`${level}Events`];
|
|
49028
|
-
if (events.length === 0)
|
|
49029
|
-
return;
|
|
49030
|
-
const devLogEventWithPayload = this.createDevLogEventWithPayload({
|
|
49031
|
-
events,
|
|
49032
|
-
level
|
|
49033
|
-
});
|
|
49034
|
-
payload.push(devLogEventWithPayload);
|
|
49035
|
-
});
|
|
49036
|
-
this.devLogEvent = null;
|
|
49037
|
-
return this.pendo.compress(payload);
|
|
49038
|
-
}
|
|
49039
|
-
pack(url) {
|
|
49183
|
+
pack() {
|
|
49040
49184
|
if (this.isEmpty())
|
|
49041
|
-
return
|
|
49042
|
-
const jzb = this.
|
|
49185
|
+
return;
|
|
49186
|
+
const jzb = this.pendo.compress(this.events);
|
|
49043
49187
|
this.clear();
|
|
49044
|
-
return
|
|
49188
|
+
return jzb;
|
|
49045
49189
|
}
|
|
49046
49190
|
}
|
|
49047
49191
|
|
|
@@ -55825,12 +55969,11 @@ function ConsoleCapture() {
|
|
|
55825
55969
|
initialize,
|
|
55826
55970
|
teardown,
|
|
55827
55971
|
addIntercepts,
|
|
55828
|
-
|
|
55972
|
+
createConsoleEvent,
|
|
55829
55973
|
captureStackTrace,
|
|
55830
55974
|
send,
|
|
55831
55975
|
onAppHidden,
|
|
55832
55976
|
onAppUnloaded,
|
|
55833
|
-
onEventCaptured,
|
|
55834
55977
|
onPtmPaused,
|
|
55835
55978
|
onPtmUnpaused,
|
|
55836
55979
|
get buffer() {
|
|
@@ -55864,7 +56007,6 @@ function ConsoleCapture() {
|
|
|
55864
56007
|
pluginAPI.Events.ready.on(addIntercepts);
|
|
55865
56008
|
pluginAPI.Events.appUnloaded.on(onAppUnloaded);
|
|
55866
56009
|
pluginAPI.Events.appHidden.on(onAppHidden);
|
|
55867
|
-
pluginAPI.Events.eventCaptured.on(onEventCaptured);
|
|
55868
56010
|
pluginAPI.Events['ptm:paused'].on(onPtmPaused);
|
|
55869
56011
|
pluginAPI.Events['ptm:unpaused'].on(onPtmUnpaused);
|
|
55870
56012
|
pluginAPI.log.info('Console logs are being captured');
|
|
@@ -55875,36 +56017,19 @@ function ConsoleCapture() {
|
|
|
55875
56017
|
function onAppUnloaded() {
|
|
55876
56018
|
send({ unload: true });
|
|
55877
56019
|
}
|
|
55878
|
-
/**
|
|
55879
|
-
* Handles eventCaptured events to monitor recordingId changes and/or link devLog events with recordingId
|
|
55880
|
-
*
|
|
55881
|
-
* @param {object} event - eventCaptured event
|
|
55882
|
-
*/
|
|
55883
|
-
function onEventCaptured(event) {
|
|
55884
|
-
if (!event || !event.data || !event.data.length || !buffer.devLogEvent)
|
|
55885
|
-
return;
|
|
55886
|
-
const capturedEvent = event.data[0];
|
|
55887
|
-
const { type, recordingId, recordingSessionId } = capturedEvent;
|
|
55888
|
-
if (type === DEV_LOG_TYPE || type === 'identify' || !recordingId || !recordingSessionId)
|
|
55889
|
-
return;
|
|
55890
|
-
const { recordingId: devLogRecordingId } = buffer.devLogEvent;
|
|
55891
|
-
// if recordingId has changed, send current buffer immediately to separate recording sessions
|
|
55892
|
-
if (devLogRecordingId && recordingId !== devLogRecordingId) {
|
|
55893
|
-
send();
|
|
55894
|
-
return;
|
|
55895
|
-
}
|
|
55896
|
-
}
|
|
55897
56020
|
function onPtmPaused() {
|
|
55898
56021
|
isPtmPaused = true;
|
|
55899
56022
|
}
|
|
55900
56023
|
function onPtmUnpaused() {
|
|
55901
56024
|
isPtmPaused = false;
|
|
55902
|
-
if (!buffer.
|
|
55903
|
-
buffer.
|
|
56025
|
+
if (!buffer.isEmpty()) {
|
|
56026
|
+
for (const event of buffer.events) {
|
|
56027
|
+
pluginAPI.Events.eventCaptured.trigger(event);
|
|
56028
|
+
}
|
|
56029
|
+
send();
|
|
55904
56030
|
}
|
|
55905
|
-
pluginAPI.Events.eventCaptured.trigger(buffer.devLogEvent);
|
|
55906
56031
|
}
|
|
55907
|
-
function
|
|
56032
|
+
function createDevLogEnvelope() {
|
|
55908
56033
|
return {
|
|
55909
56034
|
visitorId: globalPendo.get_visitor_id(),
|
|
55910
56035
|
accountId: globalPendo.get_account_id(),
|
|
@@ -55923,14 +56048,14 @@ function ConsoleCapture() {
|
|
|
55923
56048
|
// slice 1 to omit originalFn
|
|
55924
56049
|
const args = _.toArray(arguments).slice(1);
|
|
55925
56050
|
originalFn.apply(console, args);
|
|
55926
|
-
|
|
56051
|
+
createConsoleEvent(args, methodName);
|
|
55927
56052
|
});
|
|
55928
56053
|
console[methodName]._pendoUnwrap = function () {
|
|
55929
56054
|
console[methodName] = originalMethod;
|
|
55930
56055
|
};
|
|
55931
56056
|
});
|
|
55932
56057
|
}
|
|
55933
|
-
function
|
|
56058
|
+
function createConsoleEvent(args, methodName) {
|
|
55934
56059
|
if (!args || args.length === 0)
|
|
55935
56060
|
return;
|
|
55936
56061
|
// stringify args
|
|
@@ -55958,22 +56083,16 @@ function ConsoleCapture() {
|
|
|
55958
56083
|
buffer.lastEvent.devLogCount++;
|
|
55959
56084
|
return;
|
|
55960
56085
|
}
|
|
55961
|
-
const
|
|
55962
|
-
|
|
55963
|
-
|
|
55964
|
-
devLogTrace: stackTrace,
|
|
55965
|
-
devLogTimestamp: pluginAPI.util.getNow(),
|
|
55966
|
-
devLogCount: 1
|
|
55967
|
-
};
|
|
55968
|
-
const wasAccepted = buffer.push(devLog);
|
|
56086
|
+
const devLogEnvelope = createDevLogEnvelope();
|
|
56087
|
+
const consoleEvent = Object.assign(Object.assign({}, devLogEnvelope), { devLogLevel: methodName === 'log' ? 'info' : methodName, devLogMessage: scrubPII(message), devLogTrace: stackTrace, devLogCount: 1 });
|
|
56088
|
+
const wasAccepted = buffer.push(consoleEvent);
|
|
55969
56089
|
if (wasAccepted) {
|
|
55970
|
-
if (
|
|
55971
|
-
|
|
55972
|
-
pluginAPI.Events.eventCaptured.trigger(buffer.devLogEvent);
|
|
56090
|
+
if (!isPtmPaused) {
|
|
56091
|
+
pluginAPI.Events.eventCaptured.trigger(consoleEvent);
|
|
55973
56092
|
}
|
|
55974
56093
|
updateLastLog(logKey);
|
|
55975
56094
|
}
|
|
55976
|
-
return
|
|
56095
|
+
return consoleEvent;
|
|
55977
56096
|
}
|
|
55978
56097
|
function captureStackTrace(maxStackFrames) {
|
|
55979
56098
|
try {
|
|
@@ -55993,19 +56112,23 @@ function ConsoleCapture() {
|
|
|
55993
56112
|
function send({ unload = false, hidden = false } = {}) {
|
|
55994
56113
|
if (!buffer || buffer.isEmpty())
|
|
55995
56114
|
return;
|
|
56115
|
+
if (!globalPendo.isSendingEvents()) {
|
|
56116
|
+
buffer.clear();
|
|
56117
|
+
return;
|
|
56118
|
+
}
|
|
55996
56119
|
const queryParams = {
|
|
55997
56120
|
v: globalPendo.VERSION,
|
|
55998
56121
|
ct: pluginAPI.util.getNow()
|
|
55999
56122
|
};
|
|
56000
56123
|
const url = pluginAPI.transmit.buildBaseDataUrl('devlog', globalPendo.apiKey, queryParams);
|
|
56001
|
-
const
|
|
56002
|
-
if (!
|
|
56124
|
+
const jzb = buffer.pack();
|
|
56125
|
+
if (!jzb)
|
|
56003
56126
|
return;
|
|
56004
56127
|
if (unload || hidden) {
|
|
56005
|
-
sendQueue.drain(
|
|
56128
|
+
sendQueue.drain([{ url, jzb }], unload);
|
|
56006
56129
|
}
|
|
56007
56130
|
else {
|
|
56008
|
-
sendQueue.push(
|
|
56131
|
+
sendQueue.push({ url, jzb });
|
|
56009
56132
|
}
|
|
56010
56133
|
}
|
|
56011
56134
|
function teardown() {
|
|
@@ -56021,7 +56144,6 @@ function ConsoleCapture() {
|
|
|
56021
56144
|
}
|
|
56022
56145
|
pluginAPI.Events.appHidden.off(onAppHidden);
|
|
56023
56146
|
pluginAPI.Events.appUnloaded.off(onAppUnloaded);
|
|
56024
|
-
pluginAPI.Events.eventCaptured.off(onEventCaptured);
|
|
56025
56147
|
pluginAPI.Events['ptm:paused'].off(onPtmPaused);
|
|
56026
56148
|
pluginAPI.Events['ptm:unpaused'].off(onPtmUnpaused);
|
|
56027
56149
|
_.each(CONSOLE_METHODS, function (methodName) {
|