class Trace {
private static readonly _None = new class extends Trace {
constructor() { super(-1, null); }
stop() { }
branch() { return this; }
};
static traceInvocation(ctor: any): Trace {
return !_enableTracing ? Trace._None : new Trace(TraceType.Invocation, ctor.name || (ctor.toString() as string).substring(0, 42).replace(/\n/g, ''));
}
static traceCreation(ctor: any): Trace {
return !_enableTracing ? Trace._None : new Trace(TraceType.Creation, ctor.name);
}
private static _totals: number = 0;
private readonly _start: number = Date.now();
private readonly _dep: [ServiceIdentifier<any>, boolean, Trace?][] = [];
private constructor(
readonly type: TraceType,
readonly name: string | null
) { }
branch(id: ServiceIdentifier<any>, first: boolean): Trace {
let child = new Trace(TraceType.Branch, id.toString());
this._dep.push([id, first, child]);
return child;
}
stop() {
let dur = Date.now() - this._start;
Trace._totals += dur;
let causedCreation = false;
function printChild(n: number, trace: Trace) {
let res: string[] = [];
let prefix = new Array(n + 1).join('\t');
for (const [id, first, child] of trace._dep) {
if (first && child) {
causedCreation = true;
res.push(`${prefix}CREATES -> ${id}`);
let nested = printChild(n + 1, child);
if (nested) {
res.push(nested);
}
} else {
res.push(`${prefix}uses -> ${id}`);
}
}
return res.join('\n');
}
let lines = [
`${this.type === TraceType.Creation ? 'CREATE' : 'CALL'} ${this.name}`,
`${printChild(1, this)}`,
`DONE, took ${dur.toFixed(2)}ms (grand total ${Trace._totals.toFixed(2)}ms)`
];
if (dur > 2 || causedCreation) {
console.log(lines.join('\n'));
}
}
}