summaryrefslogtreecommitdiff
path: root/u/trace/metrics.ts
diff options
context:
space:
mode:
Diffstat (limited to 'u/trace/metrics.ts')
-rw-r--r--u/trace/metrics.ts229
1 files changed, 109 insertions, 120 deletions
diff --git a/u/trace/metrics.ts b/u/trace/metrics.ts
index 822fc38..2301afd 100644
--- a/u/trace/metrics.ts
+++ b/u/trace/metrics.ts
@@ -1,151 +1,140 @@
import {
- isObject,
- type ITrace,
- type ITraceWith,
- type Mapper,
- type SideEffect,
- type Supplier,
-} from "@emprespresso/pengueno";
+ isObject,
+ type ITrace,
+ type ITraceWith,
+ type Mapper,
+ type SideEffect,
+ type Supplier,
+} from '@emprespresso/pengueno';
export enum Unit {
- COUNT = "COUNT",
- MILLISECONDS = "MILLISECONDS",
+ COUNT = 'COUNT',
+ MILLISECONDS = 'MILLISECONDS',
}
export interface IMetric {
- readonly count: IEmittableMetric;
- readonly time: IEmittableMetric;
- readonly failure?: IMetric;
- readonly success?: IMetric;
- readonly warn?: IMetric;
- readonly children: Supplier<Array<IMetric>>;
-
- readonly _tag: "IMetric";
+ readonly count: IEmittableMetric;
+ readonly time: IEmittableMetric;
+ readonly failure: undefined | IMetric;
+ readonly success: undefined | IMetric;
+ readonly warn: undefined | IMetric;
+ readonly children: Supplier<Array<IMetric>>;
+
+ readonly _tag: 'IMetric';
}
-export const isIMetric = (t: unknown): t is IMetric =>
- isObject(t) && "_tag" in t && t._tag === "IMetric";
+export const isIMetric = (t: unknown): t is IMetric => isObject(t) && '_tag' in t && t._tag === 'IMetric';
export interface IEmittableMetric {
- readonly name: string;
- readonly unit: Unit;
- withValue: Mapper<number, MetricValue>;
+ readonly name: string;
+ readonly unit: Unit;
+ withValue: Mapper<number, MetricValue>;
}
export class EmittableMetric implements IEmittableMetric {
- constructor(
- public readonly name: string,
- public readonly unit: Unit,
- ) {}
-
- public withValue(value: number): MetricValue {
- return {
- name: this.name,
- unit: this.unit,
- emissionTimestamp: Date.now(),
- value,
- _tag: "MetricValue",
- };
- }
+ constructor(
+ public readonly name: string,
+ public readonly unit: Unit,
+ ) {}
+
+ public withValue(value: number): MetricValue {
+ return {
+ name: this.name,
+ unit: this.unit,
+ emissionTimestamp: Date.now(),
+ value,
+ _tag: 'MetricValue',
+ };
+ }
}
export class Metric implements IMetric {
- constructor(
- public readonly count: IEmittableMetric,
- public readonly time: IEmittableMetric,
- public readonly failure?: Metric,
- public readonly success?: Metric,
- public readonly warn?: Metric,
- public readonly _tag: "IMetric" = "IMetric",
- ) {}
-
- public children() {
- return [this.failure, this.success, this.warn].filter(
- (x) => x,
- ) as IMetric[];
- }
-
- static fromName(name: string, addChildren = true): Metric {
- return new Metric(
- new EmittableMetric(`${name}.count`, Unit.COUNT),
- new EmittableMetric(`${name}.elapsed`, Unit.MILLISECONDS),
- addChildren ? Metric.fromName(`${name}.failure`, false) : undefined,
- addChildren ? Metric.fromName(`${name}.success`, false) : undefined,
- addChildren ? Metric.fromName(`${name}.warn`, false) : undefined,
- );
- }
+ constructor(
+ public readonly count: IEmittableMetric,
+ public readonly time: IEmittableMetric,
+ public readonly failure: undefined | Metric = undefined,
+ public readonly success: undefined | Metric = undefined,
+ public readonly warn: undefined | Metric = undefined,
+ public readonly _tag: 'IMetric' = 'IMetric',
+ ) {}
+
+ public children() {
+ return [this.failure, this.success, this.warn].filter((x) => x) as IMetric[];
+ }
+
+ static fromName(name: string, addChildren = true): Metric {
+ return new Metric(
+ new EmittableMetric(`${name}.count`, Unit.COUNT),
+ new EmittableMetric(`${name}.elapsed`, Unit.MILLISECONDS),
+ addChildren ? Metric.fromName(`${name}.failure`, false) : undefined,
+ addChildren ? Metric.fromName(`${name}.success`, false) : undefined,
+ addChildren ? Metric.fromName(`${name}.warn`, false) : undefined,
+ );
+ }
}
export interface MetricValue {
- readonly name: string;
- readonly unit: Unit;
- readonly value: number;
- readonly emissionTimestamp: number;
- readonly _tag: "MetricValue";
+ readonly name: string;
+ readonly unit: Unit;
+ readonly value: number;
+ readonly emissionTimestamp: number;
+ readonly _tag: 'MetricValue';
}
-export const isMetricValue = (t: unknown): t is MetricValue =>
- isObject(t) && "_tag" in t && t._tag === "MetricValue";
+export const isMetricValue = (t: unknown): t is MetricValue => isObject(t) && '_tag' in t && t._tag === 'MetricValue';
-export const isMetricsTraceSupplier = (t: unknown): t is MetricsTraceSupplier =>
- isMetricValue(t) || isIMetric(t);
+export const isMetricsTraceSupplier = (t: unknown): t is MetricsTraceSupplier => isMetricValue(t) || isIMetric(t);
-export type MetricsTraceSupplier = ITraceWith<
- IMetric | MetricValue | undefined
->;
+export type MetricsTraceSupplier = ITraceWith<IMetric | MetricValue | undefined>;
type MetricTracingTuple = [IMetric, Date];
export class MetricsTrace implements ITrace<MetricsTraceSupplier> {
- constructor(
- private readonly metricConsumer: SideEffect<Array<MetricValue>>,
- private readonly tracing: Array<MetricTracingTuple> = [],
- private readonly flushed: Set<IMetric> = new Set(),
- ) {}
-
- public addTrace(trace: MetricsTraceSupplier) {
- if (!isIMetric(trace)) return this;
- return new MetricsTrace(this.metricConsumer)._nowTracing(trace);
- }
-
- public trace(metric: MetricsTraceSupplier) {
- if (typeof metric === "undefined" || typeof metric === "string")
- return this;
- if (isMetricValue(metric)) {
- this.metricConsumer([metric]);
- return this;
+ constructor(
+ private readonly metricConsumer: SideEffect<Array<MetricValue>>,
+ private readonly tracing: Array<MetricTracingTuple> = [],
+ private readonly flushed: Set<IMetric> = new Set(),
+ ) {}
+
+ public addTrace(trace: MetricsTraceSupplier) {
+ if (!isIMetric(trace)) return this;
+ return new MetricsTrace(this.metricConsumer)._nowTracing(trace);
}
- const foundMetricValues = this.tracing
- .flatMap(([tracing, startedTracing]) =>
- [tracing, ...tracing.children()]
- .filter((_tracing) => metric === _tracing)
- .flatMap((metric) => [
- this.addMetric(metric, startedTracing),
- this.addMetric(tracing, startedTracing),
- ]),
- )
- .flatMap((values) => values);
-
- if (foundMetricValues.length === 0) {
- return this._nowTracing(metric);
+ public trace(metric: MetricsTraceSupplier) {
+ if (typeof metric === 'undefined' || typeof metric === 'string') return this;
+ if (isMetricValue(metric)) {
+ this.metricConsumer([metric]);
+ return this;
+ }
+
+ const foundMetricValues = this.tracing
+ .flatMap(([tracing, startedTracing]) =>
+ [tracing, ...tracing.children()]
+ .filter((_tracing) => metric === _tracing)
+ .flatMap((metric) => [
+ this.addMetric(metric, startedTracing),
+ this.addMetric(tracing, startedTracing),
+ ]),
+ )
+ .flatMap((values) => values);
+
+ if (foundMetricValues.length === 0) {
+ return this._nowTracing(metric);
+ }
+
+ this.metricConsumer(foundMetricValues);
+ return this;
}
- this.metricConsumer(foundMetricValues);
- return this;
- }
+ private addMetric(metric: IMetric, startedTracing: Date): Array<MetricValue> {
+ if (this.flushed.has(metric)) {
+ return [];
+ }
- private addMetric(metric: IMetric, startedTracing: Date): Array<MetricValue> {
- if (this.flushed.has(metric)) {
- return [];
+ this.flushed.add(metric);
+ return [metric.count.withValue(1.0), metric.time.withValue(Date.now() - startedTracing.getTime())];
}
- this.flushed.add(metric);
- return [
- metric.count.withValue(1.0),
- metric.time.withValue(Date.now() - startedTracing.getTime()),
- ];
- }
-
- private _nowTracing(metric?: IMetric): MetricsTrace {
- if (!metric) return this;
- this.tracing.push([metric, new Date()]);
- return this;
- }
+ private _nowTracing(metric?: IMetric): MetricsTrace {
+ if (!metric) return this;
+ this.tracing.push([metric, new Date()]);
+ return this;
+ }
}