@pendo/agent 2.291.4 → 2.292.1
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.1_';
|
|
3915
|
+
var PACKAGE_VERSION = '2.292.1';
|
|
3909
3916
|
var LOADER = 'xhr';
|
|
3910
3917
|
/* eslint-enable agent-eslint-rules/no-gulp-env-references */
|
|
3911
3918
|
/**
|
|
@@ -12184,6 +12191,92 @@ class LocalStorageEventBuffer {
|
|
|
12184
12191
|
}
|
|
12185
12192
|
var localStorageEventBuffer = new LocalStorageEventBuffer();
|
|
12186
12193
|
|
|
12194
|
+
class PerformanceMonitor {
|
|
12195
|
+
constructor() {
|
|
12196
|
+
this._isPerformanceApiAvailable = this._checkPerformanceApi();
|
|
12197
|
+
this._measuringPerformance = false;
|
|
12198
|
+
this._marks = {};
|
|
12199
|
+
this._measures = {};
|
|
12200
|
+
}
|
|
12201
|
+
initialize() {
|
|
12202
|
+
this._measuringPerformance = true;
|
|
12203
|
+
this._markPerformance('initialize');
|
|
12204
|
+
// temporary clear interval while working on send implementation
|
|
12205
|
+
this.interval = setInterval(() => {
|
|
12206
|
+
this._clearMarksAndMeasures();
|
|
12207
|
+
}, 1000 * 60 * 10);
|
|
12208
|
+
return () => {
|
|
12209
|
+
this.teardown();
|
|
12210
|
+
};
|
|
12211
|
+
}
|
|
12212
|
+
teardown() {
|
|
12213
|
+
this._measuringPerformance = false;
|
|
12214
|
+
this._markPerformance('teardown');
|
|
12215
|
+
this._clearMarksAndMeasures();
|
|
12216
|
+
clearInterval(this.interval);
|
|
12217
|
+
}
|
|
12218
|
+
startTimer(name) {
|
|
12219
|
+
this._markPerformance(`${name}-start`);
|
|
12220
|
+
}
|
|
12221
|
+
stopTimer(name) {
|
|
12222
|
+
this._markPerformance(`${name}-stop`);
|
|
12223
|
+
this._measurePerformance(name);
|
|
12224
|
+
}
|
|
12225
|
+
track(name) {
|
|
12226
|
+
this._markPerformance(name);
|
|
12227
|
+
}
|
|
12228
|
+
send() {
|
|
12229
|
+
performance.getEntries();
|
|
12230
|
+
// TODO: implement filter/send process
|
|
12231
|
+
this._clearMarksAndMeasures();
|
|
12232
|
+
}
|
|
12233
|
+
_checkPerformanceApi() {
|
|
12234
|
+
return detectNativeBrowserAPI('performance.mark') &&
|
|
12235
|
+
detectNativeBrowserAPI('performance.measure') &&
|
|
12236
|
+
detectNativeBrowserAPI('performance.getEntries') &&
|
|
12237
|
+
detectNativeBrowserAPI('performance.clearMarks') &&
|
|
12238
|
+
detectNativeBrowserAPI('performance.clearMeasures');
|
|
12239
|
+
}
|
|
12240
|
+
_shouldMeasurePerformance() {
|
|
12241
|
+
return this._isPerformanceApiAvailable && this._measuringPerformance;
|
|
12242
|
+
}
|
|
12243
|
+
_markPerformance(name) {
|
|
12244
|
+
if (!this._shouldMeasurePerformance())
|
|
12245
|
+
return;
|
|
12246
|
+
name = `pendo-${name}`;
|
|
12247
|
+
performance.mark(name);
|
|
12248
|
+
this._count(this._marks, name);
|
|
12249
|
+
}
|
|
12250
|
+
_measurePerformance(name) {
|
|
12251
|
+
if (!this._shouldMeasurePerformance())
|
|
12252
|
+
return;
|
|
12253
|
+
name = `pendo-${name}`;
|
|
12254
|
+
const startMark = `${name}-start`;
|
|
12255
|
+
const stopMark = `${name}-stop`;
|
|
12256
|
+
performance.measure(name, startMark, stopMark);
|
|
12257
|
+
this._count(this._measures, name);
|
|
12258
|
+
}
|
|
12259
|
+
_count(registry, name) {
|
|
12260
|
+
if (!registry[name]) {
|
|
12261
|
+
registry[name] = 1;
|
|
12262
|
+
}
|
|
12263
|
+
else {
|
|
12264
|
+
registry[name]++;
|
|
12265
|
+
}
|
|
12266
|
+
}
|
|
12267
|
+
_clearMarksAndMeasures() {
|
|
12268
|
+
_.each(this._marks, (count, name) => {
|
|
12269
|
+
performance.clearMarks(name);
|
|
12270
|
+
});
|
|
12271
|
+
_.each(this._measures, (count, name) => {
|
|
12272
|
+
performance.clearMeasures(name);
|
|
12273
|
+
});
|
|
12274
|
+
this._marks = {};
|
|
12275
|
+
this._measures = {};
|
|
12276
|
+
}
|
|
12277
|
+
}
|
|
12278
|
+
var PerformanceMonitor$1 = new PerformanceMonitor();
|
|
12279
|
+
|
|
12187
12280
|
var defaultTrackName = '_PENDO_UNNAMED_';
|
|
12188
12281
|
var SILO_AVG_COMPRESSION_RATIO = 5;
|
|
12189
12282
|
/**
|
|
@@ -12245,21 +12338,7 @@ function collectEvent(type, props, url, name, eventProperties, context) {
|
|
|
12245
12338
|
agenticEventQueue.push(event);
|
|
12246
12339
|
return;
|
|
12247
12340
|
}
|
|
12248
|
-
eventQueue.push(
|
|
12249
|
-
}
|
|
12250
|
-
function attachMonitoringData(store, event) {
|
|
12251
|
-
try {
|
|
12252
|
-
if (!store.getters['monitoring/shouldFlush']())
|
|
12253
|
-
return event;
|
|
12254
|
-
var payload = store.getters['monitoring/payload']();
|
|
12255
|
-
store.dispatch('monitoring/flush');
|
|
12256
|
-
if (!_.isEmpty(payload)) {
|
|
12257
|
-
event.ops = payload;
|
|
12258
|
-
}
|
|
12259
|
-
}
|
|
12260
|
-
catch (e) {
|
|
12261
|
-
}
|
|
12262
|
-
return event;
|
|
12341
|
+
eventQueue.push(event);
|
|
12263
12342
|
}
|
|
12264
12343
|
// @const {Event.type[]}
|
|
12265
12344
|
var WHITELIST_FREE_NPS = ['load', 'meta', 'identify'];
|
|
@@ -12698,7 +12777,7 @@ function createSendQueue(options, send, guaranteedSend) {
|
|
|
12698
12777
|
}
|
|
12699
12778
|
});
|
|
12700
12779
|
queue.onTimeout = function () {
|
|
12701
|
-
|
|
12780
|
+
PerformanceMonitor$1.track(`${options.beacon}-gif-failure`);
|
|
12702
12781
|
};
|
|
12703
12782
|
queue.retryPending = true;
|
|
12704
12783
|
return queue;
|
|
@@ -12990,7 +13069,7 @@ var handleEmbeddedData = function (src) {
|
|
|
12990
13069
|
return src + '';
|
|
12991
13070
|
};
|
|
12992
13071
|
function getAttributeValue(element, attrName) {
|
|
12993
|
-
return
|
|
13072
|
+
return store.getters['nodeAttr/getAttribute']()(element, attrName);
|
|
12994
13073
|
}
|
|
12995
13074
|
var extractAttribute = function (element, attrName, type) {
|
|
12996
13075
|
if (!element || !element.nodeName)
|
|
@@ -21042,10 +21121,6 @@ class UpdateRunner {
|
|
|
21042
21121
|
}
|
|
21043
21122
|
}
|
|
21044
21123
|
complete(time) {
|
|
21045
|
-
store.commit('monitoring/setTimer', {
|
|
21046
|
-
name: 'guideUpdateTimeMS',
|
|
21047
|
-
time: this.updateTotalTime
|
|
21048
|
-
});
|
|
21049
21124
|
store.commit('guideUpdate/completeUpdate', time);
|
|
21050
21125
|
this.cancel();
|
|
21051
21126
|
}
|
|
@@ -26533,6 +26608,11 @@ var EventRouter = function () {
|
|
|
26533
26608
|
var config = configParam.value;
|
|
26534
26609
|
var cases = casesParam.value;
|
|
26535
26610
|
var conditionResult = evaluateCondition(conditionType, config);
|
|
26611
|
+
Events.trigger('appUsage', {
|
|
26612
|
+
type: 'conditionalSplitResult',
|
|
26613
|
+
elementId: evt.srcElement.id,
|
|
26614
|
+
conditionResult
|
|
26615
|
+
});
|
|
26536
26616
|
var matchingCase = _.find(cases, function (caseItem) {
|
|
26537
26617
|
return caseItem.value === conditionResult;
|
|
26538
26618
|
});
|
|
@@ -26600,16 +26680,27 @@ var GuideActivity = (function () {
|
|
|
26600
26680
|
var isObject = _.isObject;
|
|
26601
26681
|
var findWhere = _.findWhere;
|
|
26602
26682
|
const _guideResolvers = [];
|
|
26683
|
+
var conditionalSplitEventQueue = [];
|
|
26603
26684
|
return {
|
|
26604
26685
|
type: GA_TYPE,
|
|
26605
26686
|
handler(evtData) {
|
|
26606
26687
|
var appData = evtData.data[0];
|
|
26688
|
+
if (appData && appData.type === 'conditionalSplitResult') {
|
|
26689
|
+
finalizeConditionalSplitEvent(appData);
|
|
26690
|
+
return;
|
|
26691
|
+
}
|
|
26607
26692
|
var browserEvt = evtData.data[1];
|
|
26608
26693
|
if (!shouldHandleEvent(appData, browserEvt))
|
|
26609
26694
|
return;
|
|
26610
26695
|
var activityEvent = transformToGuideActivity(appData);
|
|
26611
26696
|
if (activityEvent) {
|
|
26612
|
-
|
|
26697
|
+
const firstAction = _.get(activityEvent, ['props', 'ui_element_actions', 0, 'action']);
|
|
26698
|
+
if (firstAction === 'conditionalSplit') {
|
|
26699
|
+
conditionalSplitEventQueue.push(activityEvent);
|
|
26700
|
+
}
|
|
26701
|
+
else {
|
|
26702
|
+
stageGuideEvent(activityEvent);
|
|
26703
|
+
}
|
|
26613
26704
|
}
|
|
26614
26705
|
},
|
|
26615
26706
|
registerGuideResolver(callBack) {
|
|
@@ -26622,6 +26713,22 @@ var GuideActivity = (function () {
|
|
|
26622
26713
|
}
|
|
26623
26714
|
}
|
|
26624
26715
|
};
|
|
26716
|
+
function finalizeConditionalSplitEvent(evtData) {
|
|
26717
|
+
const { conditionResult, elementId } = evtData;
|
|
26718
|
+
const matchingEventIndex = _.findIndex(conditionalSplitEventQueue, (event) => {
|
|
26719
|
+
return event.props.ui_element_id === elementId;
|
|
26720
|
+
});
|
|
26721
|
+
if (matchingEventIndex === -1)
|
|
26722
|
+
return;
|
|
26723
|
+
const matchingEvent = conditionalSplitEventQueue.splice(matchingEventIndex, 1)[0];
|
|
26724
|
+
const conditionalSplitAction = matchingEvent.props.ui_element_actions[0];
|
|
26725
|
+
conditionalSplitAction.condition_result = conditionResult;
|
|
26726
|
+
const cases = conditionalSplitAction.cases;
|
|
26727
|
+
const resultCase = cases[conditionResult];
|
|
26728
|
+
matchingEvent.props.ui_element_actions = matchingEvent.props.ui_element_actions.concat(resultCase);
|
|
26729
|
+
delete conditionalSplitAction.cases;
|
|
26730
|
+
stageGuideEvent(matchingEvent);
|
|
26731
|
+
}
|
|
26625
26732
|
function isClickEvent(browserEvt) {
|
|
26626
26733
|
return browserEvt && browserEvt.type === 'click';
|
|
26627
26734
|
}
|
|
@@ -26738,58 +26845,7 @@ var GuideActivity = (function () {
|
|
|
26738
26845
|
];
|
|
26739
26846
|
}
|
|
26740
26847
|
if (element.actions !== undefined) {
|
|
26741
|
-
return _.map(element.actions,
|
|
26742
|
-
switch (action.action) {
|
|
26743
|
-
case 'automation':
|
|
26744
|
-
var automationIds = findWhere(action.parameters, { name: 'automationIds' });
|
|
26745
|
-
return {
|
|
26746
|
-
action: action.action,
|
|
26747
|
-
automationIds
|
|
26748
|
-
};
|
|
26749
|
-
case 'openLink':
|
|
26750
|
-
var url = findWhere(action.parameters, { name: 'url' });
|
|
26751
|
-
var target = findWhere(action.parameters, { name: 'target' });
|
|
26752
|
-
return {
|
|
26753
|
-
action: action.action,
|
|
26754
|
-
url: sanitizeUrl(url.value),
|
|
26755
|
-
target: target.value
|
|
26756
|
-
};
|
|
26757
|
-
case 'submitPollAndGoToStep':
|
|
26758
|
-
case 'goToStep':
|
|
26759
|
-
var guideStepId = findWhere(action.parameters, { name: 'goToStepId' });
|
|
26760
|
-
return {
|
|
26761
|
-
action: action.action,
|
|
26762
|
-
guideStepId: guideStepId.value
|
|
26763
|
-
};
|
|
26764
|
-
case 'guideSnoozed':
|
|
26765
|
-
var duration = findWhere(action.parameters, { name: 'snooze_duration' });
|
|
26766
|
-
var timeUnit = findWhere(action.parameters, { name: 'time_unit' });
|
|
26767
|
-
return {
|
|
26768
|
-
action: action.action,
|
|
26769
|
-
duration: duration.value,
|
|
26770
|
-
timeUnit: timeUnit.value
|
|
26771
|
-
};
|
|
26772
|
-
case 'showGuide':
|
|
26773
|
-
case 'launchGuide':
|
|
26774
|
-
var guideId = action.parameters[0];
|
|
26775
|
-
var stepId = action.parameters[1] || {};
|
|
26776
|
-
return {
|
|
26777
|
-
action: action.action,
|
|
26778
|
-
guideId: guideId.value,
|
|
26779
|
-
stepId: stepId.value
|
|
26780
|
-
};
|
|
26781
|
-
case 'advanceGuide':
|
|
26782
|
-
case 'previousStep':
|
|
26783
|
-
case 'submitPoll':
|
|
26784
|
-
case 'dismissGuide':
|
|
26785
|
-
case 'confirmation':
|
|
26786
|
-
return {
|
|
26787
|
-
action: action.action
|
|
26788
|
-
};
|
|
26789
|
-
default:
|
|
26790
|
-
return {};
|
|
26791
|
-
}
|
|
26792
|
-
});
|
|
26848
|
+
return _.map(element.actions, processAction);
|
|
26793
26849
|
}
|
|
26794
26850
|
if (uiElement.templateName === 'pendo_task_list_item') {
|
|
26795
26851
|
if (_.isArray(element.templateChildren) && element.templateChildren[uiElement.templateChildIndex]) {
|
|
@@ -26801,6 +26857,79 @@ var GuideActivity = (function () {
|
|
|
26801
26857
|
}
|
|
26802
26858
|
return [];
|
|
26803
26859
|
}
|
|
26860
|
+
function processAction(action) {
|
|
26861
|
+
switch (action.action) {
|
|
26862
|
+
case 'automation':
|
|
26863
|
+
var automationIds = findWhere(action.parameters, { name: 'automationIds' });
|
|
26864
|
+
return {
|
|
26865
|
+
action: action.action,
|
|
26866
|
+
automationIds
|
|
26867
|
+
};
|
|
26868
|
+
case 'openLink':
|
|
26869
|
+
var url = findWhere(action.parameters, { name: 'url' });
|
|
26870
|
+
var target = findWhere(action.parameters, { name: 'target' });
|
|
26871
|
+
return {
|
|
26872
|
+
action: action.action,
|
|
26873
|
+
url: sanitizeUrl(url.value),
|
|
26874
|
+
target: target.value
|
|
26875
|
+
};
|
|
26876
|
+
case 'submitPollAndGoToStep':
|
|
26877
|
+
case 'goToStep':
|
|
26878
|
+
var guideStepId = findWhere(action.parameters, { name: 'goToStepId' });
|
|
26879
|
+
return {
|
|
26880
|
+
action: action.action,
|
|
26881
|
+
guideStepId: guideStepId.value
|
|
26882
|
+
};
|
|
26883
|
+
case 'guideSnoozed':
|
|
26884
|
+
var duration = findWhere(action.parameters, { name: 'snooze_duration' });
|
|
26885
|
+
var timeUnit = findWhere(action.parameters, { name: 'time_unit' });
|
|
26886
|
+
return {
|
|
26887
|
+
action: action.action,
|
|
26888
|
+
duration: duration.value,
|
|
26889
|
+
timeUnit: timeUnit.value
|
|
26890
|
+
};
|
|
26891
|
+
case 'showGuide':
|
|
26892
|
+
case 'launchGuide':
|
|
26893
|
+
var guideId = action.parameters[0];
|
|
26894
|
+
var stepId = action.parameters[1] || {};
|
|
26895
|
+
return {
|
|
26896
|
+
action: action.action,
|
|
26897
|
+
guideId: guideId.value,
|
|
26898
|
+
stepId: stepId.value
|
|
26899
|
+
};
|
|
26900
|
+
case 'conditionalSplit':
|
|
26901
|
+
var name = findWhere(action.parameters, { name: 'name' });
|
|
26902
|
+
var conditionType = findWhere(action.parameters, { name: 'conditionType' });
|
|
26903
|
+
var config = findWhere(action.parameters, { name: 'config' });
|
|
26904
|
+
var cases = findWhere(action.parameters, { name: 'cases' });
|
|
26905
|
+
var processedCases = _.reduce(cases.value, function (acc, c) {
|
|
26906
|
+
acc[c.value] = _.map(c.actions, function (a) {
|
|
26907
|
+
var processedAction = processAction(a);
|
|
26908
|
+
processedAction.source = a.source;
|
|
26909
|
+
return processedAction;
|
|
26910
|
+
});
|
|
26911
|
+
return acc;
|
|
26912
|
+
}, {});
|
|
26913
|
+
return {
|
|
26914
|
+
action: action.action,
|
|
26915
|
+
name: name.value,
|
|
26916
|
+
condition_type: conditionType.value,
|
|
26917
|
+
element_selector: config.value.elementSelector,
|
|
26918
|
+
feature_id: config.value.featureId,
|
|
26919
|
+
cases: processedCases // will be removed in finalizeConditionalSplitEvent
|
|
26920
|
+
};
|
|
26921
|
+
case 'advanceGuide':
|
|
26922
|
+
case 'previousStep':
|
|
26923
|
+
case 'submitPoll':
|
|
26924
|
+
case 'dismissGuide':
|
|
26925
|
+
case 'confirmation':
|
|
26926
|
+
return {
|
|
26927
|
+
action: action.action
|
|
26928
|
+
};
|
|
26929
|
+
default:
|
|
26930
|
+
return {};
|
|
26931
|
+
}
|
|
26932
|
+
}
|
|
26804
26933
|
function transformToGuideActivity(appData) {
|
|
26805
26934
|
var activeGuideObj = getGuideForEvent(appData);
|
|
26806
26935
|
if (!activeGuideObj)
|
|
@@ -26999,14 +27128,14 @@ var didAccountIdentityChange = function (props) {
|
|
|
26999
27128
|
function initIdentityEvents() {
|
|
27000
27129
|
if (initialized)
|
|
27001
27130
|
return;
|
|
27002
|
-
|
|
27131
|
+
const collectIdentifyEvent = function (event) {
|
|
27003
27132
|
var props = event.data[0];
|
|
27004
27133
|
if (wasAnonymousVisitorIdentified(props) || didAccountIdentityChange(props)) {
|
|
27005
27134
|
collectEvent('identify', props);
|
|
27006
27135
|
flushLater(); // unconditionally on next tick
|
|
27007
27136
|
}
|
|
27008
|
-
}
|
|
27009
|
-
|
|
27137
|
+
};
|
|
27138
|
+
const collectMetadataEvent = function (event) {
|
|
27010
27139
|
// Check to see if this Application is sending metadata to the backend using
|
|
27011
27140
|
// different mechanism (like Segment webhooks)
|
|
27012
27141
|
var blockAgentMetadata = isMetadataBlocked();
|
|
@@ -27017,9 +27146,17 @@ function initIdentityEvents() {
|
|
|
27017
27146
|
flushLater(); // unconditionally on next tick
|
|
27018
27147
|
}
|
|
27019
27148
|
}
|
|
27020
|
-
}
|
|
27149
|
+
};
|
|
27150
|
+
Events.identify.on(collectIdentifyEvent);
|
|
27151
|
+
Events.metadata.on(collectMetadataEvent);
|
|
27021
27152
|
Events.identify.on(handleIdentifyEvent);
|
|
27022
27153
|
initialized = true;
|
|
27154
|
+
return function () {
|
|
27155
|
+
Events.identify.off(collectIdentifyEvent);
|
|
27156
|
+
Events.metadata.off(collectMetadataEvent);
|
|
27157
|
+
Events.identify.off(handleIdentifyEvent);
|
|
27158
|
+
initialized = false;
|
|
27159
|
+
};
|
|
27023
27160
|
}
|
|
27024
27161
|
|
|
27025
27162
|
/*
|
|
@@ -27230,7 +27367,7 @@ class ShadowDomManager extends EventTarget {
|
|
|
27230
27367
|
}
|
|
27231
27368
|
initialize() {
|
|
27232
27369
|
this.unpatchAttachShadow = this.patchAttachShadow(Element);
|
|
27233
|
-
this.findShadowRoots(document);
|
|
27370
|
+
this.findShadowRoots(document, 5000, (shadowRoot) => this.triggerAttachShadow(shadowRoot));
|
|
27234
27371
|
}
|
|
27235
27372
|
triggerAttachShadow(shadowRoot) {
|
|
27236
27373
|
this.cache.add(shadowRoot);
|
|
@@ -27239,7 +27376,7 @@ class ShadowDomManager extends EventTarget {
|
|
|
27239
27376
|
shadowRoot
|
|
27240
27377
|
});
|
|
27241
27378
|
}
|
|
27242
|
-
findShadowRoots(document, maxPerSearch = 5000) {
|
|
27379
|
+
findShadowRoots(document, maxPerSearch = 5000, onShadowRootFound) {
|
|
27243
27380
|
if (!_.isFunction(document.createNodeIterator))
|
|
27244
27381
|
return;
|
|
27245
27382
|
let nodesChecked = 0;
|
|
@@ -27255,7 +27392,7 @@ class ShadowDomManager extends EventTarget {
|
|
|
27255
27392
|
while ((currentNode = iterator.nextNode())) {
|
|
27256
27393
|
nodesChecked++;
|
|
27257
27394
|
if (currentNode && currentNode.shadowRoot) {
|
|
27258
|
-
|
|
27395
|
+
onShadowRootFound(currentNode.shadowRoot);
|
|
27259
27396
|
queue.push(currentNode.shadowRoot);
|
|
27260
27397
|
this.foundShadowRoots = true;
|
|
27261
27398
|
}
|
|
@@ -27376,7 +27513,8 @@ function registerEventHandlers({ events = [] }) {
|
|
|
27376
27513
|
let initializeCounter = 0;
|
|
27377
27514
|
const initializeImmediately = 'initializeImmediately';
|
|
27378
27515
|
/**
|
|
27379
|
-
* Initializes the Pendo
|
|
27516
|
+
* 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.
|
|
27517
|
+
* Once the agent has been initialized, any updates to identity or metadata should be done using `identify` or `updateOptions`.
|
|
27380
27518
|
*
|
|
27381
27519
|
* @access public
|
|
27382
27520
|
* @function
|
|
@@ -27522,13 +27660,14 @@ const initialize = makeSafe(function (options) {
|
|
|
27522
27660
|
teardownFns.push(forwardInternalEvents(Events));
|
|
27523
27661
|
registerEventHandlers(options);
|
|
27524
27662
|
teardownFns.push(initGuides(observer)); // this is safe. loadGuides actually does the loading.
|
|
27525
|
-
initIdentityEvents(); // setup identify and meta event listeners
|
|
27663
|
+
teardownFns.push(initIdentityEvents()); // setup identify and meta event listeners
|
|
27526
27664
|
teardownFns.push(wirePage());
|
|
27527
27665
|
teardownFns.push(initializePlugins());
|
|
27528
27666
|
teardownFns.push(launchDesignerOrPreview(options));
|
|
27529
27667
|
Events.appUsage.on(GuideActivity.handler);
|
|
27530
27668
|
Events.appUsage.on(ResourceCenterActivity.handler);
|
|
27531
27669
|
teardownFns.push(flushEvery(SEND_INTERVAL));
|
|
27670
|
+
teardownFns.push(PerformanceMonitor$1.initialize());
|
|
27532
27671
|
}
|
|
27533
27672
|
Events.appHidden.on(() => {
|
|
27534
27673
|
flushNow(true, { hidden: true });
|
|
@@ -29021,11 +29160,14 @@ var attrActionEnum = {
|
|
|
29021
29160
|
href: ['Replace', 'ForceSecure'],
|
|
29022
29161
|
protocol: ['ForceSecure']
|
|
29023
29162
|
};
|
|
29024
|
-
|
|
29163
|
+
const TARGETS = ['location', 'attribute', 'both'];
|
|
29164
|
+
const DEFAULT_TARGET = 'location';
|
|
29165
|
+
function UrlTransform(attr, action, data, target) {
|
|
29025
29166
|
if (_.isObject(attr)) {
|
|
29026
29167
|
action = attr.action;
|
|
29027
29168
|
data = attr.data;
|
|
29028
29169
|
attr = attr.attr;
|
|
29170
|
+
target = attr.target;
|
|
29029
29171
|
}
|
|
29030
29172
|
if (!attrActionEnum[attr]) {
|
|
29031
29173
|
var validAttrs = _.keys(attrActionEnum).join(', ');
|
|
@@ -29035,11 +29177,16 @@ function UrlAttrTransform(attr, action, data) {
|
|
|
29035
29177
|
var validActions = attrActionEnum[attr].join(', ');
|
|
29036
29178
|
throw new Error('Invalid transform action: "' + action + '" for attribute "' + attr + '". Valid actions for "' + attr + '" are: ' + validActions + '. Example: {attr: "' + attr + '", action: "' + attrActionEnum[attr][0] + '", data: ...}');
|
|
29037
29179
|
}
|
|
29180
|
+
// validate 'target'
|
|
29181
|
+
if (TARGETS.indexOf(target) < 0) {
|
|
29182
|
+
target = DEFAULT_TARGET;
|
|
29183
|
+
}
|
|
29038
29184
|
this.attr = attr;
|
|
29039
29185
|
this.action = action;
|
|
29040
29186
|
this.data = data;
|
|
29187
|
+
this.target = target || DEFAULT_TARGET;
|
|
29041
29188
|
}
|
|
29042
|
-
|
|
29189
|
+
UrlTransform.prototype.applyTo = function (url) {
|
|
29043
29190
|
var actionImpls = {
|
|
29044
29191
|
AllowOnlyKeys(url, attr, data) {
|
|
29045
29192
|
if (_.isFunction(data)) {
|
|
@@ -29112,26 +29259,26 @@ UrlAttrTransform.prototype.applyToURL = function (url) {
|
|
|
29112
29259
|
};
|
|
29113
29260
|
return actionImpls[this.action](url, this.attr, this.data);
|
|
29114
29261
|
};
|
|
29115
|
-
|
|
29262
|
+
UrlTransform.prototype.toString = function () {
|
|
29116
29263
|
return this.attr + ' - ' + this.action + ' - ' + JSON.stringify(this.data);
|
|
29117
29264
|
};
|
|
29118
29265
|
// Static method, not on the instance
|
|
29119
|
-
|
|
29120
|
-
if (obj instanceof
|
|
29266
|
+
UrlTransform.fromJSON = function (obj) {
|
|
29267
|
+
if (obj instanceof UrlTransform) {
|
|
29121
29268
|
return obj;
|
|
29122
29269
|
}
|
|
29123
29270
|
// Validate input is an object
|
|
29124
29271
|
if (!_.isObject(obj)) {
|
|
29125
|
-
throw new Error('
|
|
29272
|
+
throw new Error('UrlTransform.fromJSON expects an object. Received: ' + typeof obj + '. Example: {attr: "search", action: "AddTo", data: {key: "value"}}');
|
|
29126
29273
|
}
|
|
29127
29274
|
// Validate required properties
|
|
29128
29275
|
if (!obj.attr) {
|
|
29129
29276
|
var allValidAttrs = _.keys(attrActionEnum).join(', ');
|
|
29130
|
-
throw new Error('
|
|
29277
|
+
throw new Error('UrlTransform is missing required "attr" property. Valid attributes are: ' + allValidAttrs + '. Example: {attr: "search", action: "AddTo", data: {key: "value"}}');
|
|
29131
29278
|
}
|
|
29132
29279
|
if (!obj.action) {
|
|
29133
29280
|
var attrValidActions = attrActionEnum[obj.attr] ? attrActionEnum[obj.attr].join(', ') : 'AllowOnlyKeys, ExcludeKeys, AddTo, Replace, Clear';
|
|
29134
|
-
throw new Error('
|
|
29281
|
+
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"}}');
|
|
29135
29282
|
}
|
|
29136
29283
|
// Validate attribute and action combination
|
|
29137
29284
|
if (!attrActionEnum[obj.attr]) {
|
|
@@ -29170,7 +29317,7 @@ UrlAttrTransform.fromJSON = function (obj) {
|
|
|
29170
29317
|
}
|
|
29171
29318
|
}
|
|
29172
29319
|
try {
|
|
29173
|
-
return new
|
|
29320
|
+
return new UrlTransform(obj.attr, obj.action, obj.data, obj.target);
|
|
29174
29321
|
}
|
|
29175
29322
|
catch (error) {
|
|
29176
29323
|
// If it's already a detailed error from our validation, re-throw it
|
|
@@ -29179,7 +29326,7 @@ UrlAttrTransform.fromJSON = function (obj) {
|
|
|
29179
29326
|
throw error;
|
|
29180
29327
|
}
|
|
29181
29328
|
// Otherwise, wrap the original error with context
|
|
29182
|
-
throw new Error('Failed to create
|
|
29329
|
+
throw new Error('Failed to create UrlTransform: ' + error.message + '. Transform object: ' + JSON.stringify(obj));
|
|
29183
29330
|
}
|
|
29184
29331
|
};
|
|
29185
29332
|
|
|
@@ -29189,13 +29336,13 @@ function isURL(u) {
|
|
|
29189
29336
|
var LocationModule = (function (global) {
|
|
29190
29337
|
var createElectronTranforms = function (appname, resourcesPath, directory, userHome) {
|
|
29191
29338
|
return [
|
|
29192
|
-
new
|
|
29339
|
+
new UrlTransform('pathname', 'Replace', function (path) {
|
|
29193
29340
|
var newPath = path.replace(resourcesPath, appname);
|
|
29194
29341
|
newPath = newPath.replace(directory, appname);
|
|
29195
29342
|
newPath = newPath.replace(userHome, '');
|
|
29196
29343
|
return newPath;
|
|
29197
29344
|
}),
|
|
29198
|
-
new
|
|
29345
|
+
new UrlTransform('href', 'ForceSecure')
|
|
29199
29346
|
];
|
|
29200
29347
|
};
|
|
29201
29348
|
var DEFAULT_SRC_FN = function () {
|
|
@@ -29234,17 +29381,23 @@ var LocationModule = (function (global) {
|
|
|
29234
29381
|
},
|
|
29235
29382
|
addTransforms(context, transforms) {
|
|
29236
29383
|
_.each(transforms, function (f) {
|
|
29237
|
-
|
|
29384
|
+
const t = UrlTransform.fromJSON(f);
|
|
29385
|
+
if (t.target === 'location' || t.target === 'both') {
|
|
29386
|
+
context.commit('addTransform', t);
|
|
29387
|
+
}
|
|
29388
|
+
if (t.target === 'attribute' || t.target === 'both') {
|
|
29389
|
+
store.dispatch('nodeAttr/addAttrTransform', t);
|
|
29390
|
+
}
|
|
29238
29391
|
});
|
|
29239
29392
|
},
|
|
29240
29393
|
addInternalTransforms(context, transforms) {
|
|
29241
29394
|
_.each(transforms, function (f) {
|
|
29242
|
-
context.commit('addInternalTransform',
|
|
29395
|
+
context.commit('addInternalTransform', UrlTransform.fromJSON(f));
|
|
29243
29396
|
});
|
|
29244
29397
|
},
|
|
29245
29398
|
removeInternalTransforms(context, transforms) {
|
|
29246
29399
|
_.each(transforms, function (f) {
|
|
29247
|
-
context.commit('removeInternalTransform',
|
|
29400
|
+
context.commit('removeInternalTransform', UrlTransform.fromJSON(f));
|
|
29248
29401
|
});
|
|
29249
29402
|
},
|
|
29250
29403
|
startPolling(context) {
|
|
@@ -29272,6 +29425,7 @@ var LocationModule = (function (global) {
|
|
|
29272
29425
|
},
|
|
29273
29426
|
clearTransforms(state) {
|
|
29274
29427
|
state.transforms = [];
|
|
29428
|
+
store.commit('nodeAttr/clearURLTransforms');
|
|
29275
29429
|
},
|
|
29276
29430
|
clearInternalTransforms(state) {
|
|
29277
29431
|
state.internalTransforms = [];
|
|
@@ -29327,7 +29481,7 @@ var LocationModule = (function (global) {
|
|
|
29327
29481
|
};
|
|
29328
29482
|
var transformUrl = function (transforms, url) {
|
|
29329
29483
|
return _.reduce(transforms, function (tUrl, f) {
|
|
29330
|
-
return f.
|
|
29484
|
+
return f.applyTo(tUrl);
|
|
29331
29485
|
}, url);
|
|
29332
29486
|
};
|
|
29333
29487
|
var urlGetter = function (state) {
|
|
@@ -32544,10 +32698,12 @@ var GuideUpdateModule = (function () {
|
|
|
32544
32698
|
state.scheduledUpdate = scheduledUpdate;
|
|
32545
32699
|
},
|
|
32546
32700
|
startUpdate(state, time) {
|
|
32701
|
+
PerformanceMonitor$1.startTimer('guide-loop');
|
|
32547
32702
|
state.needsUpdate = false;
|
|
32548
32703
|
state.updateId = time;
|
|
32549
32704
|
},
|
|
32550
32705
|
completeUpdate(state, time) {
|
|
32706
|
+
PerformanceMonitor$1.stopTimer('guide-loop');
|
|
32551
32707
|
state.updateId = null;
|
|
32552
32708
|
state.updateCompleteTime = time;
|
|
32553
32709
|
}
|
|
@@ -32656,75 +32812,6 @@ var HealthCheckModule = (function () {
|
|
|
32656
32812
|
};
|
|
32657
32813
|
})();
|
|
32658
32814
|
|
|
32659
|
-
var MonitoringModule = (function () {
|
|
32660
|
-
var state = {
|
|
32661
|
-
lastFlush: getNow(),
|
|
32662
|
-
flushInterval: 5 * 60 * 1000,
|
|
32663
|
-
counters: {
|
|
32664
|
-
ptmGifFailures: 0,
|
|
32665
|
-
guideGifFailures: 0
|
|
32666
|
-
},
|
|
32667
|
-
timers: {}
|
|
32668
|
-
};
|
|
32669
|
-
var actions = {
|
|
32670
|
-
flush(context) {
|
|
32671
|
-
_.each(context.state.counters, function (value, counterName) {
|
|
32672
|
-
context.commit('resetCounter', counterName);
|
|
32673
|
-
});
|
|
32674
|
-
_.each(context.state.timers, function (value, timerName) {
|
|
32675
|
-
context.commit('resetTimer', timerName);
|
|
32676
|
-
});
|
|
32677
|
-
context.commit('setLastFlush', context.getters.now());
|
|
32678
|
-
}
|
|
32679
|
-
};
|
|
32680
|
-
var mutations = {
|
|
32681
|
-
setLastFlush(state, lastFlush) {
|
|
32682
|
-
state.lastFlush = lastFlush;
|
|
32683
|
-
},
|
|
32684
|
-
incrementCounter(state, counterName) {
|
|
32685
|
-
if (state.counters[counterName] === undefined)
|
|
32686
|
-
return;
|
|
32687
|
-
state.counters[counterName]++;
|
|
32688
|
-
},
|
|
32689
|
-
resetCounter(state, counterName) {
|
|
32690
|
-
if (state.counters[counterName] === undefined)
|
|
32691
|
-
return;
|
|
32692
|
-
state.counters[counterName] = 0;
|
|
32693
|
-
},
|
|
32694
|
-
setTimer(state, { name, time } = {}) {
|
|
32695
|
-
if (!name || time == null)
|
|
32696
|
-
return;
|
|
32697
|
-
state.timers[name] = time;
|
|
32698
|
-
},
|
|
32699
|
-
resetTimer(state, timerName) {
|
|
32700
|
-
delete state.timers[timerName];
|
|
32701
|
-
}
|
|
32702
|
-
};
|
|
32703
|
-
var getters = {
|
|
32704
|
-
shouldFlush(state, getters) {
|
|
32705
|
-
return (getters.now() - state.lastFlush) >= state.flushInterval;
|
|
32706
|
-
},
|
|
32707
|
-
payload(state) {
|
|
32708
|
-
var counters = _.reduce(state.counters, function (obj, value, key) {
|
|
32709
|
-
if (value > 0) {
|
|
32710
|
-
obj[key] = value;
|
|
32711
|
-
}
|
|
32712
|
-
return obj;
|
|
32713
|
-
}, {});
|
|
32714
|
-
return _.extend({}, counters, state.timers);
|
|
32715
|
-
},
|
|
32716
|
-
now() {
|
|
32717
|
-
return getNow();
|
|
32718
|
-
}
|
|
32719
|
-
};
|
|
32720
|
-
return {
|
|
32721
|
-
state,
|
|
32722
|
-
actions,
|
|
32723
|
-
mutations,
|
|
32724
|
-
getters
|
|
32725
|
-
};
|
|
32726
|
-
})();
|
|
32727
|
-
|
|
32728
32815
|
var MetadataModule = (function () {
|
|
32729
32816
|
var state = {
|
|
32730
32817
|
visitor: {},
|
|
@@ -32913,7 +33000,6 @@ const DebuggerModule = (() => {
|
|
|
32913
33000
|
context.commit('setTabId', EventTracer.getTabId());
|
|
32914
33001
|
context.commit('setInstallType', getInstallType());
|
|
32915
33002
|
const isTop = isLeader() && window.top === window; // only a leader frame that is a top window can launch debugger
|
|
32916
|
-
state.isTop !== isTop;
|
|
32917
33003
|
context.commit('setIsTop', isTop);
|
|
32918
33004
|
context.commit('isLeader', isLeader());
|
|
32919
33005
|
if (isTop) {
|
|
@@ -32964,6 +33050,8 @@ const DebuggerModule = (() => {
|
|
|
32964
33050
|
context.commit('enableEventLogging', enabled);
|
|
32965
33051
|
},
|
|
32966
33052
|
eventCaptured: (context, data) => {
|
|
33053
|
+
if (pendo$1.designerEnabled || isInPreviewMode() || isInDesignerPreviewMode())
|
|
33054
|
+
return;
|
|
32967
33055
|
if (!context.state.isTop) {
|
|
32968
33056
|
crossFrameChannel.postMessage({
|
|
32969
33057
|
action: 'debugger/receiveEventCaptured',
|
|
@@ -33202,6 +33290,68 @@ const DebuggerModule = (() => {
|
|
|
33202
33290
|
};
|
|
33203
33291
|
})();
|
|
33204
33292
|
|
|
33293
|
+
const NodeAttrModule = (function (global) {
|
|
33294
|
+
const state = {
|
|
33295
|
+
transforms: []
|
|
33296
|
+
};
|
|
33297
|
+
const actions = {
|
|
33298
|
+
addAttrTransform(context, urlTransform) {
|
|
33299
|
+
context.commit('addTransform', urlTransform);
|
|
33300
|
+
}
|
|
33301
|
+
};
|
|
33302
|
+
const mutations = {
|
|
33303
|
+
addTransform(state, transform) {
|
|
33304
|
+
state.transforms.push(transform);
|
|
33305
|
+
},
|
|
33306
|
+
clearURLTransforms(state) {
|
|
33307
|
+
// XXX if ever support non url transforms for attributes then we'll need to check the Transform type
|
|
33308
|
+
// or determine some other way how to purge only URL transforms as Location API provides a way for these to be
|
|
33309
|
+
// cleared via the API.
|
|
33310
|
+
state.transforms = [];
|
|
33311
|
+
}
|
|
33312
|
+
};
|
|
33313
|
+
const applyTransforms = (transforms, url) => {
|
|
33314
|
+
return _.reduce(transforms, function (tUrl, f) {
|
|
33315
|
+
return f.applyTo(tUrl);
|
|
33316
|
+
}, url);
|
|
33317
|
+
};
|
|
33318
|
+
const resolveAttrValueAsURL = (attrValue) => {
|
|
33319
|
+
// let's let the browser do this work for us...
|
|
33320
|
+
const a = document.createElement('a'); // this handles relative urls nicely
|
|
33321
|
+
a.href = attrValue;
|
|
33322
|
+
return new URL(a.href);
|
|
33323
|
+
};
|
|
33324
|
+
const getters = {
|
|
33325
|
+
getAttribute(state) {
|
|
33326
|
+
return function (element, attrName) {
|
|
33327
|
+
let attrValue = element.getAttribute ? element.getAttribute(attrName) : element[attrName];
|
|
33328
|
+
if (_.size(state.transforms) < 1) {
|
|
33329
|
+
return attrValue;
|
|
33330
|
+
}
|
|
33331
|
+
try {
|
|
33332
|
+
let url = resolveAttrValueAsURL(attrValue);
|
|
33333
|
+
url = _.reduce([
|
|
33334
|
+
_.partial(applyTransforms, state.transforms)
|
|
33335
|
+
], (url, fn) => {
|
|
33336
|
+
return fn(url);
|
|
33337
|
+
}, url);
|
|
33338
|
+
return url.href;
|
|
33339
|
+
}
|
|
33340
|
+
catch (e) {
|
|
33341
|
+
log.critical(e);
|
|
33342
|
+
return attrValue;
|
|
33343
|
+
}
|
|
33344
|
+
};
|
|
33345
|
+
}
|
|
33346
|
+
};
|
|
33347
|
+
return {
|
|
33348
|
+
state,
|
|
33349
|
+
actions,
|
|
33350
|
+
mutations,
|
|
33351
|
+
getters
|
|
33352
|
+
};
|
|
33353
|
+
})();
|
|
33354
|
+
|
|
33205
33355
|
function registerModules(store) {
|
|
33206
33356
|
store.registerModule('debugger', DebuggerModule);
|
|
33207
33357
|
store.registerModule('errorLog', ErrorLogModule);
|
|
@@ -33210,9 +33360,9 @@ function registerModules(store) {
|
|
|
33210
33360
|
store.registerModule('guideState', GuideStateModule);
|
|
33211
33361
|
store.registerModule('healthCheck', HealthCheckModule);
|
|
33212
33362
|
store.registerModule('location', LocationModule);
|
|
33213
|
-
store.registerModule('monitoring', MonitoringModule);
|
|
33214
33363
|
store.registerModule('metadata', MetadataModule);
|
|
33215
33364
|
store.registerModule('preview', PreviewModule);
|
|
33365
|
+
store.registerModule('nodeAttr', NodeAttrModule);
|
|
33216
33366
|
}
|
|
33217
33367
|
|
|
33218
33368
|
const IFrameMonitor = (function () {
|
|
@@ -36255,7 +36405,7 @@ const EventProperties = (function () {
|
|
|
36255
36405
|
return [];
|
|
36256
36406
|
}
|
|
36257
36407
|
return [
|
|
36258
|
-
new
|
|
36408
|
+
new UrlTransform('search', 'AddTo', function () { return collectPageEventProperties(); })
|
|
36259
36409
|
];
|
|
36260
36410
|
}
|
|
36261
36411
|
function createPageEventProperties() {
|
|
@@ -47297,6 +47447,7 @@ class SessionRecorder {
|
|
|
47297
47447
|
this.sendQueue = new SendQueue(bind(this.transport.send, this.transport));
|
|
47298
47448
|
this.sendQueue.onTimeout = bind(this.sendFailure, this, 'SEND_TIMEOUT');
|
|
47299
47449
|
this.isNewSession = false;
|
|
47450
|
+
this.isCheckingVisitorEligibility = false;
|
|
47300
47451
|
this.addConfigOptions();
|
|
47301
47452
|
this.config = configReader.get(RECORDING_CONFIG);
|
|
47302
47453
|
this.onRecordingStart = this.pendo._.isFunction(configReader.get(RECORDING_CONFIG_ON_RECORDING_START))
|
|
@@ -47399,19 +47550,32 @@ class SessionRecorder {
|
|
|
47399
47550
|
clearTimeout(this._changeIdentityTimer);
|
|
47400
47551
|
this.visitorId = options.visitor.id;
|
|
47401
47552
|
this.accountId = options.account.id;
|
|
47402
|
-
return this.
|
|
47403
|
-
if ((!visitorConfig || !visitorConfig.enable) && this.isRecording()) {
|
|
47404
|
-
this.stop();
|
|
47405
|
-
}
|
|
47406
|
-
else if (visitorConfig && visitorConfig.enable && !this.isRecording()) {
|
|
47407
|
-
this._startRecordingForVisitor(visitorConfig);
|
|
47408
|
-
}
|
|
47409
|
-
}).catch((e) => {
|
|
47410
|
-
this.api.log.critical('Failed to re-fetch recording config', { error: e });
|
|
47411
|
-
this.logStopReason('VISITOR_CONFIG_ERROR');
|
|
47412
|
-
});
|
|
47553
|
+
return this.checkVisitorEligibility();
|
|
47413
47554
|
}
|
|
47414
47555
|
}
|
|
47556
|
+
checkVisitorEligibility(continuationCallback) {
|
|
47557
|
+
if (!this.isRecording() && this.pendo._.isNull(this.visitorId) && this.pendo._.isNull(this.accountId))
|
|
47558
|
+
return;
|
|
47559
|
+
this.isCheckingVisitorEligibility = true;
|
|
47560
|
+
return this.fetchVisitorConfig().then(visitorConfig => {
|
|
47561
|
+
if ((!visitorConfig || !visitorConfig.enable) && this.isRecording()) {
|
|
47562
|
+
this.stop();
|
|
47563
|
+
}
|
|
47564
|
+
if (visitorConfig && visitorConfig.enable && this.isRecording()) {
|
|
47565
|
+
if (continuationCallback) {
|
|
47566
|
+
continuationCallback.call(this);
|
|
47567
|
+
}
|
|
47568
|
+
}
|
|
47569
|
+
if (visitorConfig && visitorConfig.enable && !this.isRecording()) {
|
|
47570
|
+
this._startRecordingForVisitor(visitorConfig);
|
|
47571
|
+
}
|
|
47572
|
+
}).catch((e) => {
|
|
47573
|
+
this.api.log.critical('Failed to re-fetch recording config', { error: e });
|
|
47574
|
+
this.logStopReason('VISITOR_CONFIG_ERROR');
|
|
47575
|
+
}).finally(() => {
|
|
47576
|
+
this.isCheckingVisitorEligibility = false;
|
|
47577
|
+
});
|
|
47578
|
+
}
|
|
47415
47579
|
snapshot() {
|
|
47416
47580
|
if (!this.isRecording())
|
|
47417
47581
|
return;
|
|
@@ -47673,13 +47837,24 @@ class SessionRecorder {
|
|
|
47673
47837
|
if ((!prevLastEmitTime && isMeta)) {
|
|
47674
47838
|
skipUserInteractionCheck = true;
|
|
47675
47839
|
}
|
|
47676
|
-
|
|
47840
|
+
// Ensures events emitted while the visitor eligibility check is in flight are compared against events emitted
|
|
47841
|
+
// before the visitor eligibility check occurred. This means these events which fall outside of the inactivity
|
|
47842
|
+
// duration will not be placed in the buffer and captured. This is ok since they occurred outside of the
|
|
47843
|
+
// inactivity period and before the next snapshot.
|
|
47844
|
+
if (!this.isCheckingVisitorEligibility) {
|
|
47845
|
+
this.storeLastUserInteractionEventInformation(event, this.visitorId, this.accountId, skipUserInteractionCheck);
|
|
47846
|
+
}
|
|
47677
47847
|
const inactivityDuration = this.pendo._.get(this.visitorConfig, 'inactivityDuration', THIRTY_MINUTES);
|
|
47678
47848
|
if (prevLastEmitTime && event.timestamp - prevLastEmitTime > inactivityDuration && !isSnapshot && !isMeta) {
|
|
47679
|
-
this.
|
|
47680
|
-
|
|
47681
|
-
|
|
47682
|
-
|
|
47849
|
+
if (!this.isCheckingVisitorEligibility) {
|
|
47850
|
+
const continuationCallback = function () {
|
|
47851
|
+
this.send();
|
|
47852
|
+
this.clearSessionInfo();
|
|
47853
|
+
this.snapshot();
|
|
47854
|
+
};
|
|
47855
|
+
this.checkVisitorEligibility(continuationCallback);
|
|
47856
|
+
}
|
|
47857
|
+
return;
|
|
47683
47858
|
}
|
|
47684
47859
|
/*
|
|
47685
47860
|
* META events and Snapshots are special and need to be packaged together. This is made possible by
|
|
@@ -47714,8 +47889,16 @@ class SessionRecorder {
|
|
|
47714
47889
|
const exceedsEventFreq = this.eventsSinceLastKeyFrame >= this.pendo._.get(this.visitorConfig, 'keyframeEventFrequency', 4548); // Defaults determined by BE originally, shouldn't really ever be used
|
|
47715
47890
|
const exceedsRecordingSizeLimit = this.currentRecordingSize >= this.pendo._.get(this.visitorConfig, 'recordingSizeLimit', ONE_HUNDRED_MB_IN_BYTES);
|
|
47716
47891
|
if (exceeds24Hours || (exceedsTimeFreq && exceedsEventFreq) || exceedsRecordingSizeLimit) {
|
|
47717
|
-
|
|
47718
|
-
|
|
47892
|
+
const continuationCallback = function () {
|
|
47893
|
+
this.currentRecordingSize = 0;
|
|
47894
|
+
this.snapshot();
|
|
47895
|
+
};
|
|
47896
|
+
if (exceeds24Hours && !this.isCheckingVisitorEligibility) {
|
|
47897
|
+
this.checkVisitorEligibility(continuationCallback);
|
|
47898
|
+
}
|
|
47899
|
+
else {
|
|
47900
|
+
continuationCallback.call(this);
|
|
47901
|
+
}
|
|
47719
47902
|
}
|
|
47720
47903
|
}
|
|
47721
47904
|
}
|
|
@@ -48954,17 +49137,14 @@ class ConsoleCaptureBuffer {
|
|
|
48954
49137
|
constructor(pendo, pluginAPI) {
|
|
48955
49138
|
this.pendo = pendo;
|
|
48956
49139
|
this.pluginAPI = pluginAPI;
|
|
48957
|
-
this.
|
|
48958
|
-
this.warnEvents = [];
|
|
48959
|
-
this.errorEvents = [];
|
|
49140
|
+
this.events = [];
|
|
48960
49141
|
this.lastEvent = null;
|
|
48961
|
-
this.devLogEvent = null;
|
|
48962
49142
|
this.tokens = TOKEN_MAX_SIZE;
|
|
48963
49143
|
this.lastRefillTime = this.pluginAPI.util.getNow();
|
|
48964
49144
|
this.nextRefillTime = this.lastRefillTime + TOKEN_REFRESH_INTERVAL;
|
|
48965
49145
|
}
|
|
48966
49146
|
isEmpty() {
|
|
48967
|
-
return this.
|
|
49147
|
+
return this.events.length === 0;
|
|
48968
49148
|
}
|
|
48969
49149
|
refillTokens() {
|
|
48970
49150
|
const now = this.pluginAPI.util.getNow();
|
|
@@ -48978,10 +49158,8 @@ class ConsoleCaptureBuffer {
|
|
|
48978
49158
|
}
|
|
48979
49159
|
}
|
|
48980
49160
|
clear() {
|
|
49161
|
+
this.events = [];
|
|
48981
49162
|
this.lastEvent = null;
|
|
48982
|
-
this.infoEvents.length = 0;
|
|
48983
|
-
this.warnEvents.length = 0;
|
|
48984
|
-
this.errorEvents.length = 0;
|
|
48985
49163
|
}
|
|
48986
49164
|
push(event) {
|
|
48987
49165
|
const { devLogLevel } = event;
|
|
@@ -48991,50 +49169,16 @@ class ConsoleCaptureBuffer {
|
|
|
48991
49169
|
if (this.tokens === 0)
|
|
48992
49170
|
return false;
|
|
48993
49171
|
this.lastEvent = event;
|
|
48994
|
-
this.
|
|
49172
|
+
this.events.push(event);
|
|
48995
49173
|
this.tokens = Math.max(this.tokens - 1, 0);
|
|
48996
49174
|
return true;
|
|
48997
49175
|
}
|
|
48998
|
-
|
|
48999
|
-
switch (event.devLogLevel) {
|
|
49000
|
-
case 'info':
|
|
49001
|
-
this.infoEvents.push(event);
|
|
49002
|
-
break;
|
|
49003
|
-
case 'warn':
|
|
49004
|
-
this.warnEvents.push(event);
|
|
49005
|
-
break;
|
|
49006
|
-
case 'error':
|
|
49007
|
-
this.errorEvents.push(event);
|
|
49008
|
-
break;
|
|
49009
|
-
}
|
|
49010
|
-
}
|
|
49011
|
-
createDevLogEventWithPayload({ events, level }) {
|
|
49012
|
-
if (events.length === 0)
|
|
49013
|
-
return;
|
|
49014
|
-
const totalCount = this.pendo._.reduce(events, (sum, event) => sum + (event.devLogCount || 1), 0);
|
|
49015
|
-
return Object.assign(Object.assign({}, this.devLogEvent), { devLogLevel: level, devLogCount: totalCount, devLogPayload: this.pendo.compress(events) });
|
|
49016
|
-
}
|
|
49017
|
-
generateJZB() {
|
|
49018
|
-
const payload = [];
|
|
49019
|
-
this.pendo._.each(DEV_LOG_LEVELS, level => {
|
|
49020
|
-
const events = this[`${level}Events`];
|
|
49021
|
-
if (events.length === 0)
|
|
49022
|
-
return;
|
|
49023
|
-
const devLogEventWithPayload = this.createDevLogEventWithPayload({
|
|
49024
|
-
events,
|
|
49025
|
-
level
|
|
49026
|
-
});
|
|
49027
|
-
payload.push(devLogEventWithPayload);
|
|
49028
|
-
});
|
|
49029
|
-
this.devLogEvent = null;
|
|
49030
|
-
return this.pendo.compress(payload);
|
|
49031
|
-
}
|
|
49032
|
-
pack(url) {
|
|
49176
|
+
pack() {
|
|
49033
49177
|
if (this.isEmpty())
|
|
49034
|
-
return
|
|
49035
|
-
const jzb = this.
|
|
49178
|
+
return;
|
|
49179
|
+
const jzb = this.pendo.compress(this.events);
|
|
49036
49180
|
this.clear();
|
|
49037
|
-
return
|
|
49181
|
+
return jzb;
|
|
49038
49182
|
}
|
|
49039
49183
|
}
|
|
49040
49184
|
|
|
@@ -55818,12 +55962,11 @@ function ConsoleCapture() {
|
|
|
55818
55962
|
initialize,
|
|
55819
55963
|
teardown,
|
|
55820
55964
|
addIntercepts,
|
|
55821
|
-
|
|
55965
|
+
createConsoleEvent,
|
|
55822
55966
|
captureStackTrace,
|
|
55823
55967
|
send,
|
|
55824
55968
|
onAppHidden,
|
|
55825
55969
|
onAppUnloaded,
|
|
55826
|
-
onEventCaptured,
|
|
55827
55970
|
onPtmPaused,
|
|
55828
55971
|
onPtmUnpaused,
|
|
55829
55972
|
get buffer() {
|
|
@@ -55857,7 +56000,6 @@ function ConsoleCapture() {
|
|
|
55857
56000
|
pluginAPI.Events.ready.on(addIntercepts);
|
|
55858
56001
|
pluginAPI.Events.appUnloaded.on(onAppUnloaded);
|
|
55859
56002
|
pluginAPI.Events.appHidden.on(onAppHidden);
|
|
55860
|
-
pluginAPI.Events.eventCaptured.on(onEventCaptured);
|
|
55861
56003
|
pluginAPI.Events['ptm:paused'].on(onPtmPaused);
|
|
55862
56004
|
pluginAPI.Events['ptm:unpaused'].on(onPtmUnpaused);
|
|
55863
56005
|
pluginAPI.log.info('Console logs are being captured');
|
|
@@ -55868,36 +56010,19 @@ function ConsoleCapture() {
|
|
|
55868
56010
|
function onAppUnloaded() {
|
|
55869
56011
|
send({ unload: true });
|
|
55870
56012
|
}
|
|
55871
|
-
/**
|
|
55872
|
-
* Handles eventCaptured events to monitor recordingId changes and/or link devLog events with recordingId
|
|
55873
|
-
*
|
|
55874
|
-
* @param {object} event - eventCaptured event
|
|
55875
|
-
*/
|
|
55876
|
-
function onEventCaptured(event) {
|
|
55877
|
-
if (!event || !event.data || !event.data.length || !buffer.devLogEvent)
|
|
55878
|
-
return;
|
|
55879
|
-
const capturedEvent = event.data[0];
|
|
55880
|
-
const { type, recordingId, recordingSessionId } = capturedEvent;
|
|
55881
|
-
if (type === DEV_LOG_TYPE || type === 'identify' || !recordingId || !recordingSessionId)
|
|
55882
|
-
return;
|
|
55883
|
-
const { recordingId: devLogRecordingId } = buffer.devLogEvent;
|
|
55884
|
-
// if recordingId has changed, send current buffer immediately to separate recording sessions
|
|
55885
|
-
if (devLogRecordingId && recordingId !== devLogRecordingId) {
|
|
55886
|
-
send();
|
|
55887
|
-
return;
|
|
55888
|
-
}
|
|
55889
|
-
}
|
|
55890
56013
|
function onPtmPaused() {
|
|
55891
56014
|
isPtmPaused = true;
|
|
55892
56015
|
}
|
|
55893
56016
|
function onPtmUnpaused() {
|
|
55894
56017
|
isPtmPaused = false;
|
|
55895
|
-
if (!buffer.
|
|
55896
|
-
buffer.
|
|
56018
|
+
if (!buffer.isEmpty()) {
|
|
56019
|
+
for (const event of buffer.events) {
|
|
56020
|
+
pluginAPI.Events.eventCaptured.trigger(event);
|
|
56021
|
+
}
|
|
56022
|
+
send();
|
|
55897
56023
|
}
|
|
55898
|
-
pluginAPI.Events.eventCaptured.trigger(buffer.devLogEvent);
|
|
55899
56024
|
}
|
|
55900
|
-
function
|
|
56025
|
+
function createDevLogEnvelope() {
|
|
55901
56026
|
return {
|
|
55902
56027
|
visitorId: globalPendo.get_visitor_id(),
|
|
55903
56028
|
accountId: globalPendo.get_account_id(),
|
|
@@ -55916,14 +56041,14 @@ function ConsoleCapture() {
|
|
|
55916
56041
|
// slice 1 to omit originalFn
|
|
55917
56042
|
const args = _.toArray(arguments).slice(1);
|
|
55918
56043
|
originalFn.apply(console, args);
|
|
55919
|
-
|
|
56044
|
+
createConsoleEvent(args, methodName);
|
|
55920
56045
|
});
|
|
55921
56046
|
console[methodName]._pendoUnwrap = function () {
|
|
55922
56047
|
console[methodName] = originalMethod;
|
|
55923
56048
|
};
|
|
55924
56049
|
});
|
|
55925
56050
|
}
|
|
55926
|
-
function
|
|
56051
|
+
function createConsoleEvent(args, methodName) {
|
|
55927
56052
|
if (!args || args.length === 0)
|
|
55928
56053
|
return;
|
|
55929
56054
|
// stringify args
|
|
@@ -55951,22 +56076,16 @@ function ConsoleCapture() {
|
|
|
55951
56076
|
buffer.lastEvent.devLogCount++;
|
|
55952
56077
|
return;
|
|
55953
56078
|
}
|
|
55954
|
-
const
|
|
55955
|
-
|
|
55956
|
-
|
|
55957
|
-
devLogTrace: stackTrace,
|
|
55958
|
-
devLogTimestamp: pluginAPI.util.getNow(),
|
|
55959
|
-
devLogCount: 1
|
|
55960
|
-
};
|
|
55961
|
-
const wasAccepted = buffer.push(devLog);
|
|
56079
|
+
const devLogEnvelope = createDevLogEnvelope();
|
|
56080
|
+
const consoleEvent = Object.assign(Object.assign({}, devLogEnvelope), { devLogLevel: methodName === 'log' ? 'info' : methodName, devLogMessage: scrubPII(message), devLogTrace: stackTrace, devLogCount: 1 });
|
|
56081
|
+
const wasAccepted = buffer.push(consoleEvent);
|
|
55962
56082
|
if (wasAccepted) {
|
|
55963
|
-
if (
|
|
55964
|
-
|
|
55965
|
-
pluginAPI.Events.eventCaptured.trigger(buffer.devLogEvent);
|
|
56083
|
+
if (!isPtmPaused) {
|
|
56084
|
+
pluginAPI.Events.eventCaptured.trigger(consoleEvent);
|
|
55966
56085
|
}
|
|
55967
56086
|
updateLastLog(logKey);
|
|
55968
56087
|
}
|
|
55969
|
-
return
|
|
56088
|
+
return consoleEvent;
|
|
55970
56089
|
}
|
|
55971
56090
|
function captureStackTrace(maxStackFrames) {
|
|
55972
56091
|
try {
|
|
@@ -55986,19 +56105,23 @@ function ConsoleCapture() {
|
|
|
55986
56105
|
function send({ unload = false, hidden = false } = {}) {
|
|
55987
56106
|
if (!buffer || buffer.isEmpty())
|
|
55988
56107
|
return;
|
|
56108
|
+
if (!globalPendo.isSendingEvents()) {
|
|
56109
|
+
buffer.clear();
|
|
56110
|
+
return;
|
|
56111
|
+
}
|
|
55989
56112
|
const queryParams = {
|
|
55990
56113
|
v: globalPendo.VERSION,
|
|
55991
56114
|
ct: pluginAPI.util.getNow()
|
|
55992
56115
|
};
|
|
55993
56116
|
const url = pluginAPI.transmit.buildBaseDataUrl('devlog', globalPendo.apiKey, queryParams);
|
|
55994
|
-
const
|
|
55995
|
-
if (!
|
|
56117
|
+
const jzb = buffer.pack();
|
|
56118
|
+
if (!jzb)
|
|
55996
56119
|
return;
|
|
55997
56120
|
if (unload || hidden) {
|
|
55998
|
-
sendQueue.drain(
|
|
56121
|
+
sendQueue.drain([{ url, jzb }], unload);
|
|
55999
56122
|
}
|
|
56000
56123
|
else {
|
|
56001
|
-
sendQueue.push(
|
|
56124
|
+
sendQueue.push({ url, jzb });
|
|
56002
56125
|
}
|
|
56003
56126
|
}
|
|
56004
56127
|
function teardown() {
|
|
@@ -56014,7 +56137,6 @@ function ConsoleCapture() {
|
|
|
56014
56137
|
}
|
|
56015
56138
|
pluginAPI.Events.appHidden.off(onAppHidden);
|
|
56016
56139
|
pluginAPI.Events.appUnloaded.off(onAppUnloaded);
|
|
56017
|
-
pluginAPI.Events.eventCaptured.off(onEventCaptured);
|
|
56018
56140
|
pluginAPI.Events['ptm:paused'].off(onPtmPaused);
|
|
56019
56141
|
pluginAPI.Events['ptm:unpaused'].off(onPtmUnpaused);
|
|
56020
56142
|
_.each(CONSOLE_METHODS, function (methodName) {
|