diff options
Diffstat (limited to 'tst/metrics_trace.test.ts')
| -rw-r--r-- | tst/metrics_trace.test.ts | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/tst/metrics_trace.test.ts b/tst/metrics_trace.test.ts new file mode 100644 index 0000000..23d5147 --- /dev/null +++ b/tst/metrics_trace.test.ts @@ -0,0 +1,125 @@ +import { Metric, MetricsTrace, MetricValueTag, isMetricsTraceSupplier, type MetricValue } from '../lib/index'; + +describe('trace/metric/trace (MetricsTrace)', () => { + beforeEach(() => { + jest.useFakeTimers(); + jest.setSystemTime(new Date('2020-01-01T00:00:00.000Z')); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + test('isMetricsTraceSupplier accepts metrics and values', () => { + const m = Metric.fromName('m'); + const v = m.count.withValue(1); + + expect(isMetricsTraceSupplier(m)).toBe(true); + expect(isMetricsTraceSupplier(v)).toBe(true); + expect(isMetricsTraceSupplier([m, v])).toBe(true); + expect(isMetricsTraceSupplier('nope')).toBe(false); + expect(isMetricsTraceSupplier(undefined)).toBe(false); + }); + + test('traceScope + trace ends a metric and emits count/time', () => { + const emitted: MetricValue[] = []; + const consumer = (vals: MetricValue[]) => emitted.push(...vals); + + const metric = Metric.fromName('A'); + const t0 = new MetricsTrace(consumer).traceScope(metric); + + jest.setSystemTime(new Date('2020-01-01T00:00:00.100Z')); + t0.trace(metric); + + expect(emitted).toEqual( + expect.arrayContaining([ + expect.objectContaining({ _tag: MetricValueTag, name: 'A.count', value: 1 }), + expect.objectContaining({ _tag: MetricValueTag, name: 'A.time', value: 100 }), + ]), + ); + }); + + test('trace does not emit when given string/undefined', () => { + const emitted: MetricValue[] = []; + const consumer = (vals: MetricValue[]) => emitted.push(...vals); + const t = new MetricsTrace(consumer); + + t.trace(undefined); + t.trace('hello'); + expect(emitted).toEqual([]); + }); + + test('parent-based metric emits relative to parent start', () => { + const emitted: MetricValue[] = []; + const consumer = (vals: MetricValue[]) => emitted.push(...vals); + + const parent = Metric.fromName('parent'); + const child = parent.child('child'); + + const t0 = new MetricsTrace(consumer).traceScope(parent); + + jest.setSystemTime(new Date('2020-01-01T00:00:00.050Z')); + const t1 = t0.trace(child); + + expect(emitted).toEqual( + expect.arrayContaining([ + expect.objectContaining({ name: 'parent.child.count', value: 1 }), + expect.objectContaining({ name: 'parent.child.time', value: 50 }), + ]), + ); + + // end parent normally + jest.setSystemTime(new Date('2020-01-01T00:00:00.080Z')); + t1.trace(parent); + expect(emitted).toEqual( + expect.arrayContaining([ + expect.objectContaining({ name: 'parent.count', value: 1 }), + expect.objectContaining({ name: 'parent.time', value: 80 }), + ]), + ); + + // child should be considered completed already + const before = emitted.length; + jest.setSystemTime(new Date('2020-01-01T00:00:00.100Z')); + t1.trace(child); + expect(emitted.length).toBe(before); + }); + + test('nested scope can end parent metric via result child', () => { + const emitted: MetricValue[] = []; + const consumer = (vals: MetricValue[]) => emitted.push(...vals); + + const result = Metric.fromName('job').asResult(); + + const root = new MetricsTrace(consumer).traceScope(result); + + jest.setSystemTime(new Date('2020-01-01T00:00:00.100Z')); + const child = root.traceScope('child-scope'); + const childAfterSuccess = child.trace(result.success); + + expect(emitted).toEqual( + expect.arrayContaining([ + expect.objectContaining({ name: 'job.success.count', value: 1 }), + expect.objectContaining({ name: 'job.success.time', value: 100 }), + ]), + ); + + const before = emitted.length; + jest.setSystemTime(new Date('2020-01-01T00:00:00.200Z')); + childAfterSuccess.trace(result.success); + expect(emitted.length).toBe(before); + }); + + test('trace forwards MetricValue emissions unchanged', () => { + const emitted: MetricValue[] = []; + const consumer = (vals: MetricValue[]) => emitted.push(...vals); + + const metric = Metric.fromName('X'); + const value = metric.count.withValue(7); + + const t = new MetricsTrace(consumer); + t.trace(value); + + expect(emitted).toEqual([value]); + }); +}); |
