UNPKG

datadog-ux-utils

Version:

Datadog RUM focused UX & performance toolkit: API guards (retry, breaker, rate), React telemetry (error boundary, profiler, Suspense), web vitals & resource observers, offline queues.

647 lines (646 loc) 19.2 kB
import de, { Component as we, useMemo as X, useRef as C, Profiler as ce, useEffect as D, Suspense as Re, useCallback as B } from "react"; import { datadogRum as le } from "@datadog/browser-rum"; import { g as ue } from "./config-D7lUKPO2.js"; import { a as H, c as pe } from "./datadog-irY4zUa4.js"; import { a as ie } from "./rateGuard-DVhJO_z1.js"; import { r as Ee } from "./componentTelemetry-B8Ifhf_1.js"; class xe extends we { constructor() { super(...arguments), this.state = { hasError: !1 }; } /** * Updates state so the next render shows the fallback UI. */ static getDerivedStateFromError() { return { hasError: !0 }; } /** * Reports the error to Datadog RUM with boundary name, stack, and app name. * @param error - The error thrown by a child component. * @param info - React error info (component stack). */ componentDidCatch(n, l) { const { name: a } = this.props; le.addError(n, { boundary: a ?? "ErrorBoundary", componentStack: l.componentStack, app: ue().appName }); } /** * Renders the fallback UI if an error was caught, otherwise renders children. */ render() { return this.state.hasError ? this.props.fallback ?? null : this.props.children; } } var J = { exports: {} }, O = {}; /** * @license React * react-jsx-runtime.production.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var te; function he() { if (te) return O; te = 1; var t = Symbol.for("react.transitional.element"), n = Symbol.for("react.fragment"); function l(a, r, s) { var c = null; if (s !== void 0 && (c = "" + s), r.key !== void 0 && (c = "" + r.key), "key" in r) { s = {}; for (var i in r) i !== "key" && (s[i] = r[i]); } else s = r; return r = s.ref, { $$typeof: t, type: a, key: c, ref: r !== void 0 ? r : null, props: s }; } return O.Fragment = n, O.jsx = l, O.jsxs = l, O; } var j = {}; /** * @license React * react-jsx-runtime.development.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var ne; function be() { return ne || (ne = 1, process.env.NODE_ENV !== "production" && function() { function t(e) { if (e == null) return null; if (typeof e == "function") return e.$$typeof === $ ? null : e.displayName || e.name || null; if (typeof e == "string") return e; switch (e) { case m: return "Fragment"; case h: return "Profiler"; case W: return "StrictMode"; case N: return "Suspense"; case x: return "SuspenseList"; case M: return "Activity"; } if (typeof e == "object") switch (typeof e.tag == "number" && console.error( "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue." ), e.$$typeof) { case d: return "Portal"; case L: return (e.displayName || "Context") + ".Provider"; case g: return (e._context.displayName || "Context") + ".Consumer"; case F: var o = e.render; return e = e.displayName, e || (e = o.displayName || o.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e; case A: return o = e.displayName || null, o !== null ? o : t(e.type) || "Memo"; case Y: o = e._payload, e = e._init; try { return t(e(o)); } catch { } } return null; } function n(e) { return "" + e; } function l(e) { try { n(e); var o = !1; } catch { o = !0; } if (o) { o = console; var u = o.error, w = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object"; return u.call( o, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", w ), n(e); } } function a(e) { if (e === m) return "<>"; if (typeof e == "object" && e !== null && e.$$typeof === Y) return "<...>"; try { var o = t(e); return o ? "<" + o + ">" : "<...>"; } catch { return "<...>"; } } function r() { var e = k.A; return e === null ? null : e.getOwner(); } function s() { return Error("react-stack-top-frame"); } function c(e) { if (I.call(e, "key")) { var o = Object.getOwnPropertyDescriptor(e, "key").get; if (o && o.isReactWarning) return !1; } return e.key !== void 0; } function i(e, o) { function u() { Z || (Z = !0, console.error( "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", o )); } u.isReactWarning = !0, Object.defineProperty(e, "key", { get: u, configurable: !0 }); } function f() { var e = t(this.type); return Q[e] || (Q[e] = !0, console.error( "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release." )), e = this.props.ref, e !== void 0 ? e : null; } function _(e, o, u, w, y, v, q, G) { return u = v.ref, e = { $$typeof: p, type: e, key: o, props: v, _owner: y }, (u !== void 0 ? u : null) !== null ? Object.defineProperty(e, "ref", { enumerable: !1, get: f }) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", { configurable: !1, enumerable: !1, writable: !0, value: 0 }), Object.defineProperty(e, "_debugInfo", { configurable: !1, enumerable: !1, writable: !0, value: null }), Object.defineProperty(e, "_debugStack", { configurable: !1, enumerable: !1, writable: !0, value: q }), Object.defineProperty(e, "_debugTask", { configurable: !1, enumerable: !1, writable: !0, value: G }), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e; } function E(e, o, u, w, y, v, q, G) { var R = o.children; if (R !== void 0) if (w) if (fe(R)) { for (w = 0; w < R.length; w++) b(R[w]); Object.freeze && Object.freeze(R); } else console.error( "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead." ); else b(R); if (I.call(o, "key")) { R = t(e); var P = Object.keys(o).filter(function(me) { return me !== "key"; }); w = 0 < P.length ? "{key: someKey, " + P.join(": ..., ") + ": ...}" : "{key: someKey}", re[R + w] || (P = 0 < P.length ? "{" + P.join(": ..., ") + ": ...}" : "{}", console.error( `A props object containing a "key" prop is being spread into JSX: let props = %s; <%s {...props} /> React keys must be passed directly to JSX without using spread: let props = %s; <%s key={someKey} {...props} />`, w, R, P, R ), re[R + w] = !0); } if (R = null, u !== void 0 && (l(u), R = "" + u), c(o) && (l(o.key), R = "" + o.key), "key" in o) { u = {}; for (var z in o) z !== "key" && (u[z] = o[z]); } else u = o; return R && i( u, typeof e == "function" ? e.displayName || e.name || "Unknown" : e ), _( e, R, v, y, r(), u, q, G ); } function b(e) { typeof e == "object" && e !== null && e.$$typeof === p && e._store && (e._store.validated = 1); } var T = de, p = Symbol.for("react.transitional.element"), d = Symbol.for("react.portal"), m = Symbol.for("react.fragment"), W = Symbol.for("react.strict_mode"), h = Symbol.for("react.profiler"), g = Symbol.for("react.consumer"), L = Symbol.for("react.context"), F = Symbol.for("react.forward_ref"), N = Symbol.for("react.suspense"), x = Symbol.for("react.suspense_list"), A = Symbol.for("react.memo"), Y = Symbol.for("react.lazy"), M = Symbol.for("react.activity"), $ = Symbol.for("react.client.reference"), k = T.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, I = Object.prototype.hasOwnProperty, fe = Array.isArray, V = console.createTask ? console.createTask : function() { return null; }; T = { react_stack_bottom_frame: function(e) { return e(); } }; var Z, Q = {}, K = T.react_stack_bottom_frame.bind( T, s )(), ee = V(a(s)), re = {}; j.Fragment = m, j.jsx = function(e, o, u, w, y) { var v = 1e4 > k.recentlyCreatedOwnerStacks++; return E( e, o, u, !1, w, y, v ? Error("react-stack-top-frame") : K, v ? V(a(e)) : ee ); }, j.jsxs = function(e, o, u, w, y) { var v = 1e4 > k.recentlyCreatedOwnerStacks++; return E( e, o, u, !0, w, y, v ? Error("react-stack-top-frame") : K, v ? V(a(e)) : ee ); }; }()), j; } process.env.NODE_ENV === "production" ? J.exports = he() : J.exports = be(); var S = J.exports; function Oe({ id: t, options: n, children: l, __onRenderSpy: a }) { const r = X( () => ({ enabled: n?.enabled ?? (typeof process < "u" && process.env && process.env.NODE_ENV !== "production"), windowMs: n?.windowMs ?? 2e3, commitsPerSecThreshold: n?.commitsPerSecThreshold ?? 5, renderMsPerSecThreshold: n?.renderMsPerSecThreshold ?? 24, minCommits: n?.minCommits ?? 3, cooldownMs: n?.cooldownMs ?? 5e3, telemetrySampleRate: typeof n?.telemetrySampleRate == "number" ? _e(n.telemetrySampleRate) : 20, telemetryActionName: n?.telemetryActionName ?? "render_hotspot", onHotspot: n?.onHotspot ?? Se, includeProfilerDetails: n?.includeProfilerDetails ?? !0, context: n?.context ?? {} }), [n] ), s = C([]), c = C(0), i = (_, E, b, T, p, d) => { if (!r.enabled) return; const m = p, W = m - r.windowMs; s.current.push({ t: m, d: b, bd: r.includeProfilerDetails ? T : void 0, ph: E ?? "unknown" }); const h = s.current; for (; h.length && h[0].t < W; ) h.shift(); if (process.env.NODE_ENV === "test" && console.log( "[RenderDetector] buffer:", h.map((k) => k.t), "commitsInWindow:", h.length ), h.length < r.minCommits) return; const g = h.length, L = h.reduce((k, I) => k + I.d, 0), F = r.windowMs / 1e3, N = g / F, x = L / F; process.env.NODE_ENV === "test" && console.log("[RenderDetector] metrics:", { commitsPerSec: N, renderMsPerSec: x, commitsInWindow: g }); const A = []; if (N > r.commitsPerSecThreshold && A.push("commits_per_sec"), x > r.renderMsPerSecThreshold && A.push("render_ms_per_sec"), A.length === 0) return; const Y = c.current; if (m - Y < r.cooldownMs) return; c.current = m, process.env.NODE_ENV === "test" && console.log("[RenderDetector] HOTSPOT!", { reasons: A, now: m }); const M = h[h.length - 1], $ = { id: t, commitsPerSec: U(N), renderMsPerSec: U(x), commitsInWindow: g, windowMs: r.windowMs, reasons: A, at: m, lastCommit: r.includeProfilerDetails ? { phase: M.ph, actualDurationMs: U(M.d), baseDurationMs: M.bd != null ? U(M.bd) : void 0 } : void 0, context: r.context }; try { r.onHotspot($); } catch { } if (r.telemetrySampleRate > 0 && ve(r.telemetrySampleRate)) try { H( r.telemetryActionName, $, r.telemetrySampleRate ); } catch { } }; if (!r.enabled) return /* @__PURE__ */ S.jsx(S.Fragment, { children: l }); const f = ce; return /* @__PURE__ */ S.jsx(f, { id: t, onRender: a || i, children: l }); } function Se() { } function U(t) { return Math.round(t * 100) / 100; } function _e(t) { return Number.isNaN(t) ? 0 : Math.max(0, Math.min(100, Math.round(t))); } function ve(t) { return Math.random() * 100 < t; } const je = ({ id: t, children: n }) => { const l = ue(), a = (r, s, c, i, f, _) => { c >= l.renderSlowMs && le.addAction("render_slow", { id: t, actual_ms: Math.round(c), base_ms: Math.round(i), started_at: Math.round(f), committed_at: Math.round(_), threshold_ms: l.renderSlowMs }); }; return /* @__PURE__ */ S.jsx(ce, { id: t, onRender: a, children: n }); }; function Ce({ id: t, children: n, fallback: l, options: a }) { const r = C({ timeoutMs: a?.timeoutMs ?? 1200, sampleRate: oe(a?.sampleRate ?? 20), reportResolveAfterSlow: a?.reportResolveAfterSlow ?? !0, actionNames: { slow: a?.actionNames?.slow ?? "suspense_slow", resolved: a?.actionNames?.resolved ?? "suspense_resolved_after_slow" }, onSlow: a?.onSlow ?? se, onResolvedAfterSlow: a?.onResolvedAfterSlow ?? se, alsoReportError: a?.alsoReportError ?? !1 }); D(() => { r.current = { ...r.current, timeoutMs: a?.timeoutMs ?? r.current.timeoutMs, sampleRate: oe(a?.sampleRate ?? r.current.sampleRate), reportResolveAfterSlow: a?.reportResolveAfterSlow ?? r.current.reportResolveAfterSlow, actionNames: { slow: a?.actionNames?.slow ?? r.current.actionNames.slow, resolved: a?.actionNames?.resolved ?? r.current.actionNames.resolved }, onSlow: a?.onSlow ?? r.current.onSlow, onResolvedAfterSlow: a?.onResolvedAfterSlow ?? r.current.onResolvedAfterSlow, alsoReportError: a?.alsoReportError ?? r.current.alsoReportError }; }, [a]); const s = C(null), c = () => { const { timeoutMs: p } = r.current, d = performance.now(); b(!1), s.current = { fallbackStart: d, slowEmitted: !1, slowTimer: null }; const m = window.setTimeout(() => { E(d); }, p); s.current.slowTimer = m; }, i = () => { }, f = () => { const p = s.current; if (p) { if (p.slowEmitted && r.current.reportResolveAfterSlow) { const d = Math.round(performance.now() - p.fallbackStart), m = { id: t, timeoutMs: r.current.timeoutMs, fallbackStart: p.fallbackStart, fallbackVisibleMs: d }; try { r.current.onResolvedAfterSlow(m); } catch { } if (r.current.sampleRate > 0 && ae(r.current.sampleRate)) try { H( r.current.actionNames.resolved || "suspense_resolved_after_slow", m, r.current.sampleRate ); } catch { } } b(!0); } }, _ = () => { b(!1); }; function E(p) { const d = s.current; if (!d || d.slowEmitted) return; d.slowEmitted = !0; const m = { id: t, timeoutMs: r.current.timeoutMs, fallbackStart: p }; try { r.current.onSlow(m); } catch { } if (r.current.sampleRate > 0 && ae(r.current.sampleRate)) { try { H( r.current.actionNames.slow || "suspense_slow", m, r.current.sampleRate ); } catch { } if (r.current.alsoReportError) try { pe( new Error(`[suspense] ${t} exceeded ${r.current.timeoutMs}ms`), m, r.current.sampleRate ); } catch { } } } function b(p) { const d = s.current; d && (d.slowTimer != null && (clearTimeout(d.slowTimer), d.slowTimer = null), p && (s.current = null)); } const T = Re; return /* @__PURE__ */ S.jsx( T, { fallback: /* @__PURE__ */ S.jsx( Te, { onMount: c, onUnmount: i, children: l } ), children: /* @__PURE__ */ S.jsx(ye, { onMount: f, onUnmount: _, children: n }) } ); } function Te({ onMount: t, onUnmount: n, children: l }) { return D(() => (t(), n), []), /* @__PURE__ */ S.jsx(S.Fragment, { children: l }); } function ye({ onMount: t, onUnmount: n, children: l }) { return D(() => (t(), n), []), /* @__PURE__ */ S.jsx(S.Fragment, { children: l }); } function oe(t) { return Number.isNaN(t) ? 0 : Math.max(0, Math.min(100, Math.round(t))); } function ae(t) { return Math.random() * 100 < t; } function se() { } function De(t, n) { const l = n?.retryAfter ?? "none", a = C(n?.cancelSignal ?? null); D(() => { a.current = n?.cancelSignal ?? null; }, [n?.cancelSignal]); const r = B(async (c) => { c <= 0 || await new Promise((i, f) => { const _ = setTimeout(i, c), E = a.current, b = () => { clearTimeout(_), f(new DOMException("Aborted", "AbortError")); }; if (E) { if (E.aborted) return b(); E.addEventListener("abort", b, { once: !0 }); } }); }, []), s = B( async (c, i) => { try { return await t.guardFetch(c, i); } catch (f) { if (f instanceof ie && (n?.onBlocked?.({ key: f.key, until: f.until, windowMs: f.windowMs, maxRequests: f.maxRequests }), l === "wait")) { const _ = f.until - Date.now(); try { return await r(_), await t.guardFetch(c, i); } catch (E) { throw E; } } throw f; } }, [t, l, r, n] ); return X(() => s, [s]); } function Fe(t, n) { const l = n?.retryAfter ?? "none", a = B( async (r, s) => { try { return await t.guard(r, s); } catch (c) { if (c instanceof ie && (n?.onBlocked?.({ key: c.key, until: c.until, windowMs: c.windowMs, maxRequests: c.maxRequests }), l === "wait")) { const i = c.until - Date.now(); return i > 0 && await new Promise((f) => setTimeout(f, i)), t.guard(r, s); } throw c; } }, [t, l, n] ); return X(() => a, [a]); } function Ye(t, n) { D(() => { Ee(t, n); }, []); } export { xe as E, Oe as R, Ce as S, je as a, Fe as b, Ye as c, De as u }; //# sourceMappingURL=useComponentTelemetry-XkbS4jed.js.map