feat (tracker): 3.2.4 - performance,selector options + beaconSizeLimit + debug_report_edp
This commit is contained in:
parent
c477c1e6c6
commit
810817575d
7 changed files with 74 additions and 22 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@openreplay/tracker",
|
||||
"description": "The OpenReplay tracker main package",
|
||||
"version": "3.2.1",
|
||||
"version": "3.2.4",
|
||||
"keywords": [
|
||||
"logging",
|
||||
"replay"
|
||||
|
|
|
|||
|
|
@ -19,13 +19,16 @@ export type Options = {
|
|||
local_uuid_key: string;
|
||||
ingestPoint: string;
|
||||
__is_snippet: boolean;
|
||||
__debug_report_edp: string | null;
|
||||
onStart?: (info: { sessionID: string, sessionToken: string, userUUID: string }) => void;
|
||||
} & ObserverOptions & WebworkerOptions;
|
||||
|
||||
type Callback = () => void;
|
||||
type CommitCallback = (messages: Array<Message>) => void;
|
||||
|
||||
export const DEFAULT_INGEST_POINT = 'https://ingest.openreplay.com';
|
||||
|
||||
// TODO: use backendHost only
|
||||
export const DEFAULT_INGEST_POINT = 'https://api.openreplay.com/ingest';
|
||||
|
||||
export default class App {
|
||||
readonly nodes: Nodes;
|
||||
|
|
@ -57,6 +60,7 @@ export default class App {
|
|||
local_uuid_key: '__openreplay_uuid',
|
||||
ingestPoint: DEFAULT_INGEST_POINT,
|
||||
__is_snippet: false,
|
||||
__debug_report_edp: null,
|
||||
obscureTextEmails: true,
|
||||
obscureTextNumbers: false,
|
||||
},
|
||||
|
|
@ -99,8 +103,23 @@ export default class App {
|
|||
this.attachEventListener(window, 'beforeunload', alertWorker, false);
|
||||
this.attachEventListener(document, 'mouseleave', alertWorker, false, false);
|
||||
this.attachEventListener(document, 'visibilitychange', alertWorker, false);
|
||||
} catch (e) { /* TODO: send report */}
|
||||
} catch (e) {
|
||||
this.sendDebugReport("worker_start", e);
|
||||
}
|
||||
}
|
||||
|
||||
private sendDebugReport(context: string, e: any) {
|
||||
if(this.options.__debug_report_edp !== null) {
|
||||
fetch(this.options.__debug_report_edp, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
context,
|
||||
error: `${e}`
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
send(message: Message, urgent = false): void {
|
||||
if (!this.isActive) {
|
||||
return;
|
||||
|
|
@ -230,14 +249,17 @@ export default class App {
|
|||
if (r.status === 200) {
|
||||
return r.json()
|
||||
} else { // TODO: handle canceling && 403
|
||||
throw new Error("Server error");
|
||||
return r.text().then(text => {
|
||||
throw new Error(`Server error: ${r.status}. ${text}`);
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(r => {
|
||||
const { token, userUUID, sessionID } = r;
|
||||
const { token, userUUID, sessionID, beaconSizeLimit } = r;
|
||||
if (typeof token !== 'string' ||
|
||||
typeof userUUID !== 'string') {
|
||||
throw new Error("Incorrect server response");
|
||||
typeof userUUID !== 'string' ||
|
||||
(typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined')) {
|
||||
throw new Error(`Incorrect server response: ${ JSON.stringify(r) }`);
|
||||
}
|
||||
sessionStorage.setItem(this.options.session_token_key, token);
|
||||
localStorage.setItem(this.options.local_uuid_key, userUUID);
|
||||
|
|
@ -247,7 +269,7 @@ export default class App {
|
|||
if (!this.worker) {
|
||||
throw new Error("Stranger things: no worker found after start request");
|
||||
}
|
||||
this.worker.postMessage({ token });
|
||||
this.worker.postMessage({ token, beaconSizeLimit });
|
||||
this.startCallbacks.forEach((cb) => cb());
|
||||
this.observer.observe();
|
||||
this.ticker.start();
|
||||
|
|
@ -259,7 +281,7 @@ export default class App {
|
|||
})
|
||||
.catch(e => {
|
||||
this.stop();
|
||||
/* TODO: send report */
|
||||
this.sendDebugReport("session_start", e);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,12 +20,14 @@ import CSSRules from './modules/cssrules';
|
|||
import { IN_BROWSER, deprecationWarn } from './utils';
|
||||
|
||||
import { Options as AppOptions } from './app';
|
||||
import { Options as ExceptionOptions } from './modules/exception';
|
||||
import { Options as ConsoleOptions } from './modules/console';
|
||||
import { Options as ExceptionOptions } from './modules/exception';
|
||||
import { Options as InputOptions } from './modules/input';
|
||||
import { Options as MouseOptions } from './modules/mouse';
|
||||
import { Options as PerformanceOptions } from './modules/performance';
|
||||
import { Options as TimingOptions } from './modules/timing';
|
||||
export type Options = Partial<
|
||||
AppOptions & ConsoleOptions & ExceptionOptions & InputOptions & TimingOptions
|
||||
AppOptions & ConsoleOptions & ExceptionOptions & InputOptions & MouseOptions & PerformanceOptions & TimingOptions
|
||||
> & {
|
||||
projectID?: number; // For the back compatibility only (deprecated)
|
||||
projectKey: string;
|
||||
|
|
@ -92,9 +94,9 @@ export default class API {
|
|||
Exception(this.app, options);
|
||||
Img(this.app);
|
||||
Input(this.app, options);
|
||||
Mouse(this.app);
|
||||
Mouse(this.app, options);
|
||||
Timing(this.app, options);
|
||||
Performance(this.app);
|
||||
Performance(this.app, options);
|
||||
Scroll(this.app);
|
||||
Longtasks(this.app);
|
||||
(window as any).__OPENREPLAY__ = (window as any).__OPENREPLAY__ || this;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
import type { Options as FinderOptions } from '../vendors/finder/finder';
|
||||
import { finder } from '../vendors/finder/finder';
|
||||
import { normSpaces, hasOpenreplayAttribute, getLabelAttribute } from '../utils';
|
||||
import App from '../app';
|
||||
import { MouseMove, MouseClick } from '../../messages';
|
||||
import { getInputLabel } from './input';
|
||||
|
||||
const selectorMap: {[id:number]: string} = {};
|
||||
function getSelector(id: number, target: Element): string {
|
||||
return selectorMap[id] = selectorMap[id] || finder(target);
|
||||
}
|
||||
|
||||
function getTarget(target: EventTarget | null): Element | null {
|
||||
if (target instanceof Element) {
|
||||
return _getTarget(target);
|
||||
|
|
@ -76,7 +72,18 @@ function getTargetLabel(target: Element): string {
|
|||
return '';
|
||||
}
|
||||
|
||||
export default function (app: App): void {
|
||||
export interface Options {
|
||||
selectorFinder: boolean | FinderOptions;
|
||||
}
|
||||
|
||||
export default function (app: App, opts: Partial<Options>): void {
|
||||
const options: Options = Object.assign(
|
||||
{
|
||||
selectorFinder: true,
|
||||
},
|
||||
opts,
|
||||
);
|
||||
|
||||
let mousePositionX = -1;
|
||||
let mousePositionY = -1;
|
||||
let mousePositionChanged = false;
|
||||
|
|
@ -97,6 +104,13 @@ export default function (app: App): void {
|
|||
}
|
||||
};
|
||||
|
||||
const selectorMap: {[id:number]: string} = {};
|
||||
function getSelector(id: number, target: Element): string {
|
||||
if (options.selectorFinder === false) { return '' }
|
||||
return selectorMap[id] = selectorMap[id] ||
|
||||
finder(target, options.selectorFinder === true ? undefined : options.selectorFinder);
|
||||
}
|
||||
|
||||
app.attachEventListener(
|
||||
<HTMLElement>document.documentElement,
|
||||
'mouseover',
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ type Perf = {
|
|||
}
|
||||
}
|
||||
|
||||
const perf: Perf = IN_BROWSER && 'memory' in performance // works in Chrome only
|
||||
const perf: Perf = IN_BROWSER && 'performance' in window && 'memory' in performance // works in Chrome only
|
||||
? performance as any
|
||||
: { memory: {} }
|
||||
|
||||
|
|
@ -19,7 +19,19 @@ const perf: Perf = IN_BROWSER && 'memory' in performance // works in Chrome only
|
|||
export const deviceMemory = IN_BROWSER ? ((navigator as any).deviceMemory || 0) * 1024 : 0;
|
||||
export const jsHeapSizeLimit = perf.memory.jsHeapSizeLimit || 0;
|
||||
|
||||
export default function (app: App): void {
|
||||
export interface Options {
|
||||
capturePerformance: boolean;
|
||||
}
|
||||
|
||||
export default function (app: App, opts: Partial<Options>): void {
|
||||
const options: Options = Object.assign(
|
||||
{
|
||||
capturePerformance: true,
|
||||
},
|
||||
opts,
|
||||
);
|
||||
if (!options.capturePerformance) { return; }
|
||||
|
||||
let frames: number | undefined;
|
||||
let ticks: number | undefined;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ type Settings = {
|
|||
pageNo?: number;
|
||||
startTimestamp?: number;
|
||||
timeAdjustment?: number;
|
||||
beaconSizeLimit?: number;
|
||||
} & Partial<Options>;
|
||||
|
||||
export type WorkerMessageData = null | "stop" | Settings | Array<{ _id: number }>;
|
||||
|
|
@ -6,7 +6,7 @@ import type { WorkerMessageData } from '../messages/webworker';
|
|||
|
||||
|
||||
const SEND_INTERVAL = 20 * 1000;
|
||||
const BEACON_SIZE_LIMIT = 1e6 // Limit is set in the backend/services/http
|
||||
let BEACON_SIZE_LIMIT = 1e6 // Limit is set in the backend/services/http
|
||||
let beaconSize = 4 * 1e5; // Default 400kB
|
||||
|
||||
|
||||
|
|
@ -123,6 +123,7 @@ self.onmessage = ({ data }: MessageEvent<WorkerMessageData>) => {
|
|||
timeAdjustment = data.timeAdjustment || timeAdjustment;
|
||||
MAX_ATTEMPTS_COUNT = data.connAttemptCount || MAX_ATTEMPTS_COUNT;
|
||||
ATTEMPT_TIMEOUT = data.connAttemptGap || ATTEMPT_TIMEOUT;
|
||||
BEACON_SIZE_LIMIT = data.beaconSizeLimit || BEACON_SIZE_LIMIT;
|
||||
beaconSize = Math.min(BEACON_SIZE_LIMIT, data.beaconSize || beaconSize);
|
||||
if (writer.isEmpty()) {
|
||||
writeBatchMeta();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue