UNPKG

@zendesk/react-measure-timing-hooks

Version:

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

123 lines 4.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.defaultEmbedSpanSelector = void 0; exports.isRenderEntry = isRenderEntry; exports.getSpanSummaryAttributes = getSpanSummaryAttributes; exports.convertTraceToRUM = convertTraceToRUM; /* eslint-disable @typescript-eslint/consistent-indexed-object-style */ const getSpanKey_1 = require("./getSpanKey"); function isRenderEntry(entry) { return (entry.type === 'component-render' || entry.type === 'component-render-start' || entry.type === 'component-unmount'); } function updateEmbeddedEntry(embeddedEntry, spanAndAnnotation) { const { annotation, span } = spanAndAnnotation; return { count: embeddedEntry.count + 1, totalDuration: embeddedEntry.totalDuration + span.duration, spans: [ ...embeddedEntry.spans, { startOffset: annotation.operationRelativeStartTime, duration: span.duration, }, ], }; } function createEmbeddedEntry({ span, annotation, }) { return { count: 1, totalDuration: span.duration, spans: [ { startOffset: annotation.operationRelativeStartTime, duration: span.duration, }, ], }; } const defaultEmbedSpanSelector = (spanAndAnnotation) => { const { span } = spanAndAnnotation; return isRenderEntry(span); }; exports.defaultEmbedSpanSelector = defaultEmbedSpanSelector; function getSpanSummaryAttributes(recordedItems) { // loop through recorded items, create a entry based on the name const spanAttributes = {}; for (const { span } of recordedItems) { const { attributes, name } = span; const existingAttributes = spanAttributes[name] ?? {}; if (attributes && Object.keys(attributes).length > 0) { spanAttributes[name] = { ...existingAttributes, ...attributes, }; } } return spanAttributes; } function recursivelyRoundValues(obj, roundFunc = (x) => Math.round(x)) { const result = {}; for (const [key, value] of Object.entries(obj)) { if (typeof value === 'number') { result[key] = roundFunc(value); } else if (Array.isArray(value)) { result[key] = value.map((item) => typeof item === 'number' ? roundFunc(item) : // Keep strings intact - don't process them typeof item === 'string' ? item : recursivelyRoundValues(item, roundFunc)); } else if (value && typeof value === 'object') { result[key] = recursivelyRoundValues(value, roundFunc); } else { result[key] = value; } } return result; } function convertTraceToRUM(traceRecording, context, embedSpanSelector = exports.defaultEmbedSpanSelector) { const { entries, ...otherTraceRecordingAttributes } = traceRecording; const embeddedEntries = []; const nonEmbeddedSpans = new Set(); const spanAttributes = getSpanSummaryAttributes(traceRecording.entries); for (const spanAndAnnotation of entries) { const isEmbedded = embedSpanSelector(spanAndAnnotation, context); if (isEmbedded) { embeddedEntries.push(spanAndAnnotation); } else { nonEmbeddedSpans.add((0, getSpanKey_1.getSpanKey)(spanAndAnnotation.span)); } } const embeddedSpans = new Map(); for (const spanAndAnnotation of embeddedEntries) { const { span } = spanAndAnnotation; const typeAndName = (0, getSpanKey_1.getSpanKey)(span); const existingEmbeddedEntry = embeddedSpans.get(typeAndName); if (existingEmbeddedEntry) { embeddedSpans.set(typeAndName, updateEmbeddedEntry(existingEmbeddedEntry, spanAndAnnotation)); } else { embeddedSpans.set(typeAndName, createEmbeddedEntry(spanAndAnnotation)); } } // Filter out entries with zero duration for (const [key, value] of embeddedSpans) { if (value.totalDuration === 0) { embeddedSpans.delete(key); } } const result = { ...otherTraceRecordingAttributes, embeddedSpans: Object.fromEntries(embeddedSpans), nonEmbeddedSpans: [...nonEmbeddedSpans], spanAttributes, }; return recursivelyRoundValues(result); } //# sourceMappingURL=convertToRum.js.map