@zendesk/retrace
Version:
define and capture Product Operation Traces along with computed metrics with an optional friendly React beacon API
74 lines • 3.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateUseBeacon = void 0;
const react_1 = require("react");
const ErrorBoundary_1 = require("../ErrorBoundary");
/**
* The job of the beacon:
* emit component-render-start, component-render, component-unmount entries
* (or hook-render-start, hook-render, hook-unmount based on the isHook option)
*/
const generateUseBeacon = (traceManager) => ({ isHook = false, ...config }) => {
const renderCountRef = (0, react_1.useRef)(0);
renderCountRef.current += 1;
const { attributes, renderedOutput } = config;
const status = config.error ? 'error' : 'ok';
const isIdle = config.isIdle ??
(renderedOutput === 'content' || renderedOutput === 'error');
const relatedTo = config.relatedTo;
const parentSpanRef = (0, react_1.useRef)();
if (config.parentSpan) {
parentSpanRef.current = config.parentSpan;
}
const renderStartEntry = traceManager.startRenderSpan({
...config,
kind: isHook ? 'hook' : 'component',
relatedTo,
attributes,
status,
renderCount: renderCountRef.current,
isIdle,
parentSpan: parentSpanRef.current,
});
const renderStartRef = (0, react_1.useRef)(renderStartEntry);
renderStartRef.current = renderStartEntry;
// Beacon effect for tracking 'component-render'. This will fire after every render as it does not have any dependencies:
(0, react_1.useEffect)(() => {
const maybeNewParent = renderStartRef.current.resolveParent(true);
parentSpanRef.current = maybeNewParent ?? parentSpanRef.current;
const currentTrace = traceManager.currentTraceContext;
if (currentTrace &&
!currentTrace.recordedItems.has(renderStartRef.current.span.id)) {
// handle edge case where the component mounted before the trace was started
renderStartRef.current = traceManager.createAndProcessSpan({
...renderStartRef.current.span,
parentSpan: parentSpanRef.current,
// if startTime is before the trace start time, we set it to undefined
// to ensure the span is added to the trace
startTime: renderStartRef.current.span.startTime.now <
currentTrace.input.startTime.now
? undefined
: renderStartRef.current.span.startTime,
});
}
traceManager.endRenderSpan(renderStartRef.current.span);
});
// Beacon effect for tracking 'component-unmount' entries
(0, ErrorBoundary_1.useOnComponentUnmount)((errorBoundaryMetadata) => {
traceManager.createAndProcessSpan({
...config,
relatedTo,
type: isHook ? 'hook-unmount' : 'component-unmount',
attributes,
error: errorBoundaryMetadata?.error,
errorInfo: errorBoundaryMetadata?.errorInfo,
status: errorBoundaryMetadata?.error ? 'error' : 'ok',
renderCount: renderCountRef.current,
isIdle,
parentSpan: renderStartRef.current?.span,
});
}, [config.name]);
return renderStartEntry;
};
exports.generateUseBeacon = generateUseBeacon;
//# sourceMappingURL=hooks.js.map