miniprogram-logger
Version:
It is used to log and gather statistics of users' behavior.
119 lines (107 loc) • 3.48 kB
text/typescript
/// <reference lib="es2015"/>
import { ITimer } from "./ITimer";
import { Reporter, logTransformFunction, BasicLogObject } from "../common/reporter";
export interface PerformanceObject extends BasicLogObject {
/**
* 操作
*/
action?: string;
/**
* 时间
*/
duration?: number;
}
export class ReportAnalytics<
T extends PerformanceObject,
TValues extends T[keyof T][],
TKeys extends (keyof T)[] = (keyof T)[]
> extends Reporter<T, TValues, TKeys> implements ITimer {
private Id = 0;
private readonly Stopwatch = new Map<number | string, [number, Partial<T>]>();
constructor(tableName: string, fields?: TKeys, context?: Partial<T>) {
super(tableName, fields || (["action", "duration"] as TKeys), context);
this.TransformFunction = logTransformFunction;
}
/**
* 快速记录性能日志
* @param action 操作,
* @param duration 耗时单位毫秒
* @param context 其它数据
*/
public log(action: string, duration: number, ...args: RemoveFisrt2<TValues>): void;
/**
* 快速记录性能日志
* @param data PerformanceParam
*/
public log(data: T): void;
public log(): void {
//@ts-ignore
this.report.apply(this, arguments);
}
/**
*
* @param label - 唯一标签,结束时使用同样标签,
* @param context - 记录上下文信息,如果未设置action则使用label作为action
*/
public time(label: string, context?: Partial<T>): void {
this.Stopwatch.set(label, [Date.now(), Object.assign({ [this.Fields[0]]: arguments[0] }, context)]);
}
/**
*
* @param label - 唯一标签,与开始对应
* @param context - 记录上下文信息,如果未设置action则使用label作为action
*/
public timeEnd(label: string, context?: Partial<T>): void {
if (!this.end(label as any, context)) {
//@ts-ignore
console.error("timer label not found", label);
}
}
/**
* 开始计时
* @param action
* @param context
* @returns 返回计时ID
*/
public start(action: string, context?: Partial<T>): number;
public start(data: T): number;
public start(): number {
if (arguments.length === 1 && typeof arguments[0] === "object") {
//对象参数
this.Stopwatch.set(this.Id, [Date.now(), arguments[0]]);
} else {
//多参数
this.Stopwatch.set(this.Id, [
Date.now(),
Object.assign(arguments[1] || {}, { [this.Fields[0]]: arguments[0] }),
]);
}
return this.Id++;
}
/**
* 完成计时,并清除计时ID
* @param id
* @param context
*/
public end(id: number, context?: Partial<T>): boolean {
const info = this.Stopwatch.get(id);
if (!info) {
return false;
}
const [start, data] = info;
Object.assign(data, context, { [this.Fields[1]]: Date.now() - start });
this.report(data as T);
return this.remove(id);
}
/**
* 清除计时
* @param id
* @returns 不存在返回false
*/
public remove(id: number | string): boolean {
return this.Stopwatch.delete(id);
}
}
type RemoveFisrt2<T extends any[]> = ((...args: T) => void) extends ((a: any, b: any, ...rest: infer Rest) => void)
? Rest
: never;