hrc-debug
Version:
print debug info at server from client
174 lines (173 loc) • 6.21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const getValue = (value) => {
// NaN
if (Number.isNaN(value)) {
return 'NaN___hrc_NaN';
}
// Infinity / -Infinity
if ((value === Infinity) || (value === -Infinity)) {
return `${value.toString()}___hrc_Infinity`;
}
// undefined
if (value === undefined) {
return 'undefined___hrc_Undefined';
}
// 基本类型
if (['string', 'number', 'boolean'].includes(typeof value)) {
return value;
}
// bigint
if (typeof value === 'bigint') {
return `${value.toString()}n___hrc_BigInt`;
}
// symbol
if (typeof value === 'symbol') {
return `${value.toString()}___hrc_Symbol`;
}
// function
if (typeof value === 'function') {
return `${value.toString()}___hrc_Function`;
}
// null
if (value === null) {
return null;
}
// object
if (typeof value === 'object') {
const obj = {};
Object.entries(value).forEach(([k, v]) => {
obj[k] = getValue(v);
});
return obj;
}
return value;
};
class HRCDebug {
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// constructor
// -------------------------------------------------------------------------
constructor(options) {
this.options = options;
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// PROPS
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// log队列
this.queue = [];
// -------------------------------------------------------------------------
// 上报节流定时器
this.timer = null;
this.options = Object.assign(HRCDebug.defaultOptions, options);
this.consoleRewrite();
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// METHODS
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// 清洗数据
consoleMethodArgumentsGen(args) {
return args.map((item) => {
return getValue(item);
});
}
// -------------------------------------------------------------------------
// 是否添加到队列
checkAddToQueue(first) {
const matcher = this.options.filterMatcher;
if (matcher) {
return first === matcher;
}
return true;
}
// -------------------------------------------------------------------------
// 重写方法
consoleRewrite() {
// 全局的console
const gConsole = globalThis.console;
// 从映射表取并复写
Object
.entries(HRCDebug.nativeConsoleMethodsMap)
.forEach(([methodName, method]) => {
gConsole[methodName] = (...args) => {
if (this.checkAddToQueue(args[0])) {
// 丢进上报队列
this.queue.push({
method: methodName,
args: this.consoleMethodArgumentsGen(args),
createdAt: Date.now(),
sourceArgs: args,
});
this.appear();
}
// 在客户端输出
method.call(gConsole, ...args);
};
});
}
// -------------------------------------------------------------------------
// 上报
appear() {
if (this.timer)
return;
this.timer = setTimeout(() => {
let queue = this.queue;
if (!queue.length) {
this.timer = null;
return;
}
;
this.queue = [];
const options = this.options;
// 调用一下钩子
if (options.beforeEachQueuePost) {
const returns = options.beforeEachQueuePost(queue);
if (returns) {
queue = returns;
}
}
// 去掉引用
queue.forEach((item) => {
delete item.sourceArgs;
});
// 完了上报
options.appear({
console: queue,
prefix: !!options.filterMatcher,
}, options.server).then(() => {
this.timer = null;
this.appear();
});
}, 166);
}
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// STATIC
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// 重写的方法列表
HRCDebug.rewriteMethods = ['log', 'warn', 'error'];
// -------------------------------------------------------------------------
// 重写方法的原生方法映射表,保留原始方法
HRCDebug.nativeConsoleMethodsMap = HRCDebug
.rewriteMethods
.reduce((obj, methodName) => {
obj[methodName] = globalThis.console[methodName];
return obj;
}, {});
// -------------------------------------------------------------------------
// 默认配置项
HRCDebug.defaultOptions = {
server: '',
appear: () => Promise.resolve(),
filterMatcher: '',
};
exports.default = HRCDebug;