feat (tracker): 3.2.4 - performance,selector options + beaconSizeLimit + debug_report_edp

This commit is contained in:
ShiKhu 2021-08-27 09:52:41 +03:00
parent c477c1e6c6
commit 810817575d
7 changed files with 74 additions and 22 deletions

View file

@ -1,7 +1,7 @@
{
"name": "@openreplay/tracker",
"description": "The OpenReplay tracker main package",
"version": "3.2.1",
"version": "3.2.4",
"keywords": [
"logging",
"replay"

View file

@ -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);
})
}
}

View file

@ -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;

View file

@ -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',

View file

@ -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;

View file

@ -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 }>;

View file

@ -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();