plugin API (#598)

* temp: plugin API

* fix a bug in the replay handler and rename some type names.

* update integration test

* improve plugin types and handle legacy log data

* use different naming in record and replay bundles

* delete unreferenced types

Co-authored-by: Lucky Feng <294889365@qq.com>
This commit is contained in:
yz-yu
2021-06-28 00:09:09 +08:00
committed by GitHub
parent 4e025c84ce
commit 5fc6c193fd
20 changed files with 753 additions and 579 deletions

View File

@@ -28,9 +28,6 @@ import {
canvasMutationData,
Mirror,
ElementState,
LogReplayConfig,
logData,
ReplayLogger,
} from '../types';
import {
createMirror,
@@ -54,11 +51,6 @@ const SKIP_TIME_INTERVAL = 5 * 1000;
const mitt = (mittProxy as any).default || mittProxy;
const REPLAY_CONSOLE_PREFIX = '[replayer]';
const ORIGINAL_ATTRIBUTE_NAME = '__rrweb_original__';
type PatchedConsoleLog = {
[ORIGINAL_ATTRIBUTE_NAME]: typeof console.log;
};
const defaultMouseTailConfig = {
duration: 500,
@@ -67,31 +59,6 @@ const defaultMouseTailConfig = {
strokeStyle: 'red',
} as const;
const defaultLogConfig: LogReplayConfig = {
level: [
'assert',
'clear',
'count',
'countReset',
'debug',
'dir',
'dirxml',
'error',
'group',
'groupCollapsed',
'groupEnd',
'info',
'log',
'table',
'time',
'timeEnd',
'timeLog',
'trace',
'warn',
],
replayLogger: undefined,
};
export class Replayer {
public wrapper: HTMLDivElement;
public iframe: HTMLIFrameElement;
@@ -149,12 +116,8 @@ export class Replayer {
UNSAFE_replayCanvas: false,
pauseAnimation: true,
mouseTail: defaultMouseTailConfig,
logConfig: defaultLogConfig,
};
this.config = Object.assign({}, defaultConfig, config);
if (!this.config.logConfig.replayLogger) {
this.config.logConfig.replayLogger = this.getConsoleLogger();
}
this.handleResize = this.handleResize.bind(this);
this.getCastFn = this.getCastFn.bind(this);
@@ -522,6 +485,11 @@ export class Replayer {
if (castFn) {
castFn();
}
for (const plugin of this.config.plugins || []) {
plugin.handler(event, isSync, { replayer: this });
}
this.service.send({ type: 'CAST_EVENT', payload: { event } });
// events are kept sorted by timestamp, check if this is the last event
@@ -1046,19 +1014,6 @@ export class Replayer {
}
break;
}
case IncrementalSource.Log: {
try {
const logData = e.data as logData;
const replayLogger = this.config.logConfig.replayLogger!;
if (typeof replayLogger[logData.level] === 'function') {
replayLogger[logData.level]!(logData);
}
} catch (error) {
if (this.config.showWarning) {
console.warn(error);
}
}
}
default:
}
}
@@ -1378,59 +1333,6 @@ export class Replayer {
}
}
/**
* format the trace data to a string
* @param data the log data
*/
private formatMessage(data: logData): string {
if (data.trace.length === 0) {
return '';
}
const stackPrefix = '\n\tat ';
let result = stackPrefix;
result += data.trace.join(stackPrefix);
return result;
}
/**
* generate a console log replayer which implement the interface ReplayLogger
*/
private getConsoleLogger(): ReplayLogger {
const replayLogger: ReplayLogger = {};
for (const level of this.config.logConfig.level!) {
if (level === 'trace') {
replayLogger[level] = (data: logData) => {
const logger = ((console.log as unknown) as PatchedConsoleLog)[
ORIGINAL_ATTRIBUTE_NAME
]
? ((console.log as unknown) as PatchedConsoleLog)[
ORIGINAL_ATTRIBUTE_NAME
]
: console.log;
logger(
...data.payload.map((s) => JSON.parse(s)),
this.formatMessage(data),
);
};
} else {
replayLogger[level] = (data: logData) => {
const logger = ((console[level] as unknown) as PatchedConsoleLog)[
ORIGINAL_ATTRIBUTE_NAME
]
? ((console[level] as unknown) as PatchedConsoleLog)[
ORIGINAL_ATTRIBUTE_NAME
]
: console[level];
logger(
...data.payload.map((s) => JSON.parse(s)),
this.formatMessage(data),
);
};
}
}
return replayLogger;
}
private legacy_resolveMissingNode(
map: missingNodeMap,
parent: Node,