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
JavaScript
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