@grafana/faro-web-sdk
Version:
Faro instrumentations, metas, transports for web.
125 lines • 5.83 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserActionController = void 0;
// packages/web-sdk/src/instrumentations/userActions/userActionController.ts
var faro_core_1 = require("@grafana/faro-core");
var domMutationMonitor_1 = require("../_internal/monitors/domMutationMonitor");
var httpRequestMonitor_1 = require("../_internal/monitors/httpRequestMonitor");
var performanceEntriesMonitor_1 = require("../_internal/monitors/performanceEntriesMonitor");
var util_1 = require("./util");
var defaultFollowUpActionTimeRange = 100;
var defaultHaltTimeout = 10 * 1000;
var UserActionController = /** @class */ (function () {
function UserActionController(userAction) {
this.userAction = userAction;
this.http = (0, httpRequestMonitor_1.monitorHttpRequests)();
this.dom = (0, domMutationMonitor_1.monitorDomMutations)();
this.perf = (0, performanceEntriesMonitor_1.monitorPerformanceEntries)();
this.isValid = false;
this.runningRequests = new Map();
}
UserActionController.prototype.attach = function () {
var _this = this;
// Subscribe to monitors while action is active/halting
this.allMonitorsSub = new faro_core_1.Observable()
.merge(this.http, this.dom, this.perf)
.takeWhile(function () { return [faro_core_1.UserActionState.Started, faro_core_1.UserActionState.Halted].includes(_this.userAction.getState()); })
.filter(function (msg) {
// If the user action is in halt state, we only keep listening to ended http requests
if (_this.userAction.getState() === faro_core_1.UserActionState.Halted &&
!((0, util_1.isRequestEndMessage)(msg) && _this.runningRequests.has(msg.request.requestId))) {
return false;
}
return true;
})
.subscribe(function (msg) {
if ((0, util_1.isRequestStartMessage)(msg)) {
// An action is on halt if it has pending items, like pending HTTP requests.
// In this case we start a separate timeout to wait for the requests to finish
// If in the halt state, we stop adding Faro signals to the action's buffer (see userActionLifecycleHandler.ts)
// But we are still subscribed to
_this.runningRequests.set(msg.request.requestId, msg.request);
}
if ((0, util_1.isRequestEndMessage)(msg)) {
_this.runningRequests.delete(msg.request.requestId);
}
if (!(0, util_1.isRequestEndMessage)(msg)) {
if (!_this.isValid) {
_this.isValid = true;
}
_this.scheduleFollowUp();
}
else if (_this.userAction.getState() === faro_core_1.UserActionState.Halted && _this.runningRequests.size === 0) {
_this.endAction();
}
});
// When UA ends or cancels, cleanup timers/subscriptions
this.stateSub = this.userAction
.filter(function (s) { return [faro_core_1.UserActionState.Ended, faro_core_1.UserActionState.Cancelled].includes(s); })
.first()
.subscribe(function () { return _this.cleanup(); });
// initial follow-up window in case nothing else happens
this.scheduleFollowUp();
};
UserActionController.prototype.scheduleFollowUp = function () {
var _this = this;
this.clearTimer(this.followUpTid);
this.followUpTid = setTimeout(function () {
// If action just started and there's pending work, go to halted
if (_this.userAction.getState() === faro_core_1.UserActionState.Started && _this.runningRequests.size > 0) {
_this.haltAction();
return;
}
// If we saw any relevant activity in the window, finish as ended
if (_this.isValid) {
_this.endAction();
return;
}
// Otherwise, no signals => cancel
_this.cancelAction();
}, defaultFollowUpActionTimeRange);
};
UserActionController.prototype.haltAction = function () {
if (this.userAction.getState() !== faro_core_1.UserActionState.Started) {
return;
}
this.userAction.halt();
this.startHaltTimeout();
};
UserActionController.prototype.startHaltTimeout = function () {
var _this = this;
this.clearTimer(this.haltTid);
this.haltTid = (0, util_1.startTimeout)(this.haltTid, function () {
// If still halted after timeout, end
if (_this.userAction.getState() === faro_core_1.UserActionState.Halted) {
_this.endAction();
}
}, defaultHaltTimeout);
};
UserActionController.prototype.endAction = function () {
this.userAction.end();
this.cleanup();
};
UserActionController.prototype.cancelAction = function () {
this.userAction.cancel();
this.cleanup();
};
UserActionController.prototype.cleanup = function () {
var _a, _b;
this.clearTimer(this.followUpTid);
this.clearTimer(this.haltTid);
(_a = this.allMonitorsSub) === null || _a === void 0 ? void 0 : _a.unsubscribe();
(_b = this.stateSub) === null || _b === void 0 ? void 0 : _b.unsubscribe();
this.allMonitorsSub = undefined;
this.stateSub = undefined;
this.runningRequests.clear();
};
UserActionController.prototype.clearTimer = function (id) {
if (id) {
clearTimeout(id);
}
};
return UserActionController;
}());
exports.UserActionController = UserActionController;
//# sourceMappingURL=userActionController.js.map