import {
Providers,
Props,
Tags,
joinFqn,
TimerWrapperFactory,
TimerWrapper,
PropEnabled,
Env,
} from '@btilford/ts-base-core';
export type PerformanceTimerOptions = {
performance?: Performance;
env?: Props;
tags?: Tags;
parent?: PerformanceTimer<any>;
startSuffix?: string;
endSuffix?: string;
measureSuffix?: string;
}
export class PerformanceTimer<T> extends TimerWrapper<T> {
readonly tags: Tags;
readonly fqn: string;
protected readonly options: PerformanceTimerOptions;
protected readonly perf: Performance;
protected readonly _enabled: PropEnabled;
constructor(readonly name: string, tags: Tags, options: PerformanceTimerOptions) {
super();
this.fqn = joinFqn(name, options.parent?.fqn);
this.perf = options.performance || performance;
this.options = { ...options };
this.tags = {
...options.tags,
...tags,
};
const env = options.env
|| options.parent?.options.env?.getConfig(this.name)
|| Providers.provide(Env).getConfig(this.fqn);
this._enabled = options.parent?._enabled.extend(this.name, 'true') ||
new PropEnabled(
{ name: this.name },
Providers.useOrProvide(Env, env).getConfig(this.name),
)
}
wrap(func: (...args: unknown[]) => T): (...args: unknown[]) => T {
const label = this.fqn;
const perf = this.perf;
const end = joinFqn(this.options.measureSuffix || this.options.endSuffix || 'end', label)
const start = joinFqn(this.options.startSuffix || 'start', label);
return function consoleTimerWrapper(...args: unknown[]): T {
perf.mark(start);
const result: T = func(...args);
try {
if (result instanceof Promise) {
result.then(result => {
perf.measure(end);
return result;
}).catch(err => {
perf.measure(end);
return err;
});
}
else {
perf.measure(end);
}
}
catch (error) {
perf.measure(end);
throw error;
}
return result;
};
}
}
export class PerformanceTimerFactory extends TimerWrapperFactory {
protected readonly options: PerformanceTimerOptions;
constructor(options: PerformanceTimerOptions) {
super();
this.options = { ...options };
}
asyncTimer<T>(name: string, tags: Tags = {}): TimerWrapper<Promise<T>> {
return new PerformanceTimer(name, tags, this.options);
}
timer<T>(name: string, tags: Tags = {}): TimerWrapper<T> {
return new PerformanceTimer(name, tags, this.options);
}
}
|