feat(tracker): 3.4.1: uint encoding safety check, log fixes, debug logs
This commit is contained in:
parent
dfe60e5bf3
commit
0fcf9e425a
8 changed files with 50 additions and 29 deletions
2
tracker/tracker/package-lock.json
generated
2
tracker/tracker/package-lock.json
generated
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@openreplay/tracker",
|
||||
"version": "3.3.0",
|
||||
"version": "3.4.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@openreplay/tracker",
|
||||
"description": "The OpenReplay tracker main package",
|
||||
"version": "3.4.0",
|
||||
"version": "3.4.1",
|
||||
"keywords": [
|
||||
"logging",
|
||||
"replay"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { timestamp, log, warn } from '../utils';
|
||||
import { Timestamp, TechnicalInfo, PageClose } from '../../messages';
|
||||
import { Timestamp, PageClose } from '../../messages';
|
||||
import Message from '../../messages/message';
|
||||
import Nodes from './nodes';
|
||||
import Observer from './observer';
|
||||
|
|
@ -24,10 +24,11 @@ export type Options = {
|
|||
session_pageno_key: string;
|
||||
local_uuid_key: string;
|
||||
ingestPoint: string;
|
||||
resourceBaseHref: string, // resourceHref?
|
||||
resourceBaseHref: string | null, // resourceHref?
|
||||
//resourceURLRewriter: (url: string) => string | boolean,
|
||||
__is_snippet: boolean;
|
||||
__debug_report_edp: string | null;
|
||||
__debug_log: boolean;
|
||||
onStart?: (info: OnStartInfo) => void;
|
||||
} & ObserverOptions & WebworkerOptions;
|
||||
|
||||
|
|
@ -67,9 +68,10 @@ export default class App {
|
|||
session_pageno_key: '__openreplay_pageno',
|
||||
local_uuid_key: '__openreplay_uuid',
|
||||
ingestPoint: DEFAULT_INGEST_POINT,
|
||||
resourceBaseHref: '',
|
||||
resourceBaseHref: null,
|
||||
__is_snippet: false,
|
||||
__debug_report_edp: null,
|
||||
__debug_log: false,
|
||||
obscureTextEmails: true,
|
||||
obscureTextNumbers: false,
|
||||
captureIFrames: false,
|
||||
|
|
@ -90,10 +92,9 @@ export default class App {
|
|||
new Blob([`WEBWORKER_BODY`], { type: 'text/javascript' }),
|
||||
),
|
||||
);
|
||||
// this.worker.onerror = e => {
|
||||
// this.send(new TechnicalInfo("webworker_error", JSON.stringify(e)));
|
||||
// /* TODO: send report */
|
||||
// }
|
||||
this.worker.onerror = e => {
|
||||
this._debug("webworker_error", e)
|
||||
}
|
||||
let lastTs = timestamp();
|
||||
let fileno = 0;
|
||||
this.worker.onmessage = ({ data }: MessageEvent) => {
|
||||
|
|
@ -114,11 +115,11 @@ export default class App {
|
|||
this.attachEventListener(document, 'mouseleave', alertWorker, false, false);
|
||||
this.attachEventListener(document, 'visibilitychange', alertWorker, false);
|
||||
} catch (e) {
|
||||
this.sendDebugReport("worker_start", e);
|
||||
this._debug("worker_start", e);
|
||||
}
|
||||
}
|
||||
|
||||
private sendDebugReport(context: string, e: any) {
|
||||
private _debug(context: string, e: any) {
|
||||
if(this.options.__debug_report_edp !== null) {
|
||||
fetch(this.options.__debug_report_edp, {
|
||||
method: 'POST',
|
||||
|
|
@ -129,6 +130,9 @@ export default class App {
|
|||
})
|
||||
});
|
||||
}
|
||||
if(this.options.__debug_log) {
|
||||
warn("OpenReplay errror: ", context, e)
|
||||
}
|
||||
}
|
||||
|
||||
send(message: Message, urgent = false): void {
|
||||
|
|
@ -160,12 +164,11 @@ export default class App {
|
|||
try {
|
||||
fn.apply(this, args);
|
||||
} catch (e) {
|
||||
app.send(new TechnicalInfo("error", JSON.stringify({
|
||||
time: timestamp(),
|
||||
name: e.name,
|
||||
message: e.message,
|
||||
stack: e.stack
|
||||
})));
|
||||
this._debug("safe_fn_call", e)
|
||||
// time: timestamp(),
|
||||
// name: e.name,
|
||||
// message: e.message,
|
||||
// stack: e.stack
|
||||
}
|
||||
} as any // TODO: correct typing
|
||||
}
|
||||
|
|
@ -210,8 +213,10 @@ export default class App {
|
|||
return this.projectKey
|
||||
}
|
||||
getBaseHref(): string {
|
||||
if (this.options.resourceBaseHref) {
|
||||
if (typeof this.options.resourceBaseHref === 'string') {
|
||||
return this.options.resourceBaseHref
|
||||
} else if (typeof this.options.resourceBaseHref === 'object') {
|
||||
//switch between types
|
||||
}
|
||||
if (document.baseURI) {
|
||||
return document.baseURI
|
||||
|
|
@ -221,6 +226,12 @@ export default class App {
|
|||
?.getElementsByTagName("base")[0]
|
||||
?.getAttribute("href") || location.origin + location.pathname
|
||||
}
|
||||
resolveResourceURL(resourceURL: string): string {
|
||||
const base = new URL(this.getBaseHref())
|
||||
base.pathname += "/" + new URL(resourceURL).pathname
|
||||
base.pathname.replace(/\/+/g, "/")
|
||||
return base.toString()
|
||||
}
|
||||
|
||||
isServiceURL(url: string): boolean {
|
||||
return url.startsWith(this.options.ingestPoint)
|
||||
|
|
@ -310,7 +321,7 @@ export default class App {
|
|||
.catch(e => {
|
||||
this.stop();
|
||||
warn("OpenReplay was unable to start. ", e)
|
||||
this.sendDebugReport("session_start", e);
|
||||
this._debug("session_start", e);
|
||||
throw e;
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import Scroll from './modules/scroll';
|
|||
import Viewport from './modules/viewport';
|
||||
import Longtasks from './modules/longtasks';
|
||||
import CSSRules from './modules/cssrules';
|
||||
import { IN_BROWSER, deprecationWarn } from './utils';
|
||||
import { IN_BROWSER, deprecationWarn, DOCS_HOST } from './utils';
|
||||
|
||||
import { Options as AppOptions } from './app';
|
||||
import { Options as ConsoleOptions } from './modules/console';
|
||||
|
|
@ -41,13 +41,13 @@ const DOCS_SETUP = '/installation/setup-or';
|
|||
|
||||
function processOptions(obj: any): obj is Options {
|
||||
if (obj == null) {
|
||||
console.error(`OpenReplay: invalid options argument type. Please, check documentation on https://docs.openreplay.com${ DOCS_SETUP }`);
|
||||
console.error(`OpenReplay: invalid options argument type. Please, check documentation on ${DOCS_HOST}${DOCS_SETUP}`);
|
||||
return false;
|
||||
}
|
||||
if (typeof obj.projectKey !== 'string') {
|
||||
if (typeof obj.projectKey !== 'number') {
|
||||
if (typeof obj.projectID !== 'number') { // Back compatability
|
||||
console.error(`OpenReplay: projectKey is missing or wrong type (string is expected). Please, check https://docs.openreplay.com${ DOCS_SETUP } for more information.`)
|
||||
console.error(`OpenReplay: projectKey is missing or wrong type (string is expected). Please, check ${DOCS_HOST}${DOCS_SETUP} for more information.`)
|
||||
return false
|
||||
} else {
|
||||
obj.projectKey = obj.projectID.toString();
|
||||
|
|
@ -59,7 +59,7 @@ function processOptions(obj: any): obj is Options {
|
|||
}
|
||||
}
|
||||
if (typeof obj.sessionToken !== 'string' && obj.sessionToken != null) {
|
||||
console.warn(`OpenReplay: invalid options argument type. Please, check documentation on https://docs.openreplay.com${ DOCS_SETUP }`)
|
||||
console.warn(`OpenReplay: invalid options argument type. Please, check documentation on ${DOCS_HOST}${DOCS_SETUP}`)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -70,6 +70,10 @@ export default class API {
|
|||
if (!IN_BROWSER || !processOptions(options)) {
|
||||
return;
|
||||
}
|
||||
if ((window as any).__OPENREPLAY__) {
|
||||
console.error("OpenReplay: one tracker instance has been initialised already")
|
||||
return
|
||||
}
|
||||
if (!options.__DISABLE_SECURE_MODE && location.protocol !== 'https:') {
|
||||
console.error("OpenReplay: Your website must be publicly accessible and running on SSL in order for OpenReplay to properly capture and replay the user session. You can disable this check by setting `__DISABLE_SECURE_MODE` option to `true` if you are testing in localhost. Keep in mind, that asset files on a local machine are not available to the outside world. This might affect tracking if you use css files.")
|
||||
return;
|
||||
|
|
@ -99,9 +103,9 @@ export default class API {
|
|||
Performance(this.app, options);
|
||||
Scroll(this.app);
|
||||
Longtasks(this.app);
|
||||
(window as any).__OPENREPLAY__ = (window as any).__OPENREPLAY__ || this;
|
||||
(window as any).__OPENREPLAY__ = this;
|
||||
} else {
|
||||
console.log("OpenReplay: browser doesn't support API required for tracking.")
|
||||
console.log("OpenReplay: browser doesn't support API required for tracking or doNotTrack is set to 1.")
|
||||
const req = new XMLHttpRequest();
|
||||
const orig = options.ingestPoint || DEFAULT_INGEST_POINT;
|
||||
req.open("POST", orig + "/v1/web/not-started");
|
||||
|
|
@ -133,7 +137,7 @@ export default class API {
|
|||
|
||||
start(): void {
|
||||
if (!IN_BROWSER) {
|
||||
console.error(`OpenReplay: you are trying to start Tracker on a node.js environment. If you want to use OpenReplay with SSR, please, use componentDidMount or useEffect API for placing the \`tracker.start()\` line. Check documentation on https://docs.openreplay.com${ DOCS_SETUP }`)
|
||||
console.error(`OpenReplay: you are trying to start Tracker on a node.js environment. If you want to use OpenReplay with SSR, please, use componentDidMount or useEffect API for placing the \`tracker.start()\` line. Check documentation on ${DOCS_HOST}${DOCS_SETUP}`)
|
||||
return;
|
||||
}
|
||||
if (this.app === null) {
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ export default function (app: App, opts: Partial<Options>): void {
|
|||
|
||||
options.consoleMethods.forEach((method) => {
|
||||
if (consoleMethods.indexOf(method) === -1) {
|
||||
console.error(`Asayer: unsupported console method ${method}`);
|
||||
console.error(`OpenReplay: unsupported console method "${method}"`);
|
||||
return;
|
||||
}
|
||||
const fn = (console as any)[method];
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ export const IN_BROWSER = !(typeof window === "undefined");
|
|||
export const log = console.log
|
||||
export const warn = console.warn
|
||||
|
||||
const DOCS_HOST = 'https://docs.openreplay.com';
|
||||
export const DOCS_HOST = 'https://docs.openreplay.com';
|
||||
|
||||
const warnedFeatures: { [key: string]: boolean; } = {};
|
||||
export function deprecationWarn(nameOfFeature: string, useInstead: string, docsPath: string = "/"): void {
|
||||
if (warnedFeatures[ nameOfFeature ]) {
|
||||
|
|
@ -56,3 +57,4 @@ export function hasOpenreplayAttribute(e: Element, name: string): boolean {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@ export default class Writer {
|
|||
return this.offset <= this.size;
|
||||
}
|
||||
uint(value: number): boolean {
|
||||
if (value < 0 || value > Number.MAX_SAFE_INTEGER) {
|
||||
value = 0
|
||||
}
|
||||
while (value >= 0x80) {
|
||||
this.data[this.offset++] = value % 0x100 | 0x80;
|
||||
value = Math.floor(value / 128);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ function sendBatch(batch: Uint8Array):void {
|
|||
if (this.status >= 400) { // TODO: test workflow. After 400+ it calls /start for some reason
|
||||
reset();
|
||||
sendQueue.length = 0;
|
||||
if (this.status === 403) { // Unauthorised (Token expired)
|
||||
if (this.status === 401) { // Unauthorised (Token expired)
|
||||
self.postMessage("restart")
|
||||
return
|
||||
}
|
||||
|
|
@ -74,6 +74,7 @@ function sendBatch(batch: Uint8Array):void {
|
|||
attemptsCount++;
|
||||
setTimeout(() => sendBatch(batch), ATTEMPT_TIMEOUT);
|
||||
}
|
||||
// TODO: handle offline exception
|
||||
req.send(batch.buffer);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue