diff options
author | Elizabeth Hunt <me@liz.coffee> | 2025-06-20 14:53:38 -0700 |
---|---|---|
committer | Elizabeth Hunt <me@liz.coffee> | 2025-06-20 14:53:38 -0700 |
commit | d4791f3d357634daf506fb8f91cc5332a794c421 (patch) | |
tree | 1bb01d2d4d8fa74d83bb6f99f2c8aa4146ca2d11 /u/trace | |
parent | d7e8d31c94cd713a2f4cf799e20e993acc69e361 (diff) | |
download | ci-d4791f3d357634daf506fb8f91cc5332a794c421.tar.gz ci-d4791f3d357634daf506fb8f91cc5332a794c421.zip |
Move to nodejs
Diffstat (limited to 'u/trace')
-rw-r--r-- | u/trace/index.ts | 5 | ||||
-rw-r--r-- | u/trace/itrace.ts | 120 | ||||
-rw-r--r-- | u/trace/logger.ts | 169 | ||||
-rw-r--r-- | u/trace/metrics.ts | 229 | ||||
-rw-r--r-- | u/trace/mod.ts | 5 | ||||
-rw-r--r-- | u/trace/trace.ts | 117 | ||||
-rw-r--r-- | u/trace/util.ts | 76 |
7 files changed, 328 insertions, 393 deletions
diff --git a/u/trace/index.ts b/u/trace/index.ts new file mode 100644 index 0000000..18da87a --- /dev/null +++ b/u/trace/index.ts @@ -0,0 +1,5 @@ +export * from './itrace.js'; +export * from './util.js'; +export * from './logger.js'; +export * from './metrics.js'; +export * from './trace.js'; diff --git a/u/trace/itrace.ts b/u/trace/itrace.ts index fcfbe32..8cf123a 100644 --- a/u/trace/itrace.ts +++ b/u/trace/itrace.ts @@ -1,90 +1,72 @@ -import type { Mapper, SideEffect, Supplier } from "@emprespresso/pengueno"; +import type { Mapper, SideEffect, Supplier } from '@emprespresso/pengueno'; // the "thing" every Trace writer must "trace()" type BaseTraceWith = string; export type ITraceWith<T> = BaseTraceWith | T; export interface ITrace<TraceWith> { - addTrace: Mapper<ITraceWith<TraceWith>, ITrace<TraceWith>>; - trace: SideEffect<ITraceWith<TraceWith>>; + addTrace: Mapper<ITraceWith<TraceWith>, ITrace<TraceWith>>; + trace: SideEffect<ITraceWith<TraceWith>>; } export type ITraceableTuple<T, TraceWith> = [T, BaseTraceWith | TraceWith]; -export type ITraceableMapper<T, _T, TraceWith, W = ITraceable<T, TraceWith>> = ( - w: W, -) => _T; +export type ITraceableMapper<T, _T, TraceWith, W = ITraceable<T, TraceWith>> = (w: W) => _T; export interface ITraceable<T, Trace = BaseTraceWith> { - readonly trace: ITrace<Trace>; - get: Supplier<T>; - move: <_T>(t: _T) => ITraceable<_T, Trace>; - map: <_T>(mapper: ITraceableMapper<T, _T, Trace>) => ITraceable<_T, Trace>; - bimap: <_T>( - mapper: ITraceableMapper< - T, - ITraceableTuple<_T, Array<Trace> | Trace>, - Trace - >, - ) => ITraceable<_T, Trace>; - peek: (peek: ITraceableMapper<T, void, Trace>) => ITraceable<T, Trace>; - flatMap: <_T>( - mapper: ITraceableMapper<T, ITraceable<_T, Trace>, Trace>, - ) => ITraceable<_T, Trace>; - flatMapAsync<_T>( - mapper: ITraceableMapper<T, Promise<ITraceable<_T, Trace>>, Trace>, - ): ITraceable<Promise<_T>, Trace>; + readonly trace: ITrace<Trace>; + get: Supplier<T>; + move: <_T>(t: _T) => ITraceable<_T, Trace>; + map: <_T>(mapper: ITraceableMapper<T, _T, Trace>) => ITraceable<_T, Trace>; + bimap: <_T>(mapper: ITraceableMapper<T, ITraceableTuple<_T, Array<Trace> | Trace>, Trace>) => ITraceable<_T, Trace>; + peek: (peek: ITraceableMapper<T, void, Trace>) => ITraceable<T, Trace>; + flatMap: <_T>(mapper: ITraceableMapper<T, ITraceable<_T, Trace>, Trace>) => ITraceable<_T, Trace>; + flatMapAsync<_T>( + mapper: ITraceableMapper<T, Promise<ITraceable<_T, Trace>>, Trace>, + ): ITraceable<Promise<_T>, Trace>; } export class TraceableImpl<T, TraceWith> implements ITraceable<T, TraceWith> { - protected constructor( - private readonly item: T, - public readonly trace: ITrace<TraceWith>, - ) {} + protected constructor( + private readonly item: T, + public readonly trace: ITrace<TraceWith>, + ) {} - public map<_T>(mapper: ITraceableMapper<T, _T, TraceWith>) { - const result = mapper(this); - return new TraceableImpl(result, this.trace); - } + public map<_T>(mapper: ITraceableMapper<T, _T, TraceWith>) { + const result = mapper(this); + return new TraceableImpl(result, this.trace); + } - public flatMap<_T>( - mapper: ITraceableMapper<T, ITraceable<_T, TraceWith>, TraceWith>, - ): ITraceable<_T, TraceWith> { - return mapper(this); - } + public flatMap<_T>(mapper: ITraceableMapper<T, ITraceable<_T, TraceWith>, TraceWith>): ITraceable<_T, TraceWith> { + return mapper(this); + } - public flatMapAsync<_T>( - mapper: ITraceableMapper<T, Promise<ITraceable<_T, TraceWith>>, TraceWith>, - ): ITraceable<Promise<_T>, TraceWith> { - return new TraceableImpl( - mapper(this).then((t) => t.get()), - this.trace, - ); - } + public flatMapAsync<_T>( + mapper: ITraceableMapper<T, Promise<ITraceable<_T, TraceWith>>, TraceWith>, + ): ITraceable<Promise<_T>, TraceWith> { + return new TraceableImpl( + mapper(this).then((t) => t.get()), + this.trace, + ); + } - public peek(peek: ITraceableMapper<T, void, TraceWith>) { - peek(this); - return this; - } + public peek(peek: ITraceableMapper<T, void, TraceWith>) { + peek(this); + return this; + } - public move<_T>(t: _T): ITraceable<_T, TraceWith> { - return this.map(() => t); - } + public move<_T>(t: _T): ITraceable<_T, TraceWith> { + return this.map(() => t); + } - public bimap<_T>( - mapper: ITraceableMapper< - T, - ITraceableTuple<_T, Array<TraceWith> | TraceWith>, - TraceWith - >, - ) { - const [item, trace] = mapper(this); - const traces = Array.isArray(trace) ? trace : [trace]; - return new TraceableImpl( - item, - traces.reduce((trace, _trace) => trace.addTrace(_trace), this.trace), - ); - } + public bimap<_T>(mapper: ITraceableMapper<T, ITraceableTuple<_T, Array<TraceWith> | TraceWith>, TraceWith>) { + const [item, trace] = mapper(this); + const traces = Array.isArray(trace) ? trace : [trace]; + return new TraceableImpl( + item, + traces.reduce((trace, _trace) => trace.addTrace(_trace), this.trace), + ); + } - public get() { - return this.item; - } + public get() { + return this.item; + } } diff --git a/u/trace/logger.ts b/u/trace/logger.ts index d8392eb..91432fe 100644 --- a/u/trace/logger.ts +++ b/u/trace/logger.ts @@ -1,112 +1,95 @@ -import { - isDebug, - type ITrace, - type ITraceWith, - type Supplier, -} from "@emprespresso/pengueno"; +import { isDebug, type ITrace, type ITraceWith, type Supplier } from '@emprespresso/pengueno'; export type LogTraceSupplier = ITraceWith<Supplier<string> | Error>; const defaultTrace = () => `TimeStamp = ${new Date().toISOString()}`; export class LogTrace implements ITrace<LogTraceSupplier> { - constructor( - private readonly logger: ILogger = new LoggerImpl(), - private readonly traces: Array<LogTraceSupplier> = [defaultTrace], - private readonly defaultLevel: LogLevel = LogLevel.INFO, - private readonly allowedLevels: Supplier< - Array<LogLevel> - > = defaultAllowedLevels, - ) {} + constructor( + private readonly logger: ILogger = new LoggerImpl(), + private readonly traces: Array<LogTraceSupplier> = [defaultTrace], + private readonly defaultLevel: LogLevel = LogLevel.INFO, + private readonly allowedLevels: Supplier<Array<LogLevel>> = defaultAllowedLevels, + ) {} - public addTrace(trace: LogTraceSupplier): ITrace<LogTraceSupplier> { - return new LogTrace( - this.logger, - this.traces.concat(trace), - this.defaultLevel, - this.allowedLevels, - ); - } + public addTrace(trace: LogTraceSupplier): ITrace<LogTraceSupplier> { + return new LogTrace(this.logger, this.traces.concat(trace), this.defaultLevel, this.allowedLevels); + } - public trace(trace: LogTraceSupplier) { - const { traces, level: _level } = this.foldTraces( - this.traces.concat(trace), - ); - if (!this.allowedLevels().includes(_level)) return; + public trace(trace: LogTraceSupplier) { + const { traces, level: _level } = this.foldTraces(this.traces.concat(trace)); + if (!this.allowedLevels().includes(_level)) return; - const level = _level === LogLevel.UNKNOWN ? this.defaultLevel : _level; - this.logger.log(level, ...traces); - } + const level = _level === LogLevel.UNKNOWN ? this.defaultLevel : _level; + this.logger.log(level, ...traces); + } - private foldTraces(_traces: Array<LogTraceSupplier>) { - const _logTraces = _traces.map((trace) => - typeof trace === "function" ? trace() : trace, - ); - const _level = _logTraces - .filter((trace) => isLogLevel(trace)) - .reduce((acc, level) => Math.max(logLevelOrder.indexOf(level), acc), -1); - const level = logLevelOrder[_level] ?? LogLevel.UNKNOWN; + private foldTraces(_traces: Array<LogTraceSupplier>) { + const _logTraces = _traces.map((trace) => (typeof trace === 'function' ? trace() : trace)); + const _level = _logTraces + .filter((trace) => isLogLevel(trace)) + .reduce((acc, level) => Math.max(logLevelOrder.indexOf(level), acc), -1); + const level = logLevelOrder[_level] ?? LogLevel.UNKNOWN; - const traces = _logTraces.filter((trace) => !isLogLevel(trace)).map((trace) => { - if (typeof trace === 'object') { - return `TracedException.Name = ${trace.name}, TracedException.Message = ${trace.message}, TracedException.Stack = ${trace.stack}` - } - return trace; - }); - return { - level, - traces, - }; - } + const traces = _logTraces + .filter((trace) => !isLogLevel(trace)) + .map((trace) => { + if (typeof trace === 'object') { + return `TracedException.Name = ${trace.name}, TracedException.Message = ${trace.message}, TracedException.Stack = ${trace.stack}`; + } + return trace; + }); + return { + level, + traces, + }; + } } export enum LogLevel { - UNKNOWN = "UNKNOWN", - INFO = "INFO", - WARN = "WARN", - DEBUG = "DEBUG", - ERROR = "ERROR", - SYS = "SYS", + UNKNOWN = 'UNKNOWN', + INFO = 'INFO', + WARN = 'WARN', + DEBUG = 'DEBUG', + ERROR = 'ERROR', + SYS = 'SYS', } -const logLevelOrder: Array<LogLevel> = [ - LogLevel.DEBUG, - LogLevel.INFO, - LogLevel.WARN, - LogLevel.ERROR, - LogLevel.SYS, -]; +const logLevelOrder: Array<LogLevel> = [LogLevel.DEBUG, LogLevel.INFO, LogLevel.WARN, LogLevel.ERROR, LogLevel.SYS]; export const isLogLevel = (l: unknown): l is LogLevel => - typeof l === "string" && logLevelOrder.some((level) => level === l); - + typeof l === 'string' && logLevelOrder.some((level) => level === l); const defaultAllowedLevels = () => - [ - LogLevel.UNKNOWN, - ...(isDebug() ? [LogLevel.DEBUG] : []), - LogLevel.INFO, - LogLevel.WARN, - LogLevel.ERROR, - LogLevel.SYS, - ] as Array<LogLevel>; + [ + LogLevel.UNKNOWN, + ...(isDebug() ? [LogLevel.DEBUG] : []), + LogLevel.INFO, + LogLevel.WARN, + LogLevel.ERROR, + LogLevel.SYS, + ] as Array<LogLevel>; export interface ILogger { - readonly log: (level: LogLevel, ...args: string[]) => void; + readonly log: (level: LogLevel, ...args: string[]) => void; } class LoggerImpl implements ILogger { private readonly textEncoder = new TextEncoder(); public log(level: LogLevel, ...trace: string[]) { - const message = JSON.stringify({ - level, - trace, - }, null, 4); + const message = JSON.stringify( + { + level, + trace, + }, + null, + 4, + ); const styled = `${this.getStyle(level)}${message}${ANSI.RESET}\n`; - this.getStream(level).writeSync(this.textEncoder.encode(styled)); + this.getStream(level)(this.textEncoder.encode(styled)); } private getStream(level: LogLevel) { if (level === LogLevel.ERROR) { - return Deno.stderr; + return console.error; } - return Deno.stdout; + return console.log; } private getStyle(level: LogLevel) { @@ -127,17 +110,17 @@ class LoggerImpl implements ILogger { } export const ANSI = { - RESET: "\x1b[0m", - BOLD: "\x1b[1m", - DIM: "\x1b[2m", - RED: "\x1b[31m", - GREEN: "\x1b[32m", - YELLOW: "\x1b[33m", - BLUE: "\x1b[34m", - MAGENTA: "\x1b[35m", - CYAN: "\x1b[36m", - WHITE: "\x1b[37m", - BRIGHT_RED: "\x1b[91m", - BRIGHT_YELLOW: "\x1b[93m", - GRAY: "\x1b[90m", + RESET: '\x1b[0m', + BOLD: '\x1b[1m', + DIM: '\x1b[2m', + RED: '\x1b[31m', + GREEN: '\x1b[32m', + YELLOW: '\x1b[33m', + BLUE: '\x1b[34m', + MAGENTA: '\x1b[35m', + CYAN: '\x1b[36m', + WHITE: '\x1b[37m', + BRIGHT_RED: '\x1b[91m', + BRIGHT_YELLOW: '\x1b[93m', + GRAY: '\x1b[90m', }; 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; + } } diff --git a/u/trace/mod.ts b/u/trace/mod.ts deleted file mode 100644 index 0f9b61b..0000000 --- a/u/trace/mod.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./itrace.ts"; -export * from "./util.ts"; -export * from "./logger.ts"; -export * from "./metrics.ts"; -export * from "./trace.ts"; diff --git a/u/trace/trace.ts b/u/trace/trace.ts index 5629c28..acc116f 100644 --- a/u/trace/trace.ts +++ b/u/trace/trace.ts @@ -1,86 +1,69 @@ import { - isMetricsTraceSupplier, - type ITrace, - type ITraceable, - type ITraceWith, - LogLevel, - LogTrace, - type LogTraceSupplier, - MetricsTrace, - type MetricsTraceSupplier, - type MetricValue, - TraceableImpl, -} from "@emprespresso/pengueno"; + isMetricsTraceSupplier, + type ITrace, + type ITraceable, + type ITraceWith, + LogLevel, + LogTrace, + type LogTraceSupplier, + MetricsTrace, + type MetricsTraceSupplier, + type MetricValue, + TraceableImpl, +} from '@emprespresso/pengueno'; export class LogTraceable<T> extends TraceableImpl<T, LogTraceSupplier> { - public static LogTrace = new LogTrace(); - static of<T>(t: T) { - return new LogTraceable(t, LogTraceable.LogTrace); - } + public static LogTrace = new LogTrace(); + static of<T>(t: T) { + return new LogTraceable(t, LogTraceable.LogTrace); + } } -const getEmbeddedMetricConsumer = - (logTrace: ITrace<LogTraceSupplier>) => - (metrics: Array<MetricValue>) => +const getEmbeddedMetricConsumer = (logTrace: ITrace<LogTraceSupplier>) => (metrics: Array<MetricValue>) => logTrace.addTrace(LogLevel.SYS).trace(`Metrics = <metrics>${JSON.stringify(metrics)}</metrics>`); -export class EmbeddedMetricsTraceable<T> extends TraceableImpl< - T, - MetricsTraceSupplier -> { - public static MetricsTrace = new MetricsTrace( - getEmbeddedMetricConsumer(LogTraceable.LogTrace), - ); +export class EmbeddedMetricsTraceable<T> extends TraceableImpl<T, MetricsTraceSupplier> { + public static MetricsTrace = new MetricsTrace(getEmbeddedMetricConsumer(LogTraceable.LogTrace)); - static of<T>(t: T, metricsTrace = EmbeddedMetricsTraceable.MetricsTrace) { - return new EmbeddedMetricsTraceable(t, metricsTrace); - } + static of<T>(t: T, metricsTrace = EmbeddedMetricsTraceable.MetricsTrace) { + return new EmbeddedMetricsTraceable(t, metricsTrace); + } } -export type LogMetricTraceSupplier = ITraceWith< - LogTraceSupplier | MetricsTraceSupplier ->; +export type LogMetricTraceSupplier = ITraceWith<LogTraceSupplier | MetricsTraceSupplier>; export class LogMetricTrace implements ITrace<LogMetricTraceSupplier> { - constructor( - private logTrace: ITrace<LogTraceSupplier>, - private metricsTrace: ITrace<MetricsTraceSupplier>, - ) {} + constructor( + private logTrace: ITrace<LogTraceSupplier>, + private metricsTrace: ITrace<MetricsTraceSupplier>, + ) {} - public addTrace( - trace: LogTraceSupplier | MetricsTraceSupplier, - ): LogMetricTrace { - if (isMetricsTraceSupplier(trace)) { - this.metricsTrace = this.metricsTrace.addTrace(trace); - return this; + public addTrace(trace: LogTraceSupplier | MetricsTraceSupplier): LogMetricTrace { + if (isMetricsTraceSupplier(trace)) { + this.metricsTrace = this.metricsTrace.addTrace(trace); + return this; + } + this.logTrace = this.logTrace.addTrace(trace); + return this; } - this.logTrace = this.logTrace.addTrace(trace); - return this; - } - public trace(trace: LogTraceSupplier | MetricsTraceSupplier) { - if (isMetricsTraceSupplier(trace)) { - this.metricsTrace.trace(trace); - return this; + public trace(trace: LogTraceSupplier | MetricsTraceSupplier) { + if (isMetricsTraceSupplier(trace)) { + this.metricsTrace.trace(trace); + return this; + } + this.logTrace.trace(trace); + return this; } - this.logTrace.trace(trace); - return this; - } } -export class LogMetricTraceable<T> extends TraceableImpl< - T, - MetricsTraceSupplier | LogTraceSupplier -> { - static ofLogTraceable<T>(t: ITraceable<T, LogTraceSupplier>) { - const metricsTrace = new MetricsTrace(getEmbeddedMetricConsumer(t.trace)); - return new LogMetricTraceable( - t.get(), - new LogMetricTrace(t.trace, metricsTrace), - ); - } +export class LogMetricTraceable<T> extends TraceableImpl<T, MetricsTraceSupplier | LogTraceSupplier> { + static ofLogTraceable<T>(t: ITraceable<T, LogTraceSupplier>) { + const metricsTrace = new MetricsTrace(getEmbeddedMetricConsumer(t.trace)); + return new LogMetricTraceable(t.get(), new LogMetricTrace(t.trace, metricsTrace)); + } - static of<T>(t: T) { - const logTrace = LogTraceable.of(t); - return LogMetricTraceable.ofLogTraceable(logTrace); - } + static of<T>(t: T) { + const logTrace = LogTraceable.of(t); + return LogMetricTraceable.ofLogTraceable(logTrace); + } } diff --git a/u/trace/util.ts b/u/trace/util.ts index e2200b9..db1db63 100644 --- a/u/trace/util.ts +++ b/u/trace/util.ts @@ -1,47 +1,45 @@ import { -ANSI, - type Callable, - type IMetric, - type ITraceableMapper, - type ITraceableTuple, - type MetricsTraceSupplier, -} from "@emprespresso/pengueno"; + ANSI, + type Callable, + type IMetric, + type ITraceableMapper, + type ITraceableTuple, + type MetricsTraceSupplier, +} from '@emprespresso/pengueno'; export class TraceUtil { - static withTrace<T, Trace>( - trace: string, - ansi?: Array<keyof typeof ANSI> - ): ITraceableMapper<T, ITraceableTuple<T, Trace | Array<Trace>>, Trace> { - if (ansi) { - return (t) => [t.get(), `${ansi.join("")}${trace}${ANSI.RESET}`]; - } - return (t) => [t.get(), trace]; - } + static withTrace<T, Trace>( + trace: string, + ansi?: Array<keyof typeof ANSI>, + ): ITraceableMapper<T, ITraceableTuple<T, Trace | Array<Trace>>, Trace> { + if (ansi) { + return (t) => [t.get(), `${ansi.join('')}${trace}${ANSI.RESET}`]; + } + return (t) => [t.get(), trace]; + } - static withMetricTrace<T, Trace extends MetricsTraceSupplier>( - metric: IMetric, - ): ITraceableMapper<T, ITraceableTuple<T, Trace | Array<Trace>>, Trace> { - return (t) => [t.get(), metric as Trace]; - } + static withMetricTrace<T, Trace extends MetricsTraceSupplier>( + metric: IMetric, + ): ITraceableMapper<T, ITraceableTuple<T, Trace | Array<Trace>>, Trace> { + return (t) => [t.get(), metric as Trace]; + } - static withFunctionTrace<F extends Callable, T, Trace>( - f: F, - ): ITraceableMapper<T, ITraceableTuple<T, Trace | Array<Trace>>, Trace> { - return TraceUtil.withTrace(`fn.${f.name}`); - } + static withFunctionTrace<F extends Callable, T, Trace>( + f: F, + ): ITraceableMapper<T, ITraceableTuple<T, Trace | Array<Trace>>, Trace> { + return TraceUtil.withTrace(`fn.${f.name}`); + } - static withClassTrace<C extends object, T, Trace>( - c: C, - ): ITraceableMapper<T, ITraceableTuple<T, Trace | Array<Trace>>, Trace> { - return TraceUtil.withTrace(`class.${c.constructor.name}`); - } + static withClassTrace<C extends object, T, Trace>( + c: C, + ): ITraceableMapper<T, ITraceableTuple<T, Trace | Array<Trace>>, Trace> { + return TraceUtil.withTrace(`class.${c.constructor.name}`); + } - static promiseify<T, U, Trace>( - mapper: ITraceableMapper<T, U, Trace>, - ): ITraceableMapper<Promise<T>, Promise<U>, Trace> { - return (traceablePromise) => - traceablePromise - .flatMapAsync(async (t) => t.move(await t.get()).map(mapper)) - .get(); - } + static promiseify<T, U, Trace>( + mapper: ITraceableMapper<T, U, Trace>, + ): ITraceableMapper<Promise<T>, Promise<U>, Trace> { + return (traceablePromise) => + traceablePromise.flatMapAsync(async (t) => t.move(await t.get()).map(mapper)).get(); + } } |