summaryrefslogtreecommitdiff
path: root/tst/metrics_trace.test.ts
blob: 23d51473550d57589b75b18ebc96df28a7f6ee7b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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]);
    });
});