UNPKG

@zendesk/react-measure-timing-hooks

Version:

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

191 lines 6.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.mapOperationForVisualization = void 0; const ensureTimestamp_1 = require("../ensureTimestamp"); const orderArray = [ 'longtask', 'long-animation-frame', 'computed-span', 'component-render', 'measure', 'resource', 'resource-ember', 'asset', 'iframe', ]; const ASSET_EXTENSIONS = [ '.mp3', '.mp4', '.webm', '.wav', '.ogg', '.flac', '.aac', '.aiff', '.wma', '.m4a', '.flv', '.avi', '.mov', '.wmv', '.mpg', '.mpeg', '.mkv', '.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.tiff', '.svg', '.ico', '.css', '.scss', '.less', '.styl', '.html', '.htm', '.xml', '.js', ]; const order = Object.fromEntries(orderArray.map((type, idx) => [type, idx])); const mapOperationForVisualization = (traceRecording, { collapseRenders = true, collapseAssets = true, collapseEmberResources = false, collapseIframes = false, displayResources = true, displayMeasures = true, } = {}) => { const allEntries = traceRecording.entries; if (!allEntries) return null; const preMappedEntries = allEntries.flatMap((entry) => { if (entry.span.type === 'component-render-start') { return []; } const mapped = { span: entry.span, annotation: entry.annotation, groupName: entry.span.name, type: entry.span.type, }; let overrideGroupName; let { type } = mapped; if (type === 'resource') { const filename = (mapped.span.performanceEntry?.name ?? mapped.span.name) .split('/') .at(-1) ?.split('?') .at(0); const extension = filename?.split('.').at(-1); if (filename === '$file' || (extension && ASSET_EXTENSIONS.includes(`.${extension}`))) { overrideGroupName = overrideGroupName ?? extension; type = 'asset'; } } if (collapseRenders && type === 'component-render') { overrideGroupName = 'renders'; } if (collapseAssets && type === 'asset') { overrideGroupName = 'assets'; } if (collapseIframes && type === 'iframe') { overrideGroupName = 'iframes'; } if (type === 'asset' || type === 'iframe') { overrideGroupName = overrideGroupName ?? mapped.groupName.split('/').at(-1); } if (type === 'measure' && (entry.span.name.endsWith('/tti') || entry.span.name.endsWith('/ttr'))) { // remove suffix from measure name overrideGroupName = entry.span.name.split('/').slice(0, -1).join('/'); } if (entry.span.name.startsWith('https://')) { const shortenedName = entry.span.name.split('zendesk.com').at(-1); if (mapped.span.attributes?.initiatorType === 'xmlhttprequest') { overrideGroupName = collapseEmberResources ? 'ember-resource' : overrideGroupName ?? shortenedName; type = 'resource-ember'; } if (type === 'resource') { overrideGroupName = overrideGroupName ?? shortenedName; } } return { ...mapped, overrideGroupName, type, }; }); const mappedEntries = preMappedEntries.map((mapped, idx) => { if (mapped.groupName.startsWith('graphql/')) { const clientName = mapped.span.attributes?.apolloClientName; const commonName = mapped.overrideGroupName ?? mapped.groupName; if (clientName === 'local' && mapped.span.attributes?.feature) { const { feature } = mapped.span.attributes; const matchingResourceTask = preMappedEntries.find((t) => t.span.attributes?.feature === feature && t.type === 'resource'); if (matchingResourceTask) { matchingResourceTask.groupName = commonName; } return { ...mapped, groupName: commonName, type: 'resource', }; } return { ...mapped, groupName: commonName, type: 'resource', }; } return { ...mapped, groupName: mapped.overrideGroupName ?? mapped.groupName, }; }); const entriesFromComputedSpans = Object.entries(traceRecording.computedSpans).map(([name, computedSpan]) => ({ groupName: name, type: 'computed-span', span: { type: 'computed-span', duration: computedSpan.duration, name, startTime: (0, ensureTimestamp_1.adjustTimestampBy)(traceRecording.startTime, computedSpan.startOffset), relatedTo: traceRecording.relatedTo, }, annotation: { id: traceRecording.id, occurrence: 1, operationRelativeStartTime: computedSpan.startOffset, operationRelativeEndTime: computedSpan.startOffset + computedSpan.duration, }, })); const entriesWithComputedSpans = [ ...mappedEntries, ...entriesFromComputedSpans, ].sort((a, b) => { const orderA = order[a.type] ?? 100; const orderB = order[b.type] ?? 100; return orderA - orderB; }); const spansWithDuration = entriesWithComputedSpans .filter((task) => task.span.duration > 0) .filter((task) => (displayResources || task.type !== 'resource') && (displayMeasures || task.type !== 'measure')); const spanEvents = entriesWithComputedSpans.filter((entry) => entry.span.duration === 0); const spanTypes = new Set(spansWithDuration.map((entry) => entry.type)); const uniqueGroups = [ ...new Set(spansWithDuration.map((task) => task.groupName)), ]; return { name: traceRecording.name, spansWithDuration, uniqueGroups, spanEvents, spanTypes, duration: traceRecording.duration ?? traceRecording.entries.at(-1)?.annotation.operationRelativeEndTime ?? 0, }; }; exports.mapOperationForVisualization = mapOperationForVisualization; //# sourceMappingURL=mapOperationForVisualization.js.map