import { EmittableMetric, IMetric, IMetricTag, IResultMetric, Unit } from '.'; class _Tagged { protected constructor(public readonly _tag = IMetricTag) {} } export class Metric extends _Tagged implements IMetric { private static DELIM = '.'; protected constructor( public readonly name: string, public readonly parent: undefined | IMetric = undefined, public readonly count = new EmittableMetric(Metric.join(name, 'count'), Unit.COUNT), public readonly time = new EmittableMetric(Metric.join(name, 'time'), Unit.MILLISECONDS), ) { super(); } public child(_name: string): Metric { const childName = Metric.join(this.name, _name); return new Metric(childName, this); } public asResult() { return ResultMetric.from(this); } static join(...name: Array) { return name.join(Metric.DELIM); } static fromName(name: string): Metric { return new Metric(name); } } export class ResultMetric extends Metric implements IResultMetric { protected constructor( public readonly name: string, public readonly parent: undefined | IMetric = undefined, public readonly failure: IMetric, public readonly success: IMetric, public readonly warn: IMetric, ) { super(name, parent); } static from(metric: Metric) { const failure = metric.child('failure'); const success = metric.child('success'); const warn = metric.child('warn'); return new ResultMetric(metric.name, metric.parent, failure, success, warn); } }