From ef51b25e4388cbdf3a27e23d9f1fa381ae20a5ad Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Fri, 16 May 2025 16:17:13 -0700 Subject: snapshot --- u/server/metrics.ts | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 u/server/metrics.ts (limited to 'u/server/metrics.ts') diff --git a/u/server/metrics.ts b/u/server/metrics.ts new file mode 100644 index 0000000..05df967 --- /dev/null +++ b/u/server/metrics.ts @@ -0,0 +1,112 @@ +import { + type BiMapper, + Either, + type IEither, + type ITraceable, + type Mapper, + type Supplier, +} from "@emprespresso/pengueno"; + +export enum Unit { + COUNT, + MILLISECONDS, +} + +export interface IMetric { + readonly metric: MetricT; + readonly unit: TUnit; + readonly value: number; + readonly emissionTimestamp: Date; +} + +export type BaseMetricT = string; +export interface CountMetric + extends IMetric { + readonly unit: Unit.COUNT; +} + +export interface TimeMetric + extends IMetric { + readonly unit: Unit.MILLISECONDS; +} + +export interface IMetricsData< + MetricT extends BaseMetricT, + Tracing, + TraceW, +> { + addCount: BiMapper>; + + stopwatch: BiMapper< + MetricT, + ITraceable, + ITraceable + >; + endStopwatch: Mapper< + ITraceable, + IEither> + >; + + flush: Supplier>>; +} + +export class TraceableMetricsData + implements IMetricsData { + private readonly timers: Map, Date> = new Map(); + private metricBuffer: Array> = []; + + private constructor() {} + + private addMetric( + metric: MetricT, + unit: TUnit, + value: number, + ): IMetric { + const _metric = { + metric, + unit, + value, + emissionTimestamp: new Date(), + }; + this.metricBuffer.push(_metric); + return _metric; + } + + public flush() { + const metrics = [...this.metricBuffer]; + this.metricBuffer = []; + return metrics; + } + + public addCount( + metric: MetricT, + count: number, + ): CountMetric { + return this.addMetric(metric, Unit.COUNT, count); + } + + public stopwatch(metric: MetricT, traceable: ITraceable) { + const timer = traceable.move(metric); + this.timers.set(timer, new Date()); + return timer; + } + + public endStopwatch( + stopwatch: ITraceable, + ): IEither> { + const now = new Date(); + if (this.timers.has(stopwatch)) { + const timer = this.timers.get(stopwatch)!; + const diff = now.getTime() - timer.getTime(); + this.timers.delete(stopwatch); + return Either.right>( + this.addMetric(stopwatch.item, Unit.MILLISECONDS, diff) as TimeMetric< + MetricT + >, + ); + } + return Either.left>( + new Error("cannot stop stopwatch before starting it"), + ); + } +} -- cgit v1.2.3-70-g09d2