diff options
Diffstat (limited to 'lib/trace/metric/trace.ts')
-rw-r--r-- | lib/trace/metric/trace.ts | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/lib/trace/metric/trace.ts b/lib/trace/metric/trace.ts index 0c5fe37..6508831 100644 --- a/lib/trace/metric/trace.ts +++ b/lib/trace/metric/trace.ts @@ -9,17 +9,16 @@ export const isMetricsTraceSupplier = (t: unknown): t is MetricsTraceSupplier => export class MetricsTrace implements ITrace<MetricsTraceSupplier> { constructor( private readonly metricConsumer: SideEffect<Array<MetricValue>>, - private readonly activeTraces: ReadonlyMap<IMetric, number> = new Map(), - private readonly completedTraces: ReadonlySet<IMetric> = new Set(), + private readonly activeTraces: ReadonlyMap<string, number> = new Map(), + private readonly completedTraces: ReadonlySet<string> = new Set(), ) {} public traceScope(trace: MetricsTraceSupplier): MetricsTrace { const now = Date.now(); const metricsToTrace = (Array.isArray(trace) ? trace : [trace]).filter(isIMetric); + const initialTraces = new Map(metricsToTrace.map((metric) => [metric.name, now])); - const initialTraces = new Map(metricsToTrace.map((metric) => [metric, now])); - - return new MetricsTrace(this.metricConsumer, initialTraces); + return new MetricsTrace(this.metricConsumer, initialTraces, this.completedTraces); } public trace(metrics: MetricsTraceSupplier): MetricsTrace { @@ -30,30 +29,47 @@ export class MetricsTrace implements ITrace<MetricsTraceSupplier> { const now = Date.now(); const allMetrics = Array.isArray(metrics) ? metrics : [metrics]; - // partition the incoming metrics const valuesToEmit = allMetrics.filter(isMetricValue); const traceableMetrics = allMetrics.filter(isIMetric); - const metricsToStart = traceableMetrics.filter((m) => !this.activeTraces.has(m)); - const metricsToEnd = traceableMetrics.filter((m) => this.activeTraces.has(m) && !this.completedTraces.has(m)); + const metricsToStart = traceableMetrics.filter((m) => !this.activeTraces.has(m.name)); + const metricsToEnd = traceableMetrics.filter( + (m) => this.activeTraces.has(m.name) && !this.completedTraces.has(m.name), + ); - // the new metrics to emit based on traces ending *now* const endedMetricValues = metricsToEnd.flatMap((metric) => [ metric.count.withValue(1.0), - metric.time.withValue(now - this.activeTraces.get(metric)!), + metric.time.withValue(now - this.activeTraces.get(metric.name)!), ]); - const allMetricsToEmit = [...valuesToEmit, ...endedMetricValues]; + const parentBasedMetrics = metricsToStart.filter((metric) => { + const parent = metric.parent; + return parent && this.activeTraces.has(parent.name); + }); + + const parentBasedValues = parentBasedMetrics.flatMap((metric) => { + const parentStart = this.activeTraces.get(metric.parent!.name)!; + return [ + metric.count.withValue(1.0), + metric.time.withValue(now - parentStart), + ]; + }); + + const allMetricsToEmit = [...valuesToEmit, ...endedMetricValues, ...parentBasedValues]; if (allMetricsToEmit.length > 0) { this.metricConsumer(allMetricsToEmit); } - // the next immutable state const nextActiveTraces = new Map([ ...this.activeTraces, - ...metricsToStart.map((m): [IMetric, number] => [m, now]), + ...metricsToStart.map((m): [string, number] => [m.name, now]), ]); - const nextCompletedTraces = new Set([...this.completedTraces, ...metricsToEnd]); + const nextCompletedTraces = new Set([ + ...this.completedTraces, + ...metricsToEnd.map((m) => m.name), + ...parentBasedMetrics.map((m) => m.name), + ]); + return new MetricsTrace(this.metricConsumer, nextActiveTraces, nextCompletedTraces); } } |