@embrace-io/web-sdk
Version:
86 lines (85 loc) • 3.02 kB
JavaScript
import { getSelector } from "../../../utils/getSelector.js";
import { KEY_EMB_TYPE } from "../../../constants/attributes.js";
import { EmbraceInstrumentationBase } from "../../EmbraceInstrumentationBase/EmbraceInstrumentationBase.js";
import { ATTR_RAGE_CLICK_COUNT, ATTR_RAGE_CLICK_ELEMENT_SELECTOR, ATTR_RAGE_CLICK_ELEMENT_TYPE, ATTR_RAGE_CLICK_INTERACTION_TYPE, ATTR_RAGE_CLICK_X, ATTR_RAGE_CLICK_Y, RAGE_CLICK_EVENT_NAME } from "./constants.js";
import { SeverityNumber } from "@opentelemetry/api-logs";
//#region src/instrumentations/rage-click/RageClickInstrumentation/RageClickInstrumentation.ts
var RageClickInstrumentation = class extends EmbraceInstrumentationBase {
_onClickHandler;
_eventWindow = null;
constructor({ diag, perf } = {}) {
super({
instrumentationName: "RageClickInstrumentation",
instrumentationVersion: "1.0.0",
diag,
perf,
config: {}
});
this._onClickHandler = (event) => {
try {
this._handleClick(event);
} catch (e) {
this._diag.error("failed to process rage-click candidate", e);
}
};
if (this._config.enabled) this.enable();
}
onDisable() {
document.removeEventListener("click", this._onClickHandler);
this._flush();
}
onEnable() {
document.addEventListener("click", this._onClickHandler);
}
_handleClick(event) {
if (!(event.target instanceof Element)) return;
const target = event.target;
const interactionType = event instanceof PointerEvent && event.pointerType === "touch" ? "tap" : "click";
if (this._eventWindow === null) {
this._eventWindow = {
target,
x: event.clientX,
y: event.clientY,
count: 1,
interactionType,
timestamp: event.timeStamp,
timeoutId: window.setTimeout(() => {
try {
this._flush();
} catch (e) {
this._diag.error("failed to emit rage-click log", e);
}
}, 500)
};
return;
}
const sameTarget = target === this._eventWindow.target;
const dx = Math.abs(event.clientX - this._eventWindow.x);
const dy = Math.abs(event.clientY - this._eventWindow.y);
if (sameTarget || dx <= 50 && dy <= 50) this._eventWindow.count += 1;
}
_flush() {
if (this._eventWindow === null) return;
const eventWindow = this._eventWindow;
window.clearTimeout(eventWindow.timeoutId);
this._eventWindow = null;
if (eventWindow.count < 3) return;
this.logger.emit({
timestamp: this.perf.epochMillisFromOrigin(eventWindow.timestamp),
eventName: RAGE_CLICK_EVENT_NAME,
severityNumber: SeverityNumber.INFO,
attributes: {
[KEY_EMB_TYPE]: "emb.otel_log",
[ATTR_RAGE_CLICK_ELEMENT_TYPE]: eventWindow.target.tagName.toLowerCase(),
[ATTR_RAGE_CLICK_ELEMENT_SELECTOR]: getSelector(eventWindow.target),
[ATTR_RAGE_CLICK_X]: eventWindow.x,
[ATTR_RAGE_CLICK_Y]: eventWindow.y,
[ATTR_RAGE_CLICK_COUNT]: eventWindow.count,
[ATTR_RAGE_CLICK_INTERACTION_TYPE]: eventWindow.interactionType
}
});
}
};
//#endregion
export { RageClickInstrumentation };
//# sourceMappingURL=RageClickInstrumentation.js.map