@openreplay/tracker
Advanced tools
Comparing version 3.5.16-beta.1 to 3.5.16-beta.2
import type Message from "../common/messages.js"; | ||
import Nodes from "./nodes.js"; | ||
import Nodes, { CheckOptions } from "./nodes.js"; | ||
import Sanitizer from "./sanitizer.js"; | ||
@@ -52,3 +52,3 @@ import Ticker from "./ticker.js"; | ||
onStart?: StartCallback; | ||
} & WebworkerOptions; | ||
} & WebworkerOptions & CheckOptions; | ||
export declare type Options = AppOptions & ObserverOptions & SanitizerOptions; | ||
@@ -66,3 +66,2 @@ export declare const DEFAULT_INGEST_POINT = "https://api.openreplay.com/ingest"; | ||
readonly sessionStorage: Storage; | ||
private gc; | ||
private readonly messages; | ||
@@ -69,0 +68,0 @@ private readonly observer; |
@@ -30,2 +30,3 @@ "use strict"; | ||
// } ?? maybe onStart is good | ||
// private gc?: NodeJS.Timer = undefined; | ||
this.messages = []; | ||
@@ -36,3 +37,3 @@ this.startCallbacks = []; | ||
this.activityState = ActivityState.NotActive; | ||
this.version = '3.5.16-beta.1'; // TODO: version compatability check inside each plugin. | ||
this.version = '3.5.16-beta.2'; // TODO: version compatability check inside each plugin. | ||
this.projectKey = projectKey; | ||
@@ -53,3 +54,3 @@ this.options = Object.assign({ | ||
sessionStorage: window.sessionStorage, | ||
maxMemorySize: 650 * 1e6, | ||
maxMemorySize: 550 * 1e6, | ||
memoryCheckInterval: 2 * 60 * 1000, | ||
@@ -59,3 +60,3 @@ }, options); | ||
this.sanitizer = new sanitizer_js_1.default(this, options); | ||
this.nodes = new nodes_js_1.default(this.options.node_id); | ||
this.nodes = new nodes_js_1.default(this.options.node_id, this.options.maxMemorySize, this.options.memoryCheckInterval); | ||
this.observer = new top_observer_js_1.default(this, options); | ||
@@ -152,2 +153,3 @@ this.ticker = new ticker_js_1.default(this); | ||
catch (e) { | ||
console.error(e); | ||
app._debug("safe_fn_call", e); | ||
@@ -326,12 +328,12 @@ // time: timestamp(), | ||
this.notify.log("OpenReplay tracking started."); | ||
// GC | ||
if (this.gc) { | ||
clearInterval(this.gc); | ||
} | ||
this.gc = setInterval(() => { | ||
// @ts-ignore | ||
if (window.performance.memory.usedJSHeapSize > this.options.maxMemorySize) { | ||
this.restart(); | ||
} | ||
}, this.options.memoryCheckInterval); | ||
// // GC | ||
// if (!this.gc) { | ||
// this.gc = setInterval(() => { | ||
// console.log('checking') | ||
// // @ts-ignore | ||
// if (window.performance.memory.usedJSHeapSize > this.options.maxMemorySize) { | ||
// this.restart(); | ||
// } | ||
// }, this.options.memoryCheckInterval) | ||
// } | ||
// get rid of onStart ? | ||
@@ -373,2 +375,3 @@ if (typeof this.options.onStart === 'function') { | ||
try { | ||
// this.gc && clearInterval(this.gc) | ||
this.sanitizer.clear(); | ||
@@ -375,0 +378,0 @@ this.observer.disconnect(); |
@@ -0,2 +1,7 @@ | ||
/// <reference types="node" resolution-mode="require"/> | ||
declare type NodeCallback = (node: Node, isStart: boolean) => void; | ||
export interface CheckOptions { | ||
maxMemorySize: number; | ||
memoryCheckInterval: number; | ||
} | ||
export default class Nodes { | ||
@@ -7,3 +12,4 @@ private readonly node_id; | ||
private readonly elementListeners; | ||
constructor(node_id: string); | ||
gc: NodeJS.Timer | undefined; | ||
constructor(node_id: string, maxMemorySize: CheckOptions["maxMemorySize"], memoryCheckInterval: CheckOptions["memoryCheckInterval"]); | ||
attachNodeCallback(nodeCallback: NodeCallback): void; | ||
@@ -13,2 +19,3 @@ attachElementListener(type: string, node: Element, elementListener: EventListener): void; | ||
unregisterNode(node: Node): number | undefined; | ||
cleanTree(): void; | ||
callNodeCallbacks(node: Node, isStart: boolean): void; | ||
@@ -15,0 +22,0 @@ getID(node: Node): number | undefined; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
class Nodes { | ||
constructor(node_id) { | ||
constructor(node_id, maxMemorySize, memoryCheckInterval) { | ||
this.node_id = node_id; | ||
@@ -9,2 +9,8 @@ this.nodes = []; | ||
this.elementListeners = new Map(); | ||
this.gc = setInterval(() => { | ||
// @ts-ignore should use settings object here | ||
if (window.performance.memory.usedJSHeapSize > maxMemorySize) { | ||
this.cleanTree(); | ||
} | ||
}, memoryCheckInterval); | ||
} | ||
@@ -51,8 +57,19 @@ attachNodeCallback(nodeCallback) { | ||
} | ||
// cleanTree() { | ||
// if (this.nodes.length > 10000) { | ||
// this.nodes = this.nodes.filter((n) => n !== undefined && document.contains(n)) | ||
// } | ||
// return; | ||
// } | ||
cleanTree() { | ||
// sadly we keep empty items in array here resulting in some memory still being used | ||
// but its still better than keeping dead nodes or undef elements | ||
// plus we keep our index positions for new/alive nodes | ||
// performance test: 3ms for 30k nodes with 17k dead ones | ||
for (let i = 0; i < this.nodes.length; i++) { | ||
const node = this.nodes[i]; | ||
if (node === undefined) { | ||
delete this.nodes[i]; | ||
continue; | ||
} | ||
if (!document.contains(node)) { | ||
this.unregisterNode(node); | ||
delete this.nodes[i]; | ||
} | ||
} | ||
} | ||
callNodeCallbacks(node, isStart) { | ||
@@ -76,4 +93,8 @@ this.nodeCallbacks.forEach((cb) => cb(node, isStart)); | ||
this.nodes.length = 0; | ||
if (this.gc) { | ||
clearInterval(this.gc); | ||
this.gc = undefined; | ||
} | ||
} | ||
} | ||
exports.default = Nodes; |
@@ -130,3 +130,3 @@ "use strict"; | ||
req.send(JSON.stringify({ | ||
trackerVersion: '3.5.16-beta.1', | ||
trackerVersion: '3.5.16-beta.2', | ||
projectKey: options.projectKey, | ||
@@ -133,0 +133,0 @@ doNotTrack, |
import type Message from "../common/messages.js"; | ||
import Nodes from "./nodes.js"; | ||
import Nodes, { CheckOptions } from "./nodes.js"; | ||
import Sanitizer from "./sanitizer.js"; | ||
@@ -52,3 +52,3 @@ import Ticker from "./ticker.js"; | ||
onStart?: StartCallback; | ||
} & WebworkerOptions; | ||
} & WebworkerOptions & CheckOptions; | ||
export declare type Options = AppOptions & ObserverOptions & SanitizerOptions; | ||
@@ -66,3 +66,2 @@ export declare const DEFAULT_INGEST_POINT = "https://api.openreplay.com/ingest"; | ||
readonly sessionStorage: Storage; | ||
private gc; | ||
private readonly messages; | ||
@@ -69,0 +68,0 @@ private readonly observer; |
@@ -27,2 +27,3 @@ import { Timestamp, Metadata, UserID } from "../common/messages.js"; | ||
// } ?? maybe onStart is good | ||
// private gc?: NodeJS.Timer = undefined; | ||
this.messages = []; | ||
@@ -33,3 +34,3 @@ this.startCallbacks = []; | ||
this.activityState = ActivityState.NotActive; | ||
this.version = '3.5.16-beta.1'; // TODO: version compatability check inside each plugin. | ||
this.version = '3.5.16-beta.2'; // TODO: version compatability check inside each plugin. | ||
this.projectKey = projectKey; | ||
@@ -50,3 +51,3 @@ this.options = Object.assign({ | ||
sessionStorage: window.sessionStorage, | ||
maxMemorySize: 650 * 1e6, | ||
maxMemorySize: 550 * 1e6, | ||
memoryCheckInterval: 2 * 60 * 1000, | ||
@@ -56,3 +57,3 @@ }, options); | ||
this.sanitizer = new Sanitizer(this, options); | ||
this.nodes = new Nodes(this.options.node_id); | ||
this.nodes = new Nodes(this.options.node_id, this.options.maxMemorySize, this.options.memoryCheckInterval); | ||
this.observer = new Observer(this, options); | ||
@@ -149,2 +150,3 @@ this.ticker = new Ticker(this); | ||
catch (e) { | ||
console.error(e); | ||
app._debug("safe_fn_call", e); | ||
@@ -323,12 +325,12 @@ // time: timestamp(), | ||
this.notify.log("OpenReplay tracking started."); | ||
// GC | ||
if (this.gc) { | ||
clearInterval(this.gc); | ||
} | ||
this.gc = setInterval(() => { | ||
// @ts-ignore | ||
if (window.performance.memory.usedJSHeapSize > this.options.maxMemorySize) { | ||
this.restart(); | ||
} | ||
}, this.options.memoryCheckInterval); | ||
// // GC | ||
// if (!this.gc) { | ||
// this.gc = setInterval(() => { | ||
// console.log('checking') | ||
// // @ts-ignore | ||
// if (window.performance.memory.usedJSHeapSize > this.options.maxMemorySize) { | ||
// this.restart(); | ||
// } | ||
// }, this.options.memoryCheckInterval) | ||
// } | ||
// get rid of onStart ? | ||
@@ -370,2 +372,3 @@ if (typeof this.options.onStart === 'function') { | ||
try { | ||
// this.gc && clearInterval(this.gc) | ||
this.sanitizer.clear(); | ||
@@ -372,0 +375,0 @@ this.observer.disconnect(); |
@@ -0,2 +1,7 @@ | ||
/// <reference types="node" resolution-mode="require"/> | ||
declare type NodeCallback = (node: Node, isStart: boolean) => void; | ||
export interface CheckOptions { | ||
maxMemorySize: number; | ||
memoryCheckInterval: number; | ||
} | ||
export default class Nodes { | ||
@@ -7,3 +12,4 @@ private readonly node_id; | ||
private readonly elementListeners; | ||
constructor(node_id: string); | ||
gc: NodeJS.Timer | undefined; | ||
constructor(node_id: string, maxMemorySize: CheckOptions["maxMemorySize"], memoryCheckInterval: CheckOptions["memoryCheckInterval"]); | ||
attachNodeCallback(nodeCallback: NodeCallback): void; | ||
@@ -13,2 +19,3 @@ attachElementListener(type: string, node: Element, elementListener: EventListener): void; | ||
unregisterNode(node: Node): number | undefined; | ||
cleanTree(): void; | ||
callNodeCallbacks(node: Node, isStart: boolean): void; | ||
@@ -15,0 +22,0 @@ getID(node: Node): number | undefined; |
export default class Nodes { | ||
constructor(node_id) { | ||
constructor(node_id, maxMemorySize, memoryCheckInterval) { | ||
this.node_id = node_id; | ||
@@ -7,2 +7,8 @@ this.nodes = []; | ||
this.elementListeners = new Map(); | ||
this.gc = setInterval(() => { | ||
// @ts-ignore should use settings object here | ||
if (window.performance.memory.usedJSHeapSize > maxMemorySize) { | ||
this.cleanTree(); | ||
} | ||
}, memoryCheckInterval); | ||
} | ||
@@ -49,8 +55,19 @@ attachNodeCallback(nodeCallback) { | ||
} | ||
// cleanTree() { | ||
// if (this.nodes.length > 10000) { | ||
// this.nodes = this.nodes.filter((n) => n !== undefined && document.contains(n)) | ||
// } | ||
// return; | ||
// } | ||
cleanTree() { | ||
// sadly we keep empty items in array here resulting in some memory still being used | ||
// but its still better than keeping dead nodes or undef elements | ||
// plus we keep our index positions for new/alive nodes | ||
// performance test: 3ms for 30k nodes with 17k dead ones | ||
for (let i = 0; i < this.nodes.length; i++) { | ||
const node = this.nodes[i]; | ||
if (node === undefined) { | ||
delete this.nodes[i]; | ||
continue; | ||
} | ||
if (!document.contains(node)) { | ||
this.unregisterNode(node); | ||
delete this.nodes[i]; | ||
} | ||
} | ||
} | ||
callNodeCallbacks(node, isStart) { | ||
@@ -74,3 +91,7 @@ this.nodeCallbacks.forEach((cb) => cb(node, isStart)); | ||
this.nodes.length = 0; | ||
if (this.gc) { | ||
clearInterval(this.gc); | ||
this.gc = undefined; | ||
} | ||
} | ||
} |
@@ -126,3 +126,3 @@ import App, { DEFAULT_INGEST_POINT } from "./app/index.js"; | ||
req.send(JSON.stringify({ | ||
trackerVersion: '3.5.16-beta.1', | ||
trackerVersion: '3.5.16-beta.2', | ||
projectKey: options.projectKey, | ||
@@ -129,0 +129,0 @@ doNotTrack, |
{ | ||
"name": "@openreplay/tracker", | ||
"description": "The OpenReplay tracker main package", | ||
"version": "3.5.16-beta.1", | ||
"version": "3.5.16-beta.2", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "logging", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
369748
9006