analytics-tracker-sdk
Version:
一个功能强大的前端数据埋点 SDK,支持自动埋点、手动埋点、批量上报等特性
808 lines (791 loc) • 31.2 kB
JavaScript
'use strict';
var uuid = require('uuid');
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
/**
* 本地存储实现类
* 提供基于 localStorage 的数据存储功能
*/
/**
* 本地存储实现类,使用 localStorage 作为存储介质
* 支持数据的持久化存储,并提供前缀隔离机制
*/
var LocalStorage = /** @class */ (function () {
/**
* 创建 LocalStorage 实例
* @param prefix - 存储键的前缀,默认为 'tracker_'
*/
function LocalStorage(prefix) {
if (prefix === void 0) { prefix = 'tracker_'; }
this.prefix = prefix;
}
/**
* 获取带前缀的完整存储键
* @param key - 原始键名
* @returns 带前缀的完整键名
*/
LocalStorage.prototype.getKey = function (key) {
return "".concat(this.prefix).concat(key);
};
/**
* 获取存储的值
* @param key - 存储键名
* @returns 存储的值,如果不存在或解析失败则返回 null
*/
LocalStorage.prototype.get = function (key) {
try {
var value = localStorage.getItem(this.getKey(key));
return value ? JSON.parse(value) : null;
}
catch (error) {
console.error('LocalStorage get error:', error);
return null;
}
};
/**
* 设置存储值
* @param key - 存储键名
* @param value - 要存储的值,会被自动序列化为 JSON 字符串
*/
LocalStorage.prototype.set = function (key, value) {
try {
localStorage.setItem(this.getKey(key), JSON.stringify(value));
}
catch (error) {
console.error('LocalStorage set error:', error);
}
};
/**
* 移除指定键的存储值
* @param key - 要移除的存储键名
*/
LocalStorage.prototype.remove = function (key) {
try {
localStorage.removeItem(this.getKey(key));
}
catch (error) {
console.error('LocalStorage remove error:', error);
}
};
/**
* 清除所有带有指定前缀的存储项
*/
LocalStorage.prototype.clear = function () {
var _this = this;
try {
Object.keys(localStorage).forEach(function (key) {
if (key.startsWith(_this.prefix)) {
localStorage.removeItem(key);
}
});
}
catch (error) {
console.error('LocalStorage clear error:', error);
}
};
return LocalStorage;
}());
/**
* 内存存储实现类,使用 Map 作为存储介质
* 用于在不支持 localStorage 的环境中提供备选方案
*/
var MemoryStorage = /** @class */ (function () {
function MemoryStorage() {
this.storage = new Map();
}
/**
* 获取存储的值
* @param key - 存储键名
* @returns 存储的值,如果不存在则返回 undefined
*/
MemoryStorage.prototype.get = function (key) {
return this.storage.get(key);
};
/**
* 设置存储值
* @param key - 存储键名
* @param value - 要存储的值
*/
MemoryStorage.prototype.set = function (key, value) {
this.storage.set(key, value);
};
/**
* 移除指定键的存储值
* @param key - 要移除的存储键名
*/
MemoryStorage.prototype.remove = function (key) {
this.storage.delete(key);
};
/**
* 清除所有存储项
*/
MemoryStorage.prototype.clear = function () {
this.storage.clear();
};
return MemoryStorage;
}());
/**
* 创建存储实例的工厂函数
* @param type - 存储类型,可选 'local' 或 'memory',默认为 'local'
* @param prefix - 存储键的前缀,仅在使用 LocalStorage 时有效
* @returns Storage 实例
*/
var createStorage = function (type, prefix) {
if (type === void 0) { type = 'local'; }
try {
if (type === 'local' && typeof window !== 'undefined' && window.localStorage) {
return new LocalStorage(prefix);
}
}
catch (error) {
console.warn('LocalStorage not available, fallback to MemoryStorage');
}
return new MemoryStorage();
};
/**
* 批量上报器实现类
* 支持数据批量发送、自动重试、离线缓存等特性
*/
var BatchReporter = /** @class */ (function () {
/**
* 创建批量上报器实例
* @param reportUrl - 数据上报的目标 URL
* @param batchSize - 每次批量发送的数据量,默认为 10
* @param reportInterval - 定时上报的时间间隔(毫秒),默认为 5000
* @param headers - 请求头配置
*/
function BatchReporter(reportUrl, batchSize, reportInterval, headers) {
if (batchSize === void 0) { batchSize = 10; }
if (reportInterval === void 0) { reportInterval = 5000; }
if (headers === void 0) { headers = {}; }
this.reportUrl = reportUrl;
this.batchSize = batchSize;
this.reportInterval = reportInterval;
this.headers = headers;
this.queue = [];
this.timer = null;
this.sending = false;
this.retryCount = 0;
this.maxRetries = 3;
this.maxQueueSize = 1000; // 队列最大容量
this.offlineStorage = null;
this.initOfflineStorage();
this.processOfflineData();
}
/**
* 初始化离线存储
*/
BatchReporter.prototype.initOfflineStorage = function () {
if (typeof window !== 'undefined' && window.localStorage) {
this.offlineStorage = window.localStorage;
window.addEventListener('online', this.processOfflineData.bind(this));
}
};
/**
* 处理离线数据
*/
BatchReporter.prototype.processOfflineData = function () {
return __awaiter(this, void 0, void 0, function () {
var offlineData, events, error_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!this.offlineStorage)
return [2 /*return*/];
offlineData = this.offlineStorage.getItem('offline_events');
if (!offlineData) return [3 /*break*/, 4];
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
events = JSON.parse(offlineData);
return [4 /*yield*/, this.send(events)];
case 2:
_a.sent();
this.offlineStorage.removeItem('offline_events');
return [3 /*break*/, 4];
case 3:
error_1 = _a.sent();
console.error('Process offline data error:', error_1);
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
});
};
/**
* 发送请求
* @param events - 要上报的事件数据数组
*/
BatchReporter.prototype.sendRequest = function (events) {
return __awaiter(this, void 0, void 0, function () {
var response, error_2;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 7]);
return [4 /*yield*/, fetch(this.reportUrl, {
method: 'POST',
headers: __assign({ 'Content-Type': 'application/json' }, this.headers),
body: JSON.stringify({
events: events,
timestamp: Date.now(),
}),
})];
case 1:
response = _a.sent();
if (!response.ok) {
throw new Error("HTTP error! status: ".concat(response.status));
}
this.retryCount = 0;
return [3 /*break*/, 7];
case 2:
error_2 = _a.sent();
console.error('Report error:', error_2);
if (!(this.retryCount < this.maxRetries)) return [3 /*break*/, 5];
this.retryCount++;
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 1000 * _this.retryCount); })];
case 3:
_a.sent();
return [4 /*yield*/, this.sendRequest(events)];
case 4:
_a.sent();
return [3 /*break*/, 6];
case 5:
this.retryCount = 0;
throw error_2;
case 6: return [3 /*break*/, 7];
case 7: return [2 /*return*/];
}
});
});
};
BatchReporter.prototype.isOnline = function () {
return typeof navigator !== 'undefined' ? navigator.onLine : true;
};
BatchReporter.prototype.scheduleReport = function () {
var _this = this;
if (this.timer) {
clearTimeout(this.timer);
}
this.timer = setTimeout(function () {
_this.batchSend(_this.queue);
}, this.reportInterval);
};
BatchReporter.prototype.send = function (events) {
return __awaiter(this, void 0, void 0, function () {
var _a, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!this.isOnline()) {
(_a = this.queue).push.apply(_a, events);
return [2 /*return*/];
}
_c.label = 1;
case 1:
_c.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.sendRequest(events)];
case 2:
_c.sent();
return [3 /*break*/, 4];
case 3:
_c.sent();
(_b = this.queue).push.apply(_b, events);
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
});
};
BatchReporter.prototype.batchSend = function (events) {
if (this.sending || events.length === 0)
return;
this.sending = true;
try {
while (events.length > 0) {
var batch = events.splice(0, this.batchSize);
this.send(batch);
}
}
finally {
this.sending = false;
}
if (this.queue.length >= this.batchSize) {
this.batchSend(this.queue);
}
else if (this.queue.length > 0) {
this.scheduleReport();
}
};
return BatchReporter;
}());
var createReporter = function (reportUrl, batchSize, reportInterval, headers) {
return new BatchReporter(reportUrl, batchSize, reportInterval, headers);
};
/**
* 性能监控类
* 用于收集和监控页面性能指标,包括 FCP、LCP、FID、CLS 等核心性能指标
*/
var PerformanceMonitor = /** @class */ (function () {
/**
* 创建性能监控实例
* 初始化性能观察器,开始收集性能指标
*/
function PerformanceMonitor() {
this.performanceData = {};
this.observer = null;
this.initObserver();
}
/**
* 初始化性能观察器
* 设置各项性能指标的观察器,包括 FCP、LCP、FID、CLS 等
*/
PerformanceMonitor.prototype.initObserver = function () {
var _this = this;
if (typeof window === 'undefined' || !window.PerformanceObserver)
return;
try {
// 监控首次内容绘制 (FCP)
var fcpObserver_1 = new PerformanceObserver(function (entryList) {
var entries = entryList.getEntries();
var fcp = entries[0];
if (fcp) {
_this.performanceData.fcp = fcp.startTime;
fcpObserver_1.disconnect();
}
});
fcpObserver_1.observe({ entryTypes: ['paint'] });
// 监控最大内容绘制 (LCP)
var lcpObserver = new PerformanceObserver(function (entryList) {
var entries = entryList.getEntries();
var lastEntry = entries[entries.length - 1];
if (lastEntry) {
_this.performanceData.lcp = lastEntry.startTime;
}
});
lcpObserver.observe({ entryTypes: ['largest-contentful-paint'] });
// 监控首次输入延迟 (FID)
var fidObserver_1 = new PerformanceObserver(function (entryList) {
var entries = entryList.getEntries();
var firstInput = entries[0];
if (firstInput) {
_this.performanceData.fid = firstInput.processingStart - firstInput.startTime;
fidObserver_1.disconnect();
}
});
fidObserver_1.observe({ entryTypes: ['first-input'] });
// 监控累积布局偏移 (CLS)
var clsValue_1 = 0;
var clsEntries_1 = [];
var clsObserver = new PerformanceObserver(function (entryList) {
var entries = entryList.getEntries();
entries.forEach(function (entry) {
var layoutShift = entry;
if (!layoutShift.hadRecentInput) {
var firstSessionEntry = clsEntries_1[0];
var lastSessionEntry = clsEntries_1[clsEntries_1.length - 1];
if (firstSessionEntry && entry.startTime - lastSessionEntry.startTime < 1000 && entry.startTime - firstSessionEntry.startTime < 5000) {
clsEntries_1.push(layoutShift);
}
else {
clsEntries_1 = [layoutShift];
}
if (clsEntries_1.length >= 1) {
var clsSession = clsEntries_1.reduce(function (sum, entry) { return sum + entry.value; }, 0);
clsValue_1 = Math.max(clsValue_1, clsSession);
_this.performanceData.cls = clsValue_1;
}
}
});
});
clsObserver.observe({ entryTypes: ['layout-shift'] });
this.observer = clsObserver;
}
catch (error) {
console.error('Performance observer error:', error);
}
};
/**
* 收集页面加载时间指标
*/
PerformanceMonitor.prototype.collectPageLoadTiming = function () {
if (typeof window === 'undefined' || !window.performance || !window.performance.timing)
return;
var timing = performance.timing;
var loadTime = timing.loadEventEnd - timing.navigationStart;
var domParseTime = timing.domComplete - timing.domLoading;
this.performanceData.loadTime = loadTime > 0 ? loadTime : undefined;
this.performanceData.domParseTime = domParseTime > 0 ? domParseTime : undefined;
};
/**
* 收集 Web Vitals 指标
*/
PerformanceMonitor.prototype.collectWebVitals = function () {
this.collectPageLoadTiming();
};
/**
* 获取收集到的性能数据
*/
PerformanceMonitor.prototype.getPerformanceData = function () {
return this.performanceData;
};
/**
* 获取性能指标
*/
PerformanceMonitor.prototype.getMetrics = function () {
return this.getPerformanceData();
};
/**
* 销毁性能监控实例
* 断开所有观察器连接
*/
PerformanceMonitor.prototype.destroy = function () {
if (this.observer) {
this.observer.disconnect();
this.observer = null;
}
};
return PerformanceMonitor;
}());
/**
* 创建性能监控实例
*/
var createPerformanceMonitor = function () {
return new PerformanceMonitor();
};
/**
* 错误监控类
* 用于捕获和处理 JavaScript 运行时错误、资源加载错误、Promise 异常和 AJAX 请求错误
*/
var ErrorMonitor = /** @class */ (function () {
/**
* 创建错误监控实例
* @param callback - 错误处理回调函数,用于处理捕获到的错误
*/
function ErrorMonitor(callback) {
var _this = this;
/**
* 处理 JavaScript 运行时错误和资源加载错误
* @param event - 错误事件对象
*/
this.handleError = function (event) {
var _a;
if (event instanceof ErrorEvent) {
// JavaScript 运行时错误
_this.errorCallback({
type: 'js',
message: event.message || 'Unknown error',
stack: (_a = event.error) === null || _a === void 0 ? void 0 : _a.stack,
filename: event.filename || 'unknown',
lineno: event.lineno || 0,
colno: event.colno || 0,
timestamp: Date.now()
});
}
else {
// 资源加载错误
var target = event.target;
_this.errorCallback({
type: 'resource',
message: "Resource load failed: ".concat(target.outerHTML),
filename: target.src || target.href || 'unknown',
timestamp: Date.now()
});
}
};
/**
* 处理未捕获的 Promise 异常
* @param event - Promise 异常事件对象
*/
this.handlePromiseError = function (event) {
var _a, _b;
_this.errorCallback({
type: 'promise',
message: ((_a = event.reason) === null || _a === void 0 ? void 0 : _a.message) || 'Promise rejection',
stack: (_b = event.reason) === null || _b === void 0 ? void 0 : _b.stack,
timestamp: Date.now()
});
};
this.errorCallback = callback;
this.init();
}
/**
* 初始化错误监控
* 设置各类错误的事件监听器
*/
ErrorMonitor.prototype.init = function () {
if (typeof window === 'undefined')
return;
// 监听 JS 运行时错误
window.addEventListener('error', this.handleError, true);
// 监听未捕获的 Promise 异常
window.addEventListener('unhandledrejection', this.handlePromiseError);
// 重写 XMLHttpRequest 以捕获 AJAX 错误
this.patchXMLHttpRequest();
};
/**
* 重写 XMLHttpRequest 以监控 AJAX 请求错误
*/
ErrorMonitor.prototype.patchXMLHttpRequest = function () {
var originalXHR = window.XMLHttpRequest;
var errorCallback = this.errorCallback;
window.XMLHttpRequest = function () {
var xhr = new originalXHR();
var originalOpen = xhr.open;
var originalSend = xhr.send;
xhr.open = function (method, url) {
var args = [];
for (var _i = 2; _i < arguments.length; _i++) {
args[_i - 2] = arguments[_i];
}
this._url = url.toString();
return originalOpen.apply(this, __spreadArray([method, url], args, true));
};
xhr.send = function () {
var _this = this;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this.addEventListener('error', function () {
errorCallback({
type: 'ajax',
message: "Ajax request failed: ".concat(_this._url),
timestamp: Date.now(),
filename: _this._url
});
});
this.addEventListener('timeout', function () {
errorCallback({
type: 'ajax',
message: "Ajax request timeout: ".concat(_this._url),
timestamp: Date.now(),
filename: _this._url
});
});
return originalSend.apply(this, args);
};
return xhr;
};
};
/**
* 销毁错误监控实例
* 移除所有事件监听器
*/
ErrorMonitor.prototype.destroy = function () {
window.removeEventListener('error', this.handleError, true);
window.removeEventListener('unhandledrejection', this.handlePromiseError);
};
return ErrorMonitor;
}());
/**
* 创建错误监控实例
* @param callback - 错误处理回调函数
*/
var createErrorMonitor = function (callback) {
return new ErrorMonitor(callback);
};
var Tracker = /** @class */ (function () {
function Tracker() {
this.initialized = false;
this.storage = createStorage('local', 'tracker_');
}
Tracker.prototype.init = function (config) {
var _this = this;
if (this.initialized) {
console.warn('Tracker has already been initialized');
return;
}
this.config = __assign({ autoTrackPageView: true, autoTrackClick: true, autoTrackPerformance: true, autoTrackError: true, batchSize: 10, reportInterval: 5000, debug: false, samplingRate: 1 }, config);
this.reporter = createReporter(this.config.reportUrl, this.config.batchSize, this.config.reportInterval, this.config.headers);
if (this.config.autoTrackPerformance) {
this.performanceMonitor = createPerformanceMonitor();
}
if (this.config.autoTrackError) {
this.errorMonitor = createErrorMonitor(function (error) {
_this.track('error', error);
});
}
if (this.config.autoTrackPageView) {
this.trackPageView();
window.addEventListener('popstate', this.trackPageView.bind(this));
window.addEventListener('hashchange', this.trackPageView.bind(this));
}
if (this.config.autoTrackClick) {
window.addEventListener('click', this.handleClick.bind(this), true);
}
this.initialized = true;
if (this.config.debug) {
console.log('Tracker initialized with config:', this.config);
}
};
Tracker.prototype.shouldSample = function () {
return Math.random() < (this.config.samplingRate || 1);
};
Tracker.prototype.createEvent = function (type, data) {
return {
id: uuid.v4(),
type: type,
timestamp: Date.now(),
data: __assign(__assign(__assign({}, data), { url: window.location.href, title: document.title, userAgent: navigator.userAgent }), this.getUserInfo()),
};
};
Tracker.prototype.trackPageView = function () {
var _a;
if (!this.shouldSample())
return;
var performanceData = ((_a = this.performanceMonitor) === null || _a === void 0 ? void 0 : _a.getMetrics()) || {};
this.track('page_view', {
path: window.location.pathname,
performance: performanceData,
});
};
Tracker.prototype.handleClick = function (event) {
var _a;
if (!this.shouldSample())
return;
var target = event.target;
if (!target)
return;
var trackData = {
tag: target.tagName.toLowerCase(),
text: (_a = target.textContent) === null || _a === void 0 ? void 0 : _a.trim(),
className: target.className,
id: target.id,
path: this.getElementPath(target),
};
this.track('click', trackData);
};
Tracker.prototype.getElementPath = function (element) {
var path = [];
var currentElement = element;
while (currentElement && currentElement !== document.body) {
var selector = currentElement.tagName.toLowerCase();
if (currentElement.id) {
selector += "#".concat(currentElement.id);
}
else if (currentElement.className) {
selector += ".".concat(currentElement.className.split(' ').join('.'));
}
path.unshift(selector);
currentElement = currentElement.parentElement;
}
return path.join(' > ');
};
Tracker.prototype.track = function (eventType, data) {
if (!this.initialized) {
console.error('Tracker not initialized');
return;
}
if (!this.shouldSample())
return;
var event = this.createEvent(eventType, data);
this.reporter.batchSend([event]);
if (this.config.debug) {
this.logger.debug('Event tracked:', eventData);
}
};
Tracker.prototype.setUser = function (userInfo) {
var currentInfo = this.getUserInfo();
this.storage.set('user', __assign(__assign({}, currentInfo), userInfo));
};
Tracker.prototype.getUserInfo = function () {
return this.storage.get('user') || {};
};
Tracker.prototype.clearUser = function () {
this.storage.remove('user');
};
Tracker.prototype.destroy = function () {
var _a, _b;
if (!this.initialized)
return;
if (this.config.autoTrackPageView) {
window.removeEventListener('popstate', this.trackPageView.bind(this));
window.removeEventListener('hashchange', this.trackPageView.bind(this));
}
if (this.config.autoTrackClick) {
window.removeEventListener('click', this.handleClick.bind(this), true);
}
(_a = this.performanceMonitor) === null || _a === void 0 ? void 0 : _a.destroy();
(_b = this.errorMonitor) === null || _b === void 0 ? void 0 : _b.destroy();
this.storage.clear();
this.initialized = false;
};
return Tracker;
}());
var createTracker = function () {
return new Tracker();
};
exports.createTracker = createTracker;
//# sourceMappingURL=index.js.map