UNPKG

@zendesk/react-measure-timing-hooks

Version:

react hooks for measuring time to interactive and time to render of components

650 lines 32.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); require("./testUtility/asciiTimelineSerializer"); const vitest_1 = require("vitest"); const matchSpan = __importStar(require("./matchSpan")); const relationSchemas_1 = require("./testUtility/fixtures/relationSchemas"); const makeTimeline_1 = require("./testUtility/makeTimeline"); const processSpans_1 = require("./testUtility/processSpans"); const TraceManager_1 = require("./TraceManager"); (0, vitest_1.describe)('TraceManager', () => { let reportFn; // TS doesn't like that reportFn is wrapped in Mock<> type const getReportFn = () => reportFn; let generateId; let reportErrorFn; const DEFAULT_COLDBOOT_TIMEOUT_DURATION = 45_000; vitest_1.vitest.useFakeTimers({ now: 0, }); (0, vitest_1.beforeEach)(() => { reportFn = vitest_1.vitest.fn(); generateId = vitest_1.vitest.fn().mockReturnValue('trace-id'); reportErrorFn = vitest_1.vitest.fn(); }); (0, vitest_1.afterEach)(() => { vitest_1.vitest.clearAllMocks(); vitest_1.vitest.clearAllTimers(); }); (0, vitest_1.it)('tracks trace with minimal requirements', () => { const traceManager = new TraceManager_1.TraceManager({ relationSchemas: { ticket: { ticketId: String } }, reportFn: getReportFn(), generateId, reportErrorFn, }); const tracer = traceManager.createTracer({ name: 'ticket.basic-operation', type: 'operation', relationSchemaName: 'ticket', requiredSpans: [{ name: 'end' }], variants: { cold_boot: { timeout: DEFAULT_COLDBOOT_TIMEOUT_DURATION }, }, }); const traceId = tracer.start({ relatedTo: { ticketId: '1' }, variant: 'cold_boot', }); (0, vitest_1.expect)(traceId).toBe('trace-id'); // prettier-ignore const { spans } = (0, makeTimeline_1.getSpansFromTimeline) ` Events: ${(0, makeTimeline_1.Render)('start', 0)}-----${(0, makeTimeline_1.Render)('middle', 0)}-----${(0, makeTimeline_1.Render)('end', 0)}---<===+2s===>----${makeTimeline_1.Check} Time: ${0} ${50} ${100} ${2_100} `; (0, processSpans_1.processSpans)(spans, traceManager); (0, vitest_1.expect)(reportFn).toHaveBeenCalled(); const report = reportFn.mock.calls[0][0]; (0, vitest_1.expect)(report.entries.map((spanAndAnnotation) => spanAndAnnotation.span.performanceEntry)).toMatchInlineSnapshot(` events | start middle end timeline | |-<⋯ +50 ⋯>-|-<⋯ +50 ⋯>-| time (ms) | 0 50 100 `); (0, vitest_1.expect)(report.name).toBe('ticket.basic-operation'); (0, vitest_1.expect)(report.duration).toBe(100); (0, vitest_1.expect)(report.status).toBe('ok'); (0, vitest_1.expect)(report.interruptionReason).toBeUndefined(); }); (0, vitest_1.it)('correctly calculates a computed span', () => { const traceManager = new TraceManager_1.TraceManager({ relationSchemas: { ticket: { ticketId: String } }, reportFn: getReportFn(), generateId, reportErrorFn, }); const tracer = traceManager.createTracer({ name: 'ticket.computed-span-operation', type: 'operation', relationSchemaName: 'ticket', requiredSpans: [{ name: 'end' }], variants: { cold_boot: { timeout: DEFAULT_COLDBOOT_TIMEOUT_DURATION }, }, }); const computedSpanName = 'render-1-to-3'; // Define a computed span tracer.defineComputedSpan({ name: computedSpanName, startSpan: matchSpan.withName('render-1'), endSpan: matchSpan.withName('render-3'), }); const traceId = tracer.start({ relatedTo: { ticketId: '1' }, variant: 'cold_boot', }); // Start trace (0, vitest_1.expect)(traceId).toBe('trace-id'); // prettier-ignore const { spans } = (0, makeTimeline_1.getSpansFromTimeline) ` Events: ${(0, makeTimeline_1.Render)('start', 0)}---${(0, makeTimeline_1.Render)('render-1', 50)}----${(0, makeTimeline_1.Render)('render-2', 50)}----${(0, makeTimeline_1.Render)('render-3', 50)}--------${(0, makeTimeline_1.Render)('end', 0)} Time: ${0} ${50} ${100} ${150} ${200} `; (0, processSpans_1.processSpans)(spans, traceManager); (0, vitest_1.expect)(reportFn).toHaveBeenCalled(); const report = reportFn.mock.calls[0][0]; (0, vitest_1.expect)(report.name).toBe('ticket.computed-span-operation'); (0, vitest_1.expect)(report.duration).toBe(200); (0, vitest_1.expect)(report.status).toBe('ok'); (0, vitest_1.expect)(report.interruptionReason).toBeUndefined(); (0, vitest_1.expect)(report.computedSpans[computedSpanName]?.startOffset).toBe(50); (0, vitest_1.expect)(report.computedSpans[computedSpanName]?.duration).toBe(150); (0, vitest_1.expect)(report.entries.map((spanAndAnnotation) => spanAndAnnotation.span.performanceEntry)).toMatchInlineSnapshot(` events | start render-1(50) render-2(50) render-3(50) end timeline | |-<⋯ +50 ⋯>-[++++++++++++++]-[++++++++++++++]-[++++++++++++++| time (ms) | 0 50 100 150 200 `); }); (0, vitest_1.it)('correctly calculates a computed value', () => { const traceManager = new TraceManager_1.TraceManager({ relationSchemas: { ticket: { ticketId: String } }, reportFn: getReportFn(), generateId, reportErrorFn, }); const tracer = traceManager.createTracer({ name: 'ticket.computed-value-operation', type: 'operation', relationSchemaName: 'ticket', requiredSpans: [{ name: 'end' }], variants: { cold_boot: { timeout: DEFAULT_COLDBOOT_TIMEOUT_DURATION }, }, }); // Define a computed value tracer.defineComputedValue({ name: 'feature', matches: [{ name: 'feature' }], computeValueFromMatches: (feature) => feature.length, }); const traceId = tracer.start({ relatedTo: { ticketId: '1' }, variant: 'cold_boot', }); // Start trace (0, vitest_1.expect)(traceId).toBe('trace-id'); // prettier-ignore const { spans } = (0, makeTimeline_1.getSpansFromTimeline) ` Events: ${(0, makeTimeline_1.Render)('start', 0)}--${(0, makeTimeline_1.Render)('feature', 50)}--${(0, makeTimeline_1.Render)('feature', 50)}-${(0, makeTimeline_1.Render)('end', 0)} Time: ${0} ${50} ${100} ${150} `; (0, processSpans_1.processSpans)(spans, traceManager); (0, vitest_1.expect)(reportFn).toHaveBeenCalled(); const report = reportFn.mock.calls[0][0]; (0, vitest_1.expect)(report.name).toBe('ticket.computed-value-operation'); (0, vitest_1.expect)(report.duration).toBe(150); (0, vitest_1.expect)(report.status).toBe('ok'); (0, vitest_1.expect)(report.interruptionReason).toBeUndefined(); (0, vitest_1.expect)(report.computedValues).toEqual({ feature: 2, }); (0, vitest_1.expect)(report.entries.map((spanAndAnnotation) => spanAndAnnotation.span.performanceEntry)).toMatchInlineSnapshot(` events | start feature(50) feature(50) end timeline | |-<⋯ +50 ⋯>-[+++++++++++++++++++++++][+++++++++++++++++++++++| time (ms) | 0 50 100 150 `); }); (0, vitest_1.it)('correctly calculates computedRenderBeaconSpans, adjusting the render start based on the first render-start', () => { const traceManager = new TraceManager_1.TraceManager({ relationSchemas: { ticket: { ticketId: String } }, reportFn: getReportFn(), generateId, reportErrorFn, }); const tracer = traceManager.createTracer({ name: 'ticket.computedRenderBeaconSpans', type: 'operation', relationSchemaName: 'ticket', requiredSpans: [{ name: 'Component', isIdle: true }], variants: { cold_boot: { timeout: DEFAULT_COLDBOOT_TIMEOUT_DURATION }, }, }); const traceId = tracer.start({ relatedTo: { ticketId: '1' }, variant: 'cold_boot', }); // prettier-ignore const { spans } = (0, makeTimeline_1.getSpansFromTimeline) ` Events: ${(0, makeTimeline_1.Render)('Component', 0, { type: 'component-render-start' })}--${(0, makeTimeline_1.Render)('Component', 50)}--${(0, makeTimeline_1.Render)('Component', 50, { renderedOutput: 'content' })} Time: ${0} ${50} ${100} `; (0, processSpans_1.processSpans)(spans, traceManager); vitest_1.vitest.runAllTimers(); (0, vitest_1.expect)(reportFn).toHaveBeenCalled(); const report = reportFn.mock.calls[0][0]; (0, vitest_1.expect)(report.entries.map((spanAndAnnotation) => spanAndAnnotation.span.performanceEntry)).toMatchInlineSnapshot(` events | Component Component(50) Component(50) timeline | |-<⋯ +50 ⋯>-[+++++++++++++++++++++++][+++++++++++++++++++++++] time (ms) | 0 50 100 `); (0, vitest_1.expect)(report.name).toBe('ticket.computedRenderBeaconSpans'); (0, vitest_1.expect)(report.interruptionReason).toBeUndefined(); (0, vitest_1.expect)(report.status).toBe('ok'); (0, vitest_1.expect)(report.duration).toBe(150); (0, vitest_1.expect)(report.computedRenderBeaconSpans).toEqual({ Component: { firstRenderTillContent: 150, firstRenderTillData: 100, firstRenderTillLoading: 100, renderCount: 2, startOffset: 0, sumOfRenderDurations: 150, }, }); }); (0, vitest_1.it)('when relatedTo is true for two relations: tracks trace with relatedTo ticketId: 4 and relatedTo userId: 3', () => { const traceManager = new TraceManager_1.TraceManager({ relationSchemas: relationSchemas_1.ticketAndUserAndGlobalRelationSchemasFixture, reportFn: reportFn, generateId, reportErrorFn, }); const tracer = traceManager.createTracer({ name: 'ticket.relatedTo-operation', type: 'operation', relationSchemaName: 'ticket', requiredSpans: [{ name: 'end', matchingRelations: true }], variants: { cold_boot: { timeout: DEFAULT_COLDBOOT_TIMEOUT_DURATION }, }, }); const relatedTo = { ticketId: '4', userId: '3', }; const traceId = tracer.start({ relatedTo, variant: 'cold_boot', }); (0, vitest_1.expect)(traceId).toBe('trace-id'); // prettier-ignore const { spans } = (0, makeTimeline_1.getSpansFromTimeline) ` Events: ${(0, makeTimeline_1.Render)('start', 0)}-----${(0, makeTimeline_1.Render)('middle', 0)}-----${(0, makeTimeline_1.Render)('end', 0, { relatedTo })}---<===+6s===>----${makeTimeline_1.Check} Time: ${0} ${50} ${100} ${6_000} `; (0, processSpans_1.processSpans)(spans, traceManager); (0, vitest_1.expect)(reportFn).toHaveBeenCalled(); const report = reportFn.mock.calls[0][0]; (0, vitest_1.expect)(report.entries.map((spanAndAnnotation) => spanAndAnnotation.span.performanceEntry)).toMatchInlineSnapshot(` events | start middle end timeline | |-<⋯ +50 ⋯>-|-<⋯ +50 ⋯>-| time (ms) | 0 50 100 `); (0, vitest_1.expect)(report.name).toBe('ticket.relatedTo-operation'); (0, vitest_1.expect)(report.interruptionReason).toBeUndefined(); (0, vitest_1.expect)(report.duration).toBe(100); (0, vitest_1.expect)(report.status).toBe('ok'); (0, vitest_1.expect)(report.relatedTo).toEqual(relatedTo); }); (0, vitest_1.describe)('debounce', () => { (0, vitest_1.it)('tracks trace when debouncedOn is defined but no debounce events', () => { const traceManager = new TraceManager_1.TraceManager({ relationSchemas: { ticket: { ticketId: String } }, reportFn: getReportFn(), generateId, reportErrorFn, }); const tracer = traceManager.createTracer({ name: 'ticket.operation', type: 'operation', relationSchemaName: 'ticket', requiredSpans: [{ name: 'end' }], debounceOnSpans: [{ name: 'debounce' }], variants: { cold_boot: { timeout: DEFAULT_COLDBOOT_TIMEOUT_DURATION }, }, }); const traceId = tracer.start({ relatedTo: { ticketId: '1', }, variant: 'cold_boot', }); (0, vitest_1.expect)(traceId).toBe('trace-id'); // prettier-ignore const { spans } = (0, makeTimeline_1.getSpansFromTimeline) ` Events: ${(0, makeTimeline_1.Render)('start', 0)}-----${(0, makeTimeline_1.Render)('middle', 0)}-----${(0, makeTimeline_1.Render)('end', 0)}---<===+2s===>----${makeTimeline_1.Check} Time: ${0} ${50} ${100} ${2_100} `; (0, processSpans_1.processSpans)(spans, traceManager); (0, vitest_1.expect)(reportFn).toHaveBeenCalled(); const report = reportFn.mock.calls[0][0]; (0, vitest_1.expect)(report.entries.map((spanAndAnnotation) => spanAndAnnotation.span.performanceEntry)).toMatchInlineSnapshot(` events | start middle end timeline | |-<⋯ +50 ⋯>-|-<⋯ +50 ⋯>-| time (ms) | 0 50 100 `); (0, vitest_1.expect)(report.name).toBe('ticket.operation'); (0, vitest_1.expect)(report.duration).toBe(100); (0, vitest_1.expect)(report.status).toBe('ok'); (0, vitest_1.expect)(report.interruptionReason).toBeUndefined(); }); (0, vitest_1.it)('tracks trace correctly when debounced entries are seen', () => { const traceManager = new TraceManager_1.TraceManager({ relationSchemas: { ticket: { ticketId: String } }, reportFn: getReportFn(), generateId, reportErrorFn, }); const tracer = traceManager.createTracer({ name: 'ticket.debounce-operation', type: 'operation', relationSchemaName: 'ticket', requiredSpans: [matchSpan.withName('end')], debounceOnSpans: [ matchSpan.withName((n) => n.endsWith('debounce')), ], debounceWindow: 300, variants: { cold_boot: { timeout: DEFAULT_COLDBOOT_TIMEOUT_DURATION }, }, }); tracer.start({ relatedTo: { ticketId: '1', }, variant: 'cold_boot', }); // prettier-ignore const { spans } = (0, makeTimeline_1.getSpansFromTimeline) ` Events: ${(0, makeTimeline_1.Render)('start', 0)}-----${(0, makeTimeline_1.Render)('end', 0)}-----${(0, makeTimeline_1.Render)('shorter-debounce', 0)}-----${(0, makeTimeline_1.Render)('short-debounce', 0)}-----${(0, makeTimeline_1.Render)('long-debounce', 0)}-----${makeTimeline_1.Check})} Time: ${0} ${50} ${51} ${251} ${451} ${1_051} `; (0, processSpans_1.processSpans)(spans, traceManager); (0, vitest_1.expect)(reportFn).toHaveBeenCalled(); const report = reportFn.mock.calls[0][0]; (0, vitest_1.expect)(report.entries.map((spanAndAnnotation) => spanAndAnnotation.span.performanceEntry)).toMatchInlineSnapshot(` events | shorter-debounce long-debounce events | start end short-debounce timeline | |-------------------------------------------------|-|-<⋯ +200 ⋯>--|-<⋯ +200 ⋯>-| time (ms) | 0 50 251 451 time (ms) | 51 `); (0, vitest_1.expect)(report.name).toBe('ticket.debounce-operation'); (0, vitest_1.expect)(report.duration).toBe(451); // 50 + 1 + 200 + 200 (0, vitest_1.expect)(report.status).toBe('ok'); (0, vitest_1.expect)(report.interruptionReason).toBeUndefined(); }); }); (0, vitest_1.describe)('interrupts', () => { (0, vitest_1.it)('interrupts a basic trace when interruptOnSpans criteria is met', () => { const traceManager = new TraceManager_1.TraceManager({ relationSchemas: { ticket: { ticketId: String } }, reportFn: getReportFn(), generateId, reportErrorFn, }); const tracer = traceManager.createTracer({ name: 'ticket.interrupt-on-basic-operation', type: 'operation', relationSchemaName: 'ticket', requiredSpans: [matchSpan.withName('end')], interruptOnSpans: [matchSpan.withName('interrupt')], variants: { cold_boot: { timeout: DEFAULT_COLDBOOT_TIMEOUT_DURATION }, }, }); tracer.start({ relatedTo: { ticketId: '1', }, variant: 'cold_boot', }); // prettier-ignore const { spans } = (0, makeTimeline_1.getSpansFromTimeline) ` Events: ${(0, makeTimeline_1.Render)('start', 0)}-----${(0, makeTimeline_1.Render)('interrupt', 0)}-----${(0, makeTimeline_1.Render)('end', 0)} Time: ${0} ${100} ${200} `; (0, processSpans_1.processSpans)(spans, traceManager); (0, vitest_1.expect)(reportFn).toHaveBeenCalled(); const report = reportFn.mock.calls[0][0]; (0, vitest_1.expect)(report.entries.map((spanAndAnnotation) => spanAndAnnotation.span.performanceEntry)).toMatchInlineSnapshot(` events | start timeline | | time (ms) | 0 `); (0, vitest_1.expect)(report.name).toBe('ticket.interrupt-on-basic-operation'); (0, vitest_1.expect)(report.duration).toBeNull(); (0, vitest_1.expect)(report.status).toBe('interrupted'); (0, vitest_1.expect)(report.interruptionReason).toBe('matched-on-interrupt'); }); (0, vitest_1.it)('interrupts itself when another trace is started', () => { const traceManager = new TraceManager_1.TraceManager({ relationSchemas: { ticket: { ticketId: String } }, reportFn: getReportFn(), generateId, reportErrorFn, }); const tracer = traceManager.createTracer({ name: 'ticket.interrupt-itself-operation', type: 'operation', relationSchemaName: 'ticket', requiredSpans: [{ name: 'end' }], debounceOnSpans: [{ name: 'debounce' }], variants: { cold_boot: { timeout: DEFAULT_COLDBOOT_TIMEOUT_DURATION }, }, }); const traceId = tracer.start({ relatedTo: { ticketId: '1', }, variant: 'cold_boot', }); (0, vitest_1.expect)(traceId).toBe('trace-id'); // prettier-ignore const { spans } = (0, makeTimeline_1.getSpansFromTimeline) ` Events: ${(0, makeTimeline_1.Render)('start', 0)} Time: ${0} `; (0, processSpans_1.processSpans)(spans, traceManager); // Start another operation to interrupt the first one const newTraceId = tracer.start({ relatedTo: { ticketId: '1', }, variant: 'cold_boot', }); (0, vitest_1.expect)(newTraceId).toBe('trace-id'); (0, vitest_1.expect)(reportFn).toHaveBeenCalled(); const report = reportFn.mock.calls[0][0]; (0, vitest_1.expect)(report.entries.map((spanAndAnnotation) => spanAndAnnotation.span.performanceEntry)).toMatchInlineSnapshot(` events | start timeline | | time (ms) | 0 `); (0, vitest_1.expect)(report.name).toBe('ticket.interrupt-itself-operation'); (0, vitest_1.expect)(report.duration).toBeNull(); (0, vitest_1.expect)(report.status).toBe('interrupted'); (0, vitest_1.expect)(report.interruptionReason).toBe('another-trace-started'); }); (0, vitest_1.it)('tracks a regression: interrupts a trace when a component is no longer idle', () => { const traceManager = new TraceManager_1.TraceManager({ relationSchemas: { ticket: { ticketId: String } }, reportFn: getReportFn(), generateId, reportErrorFn, }); const tracer = traceManager.createTracer({ name: 'ticket.interrupt-on-basic-operation', type: 'operation', relationSchemaName: 'ticket', requiredSpans: [{ name: 'end', isIdle: true }], debounceOnSpans: [{ name: 'end' }], variants: { cold_boot: { timeout: DEFAULT_COLDBOOT_TIMEOUT_DURATION }, }, }); tracer.start({ relatedTo: { ticketId: '1', }, variant: 'cold_boot', }); // prettier-ignore const { spans } = (0, makeTimeline_1.getSpansFromTimeline) ` Events: ${(0, makeTimeline_1.Render)('start', 0)}-----${(0, makeTimeline_1.Render)('end', 50, { isIdle: true })}-----${(0, makeTimeline_1.Render)('end', 50, { isIdle: false })} Time: ${0} ${100} ${200} `; (0, processSpans_1.processSpans)(spans, traceManager); (0, vitest_1.expect)(reportFn).toHaveBeenCalled(); const report = reportFn.mock.calls[0][0]; (0, vitest_1.expect)(report.entries.map((spanAndAnnotation) => spanAndAnnotation.span.performanceEntry)).toMatchInlineSnapshot(` events | start end(50) timeline | |-<⋯ +100 ⋯>-[++++++++++++++++++++++++++++++++++++++++++++++++] time (ms) | 0 100 `); (0, vitest_1.expect)(report.name).toBe('ticket.interrupt-on-basic-operation'); (0, vitest_1.expect)(report.interruptionReason).toBe('idle-component-no-longer-idle'); (0, vitest_1.expect)(report.status).toBe('interrupted'); (0, vitest_1.expect)(report.duration).toBeNull(); }); (0, vitest_1.describe)('timeout', () => { (0, vitest_1.it)('timeouts when the basic trace when the default timeout duration is reached', () => { const traceManager = new TraceManager_1.TraceManager({ relationSchemas: { ticket: { ticketId: String } }, reportFn: getReportFn(), generateId, reportErrorFn, }); const tracer = traceManager.createTracer({ name: 'ticket.timeout-operation', type: 'operation', relationSchemaName: 'ticket', requiredSpans: [{ name: 'timed-out-render' }], variants: { cold_boot: { timeout: 500 } }, }); const traceId = tracer.start({ startTime: { now: 0, epoch: 0 }, relatedTo: { ticketId: '1', }, variant: 'cold_boot', }); (0, vitest_1.expect)(traceId).toBe('trace-id'); // prettier-ignore const { spans } = (0, makeTimeline_1.getSpansFromTimeline) ` Events: ${(0, makeTimeline_1.Render)('start', 0)}------${(0, makeTimeline_1.Render)('timed-out-render', 0)} Time: ${0} ${500 + 1} `; (0, processSpans_1.processSpans)(spans, traceManager); (0, vitest_1.expect)(reportFn).toHaveBeenCalled(); const report = reportFn.mock.calls[0][0]; (0, vitest_1.expect)(report.entries.map((spanAndAnnotation) => spanAndAnnotation.span.performanceEntry)).toMatchInlineSnapshot(` events | start timeline | | time (ms) | 0 `); (0, vitest_1.expect)(report.interruptionReason).toBe('timeout'); (0, vitest_1.expect)(report.duration).toBeNull(); (0, vitest_1.expect)(report.name).toBe('ticket.timeout-operation'); (0, vitest_1.expect)(report.status).toBe('interrupted'); (0, vitest_1.expect)(report.interruptionReason).toBe('timeout'); (0, vitest_1.expect)(report.duration).toBeNull(); }); (0, vitest_1.it)('timeouts when the basic trace when a custom timeout duration is reached', () => { const traceManager = new TraceManager_1.TraceManager({ relationSchemas: { ticket: { ticketId: String } }, reportFn: getReportFn(), generateId, reportErrorFn, }); const CUSTOM_TIMEOUT_DURATION = 500; const tracer = traceManager.createTracer({ name: 'ticket.timeout-operation', type: 'operation', relationSchemaName: 'ticket', requiredSpans: [{ name: 'timed-out-render' }], variants: { cold_boot: { timeout: CUSTOM_TIMEOUT_DURATION }, }, }); const traceId = tracer.start({ startTime: { now: 0, epoch: 0 }, relatedTo: { ticketId: '1', }, variant: 'cold_boot', }); (0, vitest_1.expect)(traceId).toBe('trace-id'); // prettier-ignore const { spans } = (0, makeTimeline_1.getSpansFromTimeline) ` Events: ${(0, makeTimeline_1.Render)('start', 0)}------${(0, makeTimeline_1.Render)('timed-out-render', 0)} Time: ${0} ${CUSTOM_TIMEOUT_DURATION + 1} `; (0, processSpans_1.processSpans)(spans, traceManager); (0, vitest_1.expect)(reportFn).toHaveBeenCalled(); const report = reportFn.mock.calls[0][0]; (0, vitest_1.expect)(report.status).toBe('interrupted'); (0, vitest_1.expect)(report.interruptionReason).toBe('timeout'); (0, vitest_1.expect)(report.entries.map((spanAndAnnotation) => spanAndAnnotation.span.performanceEntry)).toMatchInlineSnapshot(` events | start timeline | | time (ms) | 0 `); (0, vitest_1.expect)(report.name).toBe('ticket.timeout-operation'); (0, vitest_1.expect)(report.duration).toBeNull(); }); (0, vitest_1.it)('transitions from debouncing to timeout', () => { const traceManager = new TraceManager_1.TraceManager({ relationSchemas: { ticket: { ticketId: String } }, reportFn: getReportFn(), generateId, reportErrorFn, }); const CUSTOM_TIMEOUT_DURATION = 500; const tracer = traceManager.createTracer({ name: 'ticket.timeout-operation', type: 'operation', relationSchemaName: 'ticket', requiredSpans: [{ name: 'end' }], debounceOnSpans: [{ name: 'debounce' }], variants: { cold_boot: { timeout: CUSTOM_TIMEOUT_DURATION }, }, }); const traceId = tracer.start({ startTime: { now: 0, epoch: 0 }, relatedTo: { ticketId: '1', }, variant: 'cold_boot', }); (0, vitest_1.expect)(traceId).toBe('trace-id'); // prettier-ignore const { spans } = (0, makeTimeline_1.getSpansFromTimeline) ` Events: ${(0, makeTimeline_1.Render)('start', 0)}--${(0, makeTimeline_1.Render)('end', 0)}--${(0, makeTimeline_1.Render)('debounce', 0)}--${makeTimeline_1.Check}} Time: ${0} ${50} ${51} ${CUSTOM_TIMEOUT_DURATION + 1} `; (0, processSpans_1.processSpans)(spans, traceManager); (0, vitest_1.expect)(reportFn).toHaveBeenCalled(); const report = reportFn.mock.calls[0][0]; (0, vitest_1.expect)(report.entries.map((spanAndAnnotation) => spanAndAnnotation.span.performanceEntry)).toMatchInlineSnapshot(` events | debounce events | start end timeline | |-<⋯ +50 ⋯>-||- time (ms) | 0 50 time (ms) | 51 `); (0, vitest_1.expect)(report.name).toBe('ticket.timeout-operation'); (0, vitest_1.expect)(report.duration).toBeNull(); (0, vitest_1.expect)(report.status).toBe('interrupted'); (0, vitest_1.expect)(report.interruptionReason).toBe('timeout'); }); }); }); }); //# sourceMappingURL=TraceManager.test.js.map