UNPKG

@grafana/faro-web-sdk

Version:

Faro instrumentations, metas, transports for web.

130 lines 6.22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getUserEventHandler = void 0; var faro_core_1 = require("@grafana/faro-core"); var const_1 = require("./const"); var domMutationMonitor_1 = require("./domMutationMonitor"); var httpRequestMonitor_1 = require("./httpRequestMonitor"); var performanceEntriesMonitor_1 = require("./performanceEntriesMonitor"); var util_1 = require("./util"); function getUserEventHandler(faro) { var api = faro.api, config = faro.config; var httpMonitor = (0, httpRequestMonitor_1.monitorHttpRequests)(); var domMutationsMonitor = (0, domMutationMonitor_1.monitorDomMutations)(); var performanceEntriesMonitor = (0, performanceEntriesMonitor_1.monitorPerformanceEntries)(); var allMonitorsSub; var allMonitorsObserver; var timeoutId; var actionRunning = false; function processUserEvent(event) { var _a; var userActionName = getUserActionName(event.target, (_a = config.trackUserActionsDataAttributeName) !== null && _a !== void 0 ? _a : const_1.userActionDataAttributeParsed); if (actionRunning || userActionName == null) { return; } actionRunning = true; var startTime = (0, faro_core_1.dateNow)(); var endTime; var actionId = (0, faro_core_1.genShortID)(); faro_core_1.apiMessageBus.notify({ type: faro_core_1.USER_ACTION_START_MESSAGE_TYPE, name: userActionName, startTime: startTime, parentId: actionId, }); // Triggers if no initial action happened within the first 100ms timeoutId = startTimeout(timeoutId, function () { endTime = (0, faro_core_1.dateNow)(); // Listening for follow up activities stops once action is cancelled (set to false) actionRunning = false; sendUserActionCancelMessage(userActionName, actionId); }); allMonitorsObserver = (0, faro_core_1.merge)(httpMonitor, domMutationsMonitor, performanceEntriesMonitor); allMonitorsSub = allMonitorsObserver .takeWhile(function () { return actionRunning; }) .subscribe(function () { // A http request, a DOM mutation or a performance entry happened so we have a follow up activity and start the timeout again // If timeout is triggered the user action is done and we send respective messages and events timeoutId = startTimeout(timeoutId, function () { endTime = (0, faro_core_1.dateNow)(); var duration = endTime - startTime; var eventType = event.type; // order matters, first emit the user-action-end event and then push the event faro_core_1.apiMessageBus.notify({ type: faro_core_1.USER_ACTION_END_MESSAGE_TYPE, name: userActionName, id: actionId, startTime: startTime, endTime: endTime, duration: duration, eventType: eventType, }); // Send the final action parent event api.pushEvent(userActionName, { userActionStartTime: startTime.toString(), userActionEndTime: endTime.toString(), userActionDuration: duration.toString(), userActionEventType: eventType, }, undefined, { timestampOverwriteMs: startTime, customPayloadTransformer: function (payload) { payload.action = { id: actionId, name: userActionName, }; return payload; }, }); // Ensure action is blocked until it is fully processed. actionRunning = false; allMonitorsSub === null || allMonitorsSub === void 0 ? void 0 : allMonitorsSub.unsubscribe(); allMonitorsObserver === null || allMonitorsObserver === void 0 ? void 0 : allMonitorsObserver.unsubscribeAll(); }); }); } registerVisibilityChangeHandler(allMonitorsSub, allMonitorsObserver); return processUserEvent; } exports.getUserEventHandler = getUserEventHandler; function getUserActionName(element, dataAttributeName) { var parsedDataAttributeName = (0, util_1.convertDataAttributeName)(dataAttributeName); var dataset = element.dataset; for (var key in dataset) { if (key === parsedDataAttributeName) { return dataset[key]; } } return undefined; } function startTimeout(timeoutId, cb) { var maxTimeSpanTillUserActionEnd = 100; if (timeoutId) { clearTimeout(timeoutId); } //@ts-expect-error for some reason vscode is using the node types timeoutId = setTimeout(function () { cb(); }, maxTimeSpanTillUserActionEnd); return timeoutId; } function sendUserActionCancelMessage(userActionName, actionId) { faro_core_1.apiMessageBus.notify({ type: faro_core_1.USER_ACTION_CANCEL_MESSAGE_TYPE, name: userActionName, parentId: actionId, }); } function registerVisibilityChangeHandler(allMonitorsSub, allMonitorsObserver) { // stop monitoring in background tabs document.addEventListener('visibilitychange', function () { if (document.visibilityState === 'hidden') { // Unsubscribe from all monitors when the tab goes into the background to free up resources (merge.unsubscribe() also unsubscribes from all inner observables) // Monitors will be re-subscribed in the processEvent function when the first user action is detected allMonitorsSub === null || allMonitorsSub === void 0 ? void 0 : allMonitorsSub.unsubscribe(); allMonitorsSub = undefined; allMonitorsObserver === null || allMonitorsObserver === void 0 ? void 0 : allMonitorsObserver.unsubscribeAll(); allMonitorsObserver = undefined; } }); } //# sourceMappingURL=processUserActionEventHandler.js.map