@zendesk/react-measure-timing-hooks
Version:
react hooks for measuring time to interactive and time to render of components
123 lines • 4.54 kB
JavaScript
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
;