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.

24 lines (23 loc) 13.5 kB
"use strict";const i=require("react"),oe=require("@datadog/browser-rum"),ae=require("./config-ByuBXTv9.cjs"),q=require("./datadog-DV4lp5AO.cjs"),se=require("./rateGuard-KzvlZG_6.cjs"),ue=require("./componentTelemetry-C9z5F0HB.cjs");class ie extends i.Component{constructor(){super(...arguments),this.state={hasError:!1}}static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(n,l){const{name:a}=this.props;oe.datadogRum.addError(n,{boundary:a??"ErrorBoundary",componentStack:l.componentStack,app:ae.getUxConfig().appName})}render(){return this.state.hasError?this.props.fallback??null:this.props.children}}var z={exports:{}},j={};/** * @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 K;function fe(){if(K)return j;K=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 f in r)f!=="key"&&(s[f]=r[f])}else s=r;return r=s.ref,{$$typeof:t,type:a,key:c,ref:r!==void 0?r:null,props:s}}return j.Fragment=n,j.jsx=l,j.jsxs=l,j}var C={};/** * @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 ee;function me(){return ee||(ee=1,process.env.NODE_ENV!=="production"&&function(){function t(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===Y?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case d:return"Fragment";case b:return"Profiler";case U:return"StrictMode";case x:return"Suspense";case O:return"SuspenseList";case P: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 w:return"Portal";case W:return(e.displayName||"Context")+".Provider";case N:return(e._context.displayName||"Context")+".Consumer";case D:var o=e.render;return e=e.displayName,e||(e=o.displayName||o.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case k:return o=e.displayName||null,o!==null?o:t(e.type)||"Memo";case F: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,R=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.",R),n(e)}}function a(e){if(e===d)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===F)return"<...>";try{var o=t(e);return o?"<"+o+">":"<...>"}catch{return"<...>"}}function r(){var e=M.A;return e===null?null:e.getOwner()}function s(){return Error("react-stack-top-frame")}function c(e){if($.call(e,"key")){var o=Object.getOwnPropertyDescriptor(e,"key").get;if(o&&o.isReactWarning)return!1}return e.key!==void 0}function f(e,o){function u(){H||(H=!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 m(){var e=t(this.type);return J[e]||(J[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 v(e,o,u,R,A,T,V,G){return u=T.ref,e={$$typeof:p,type:e,key:o,props:T,_owner:A},(u!==void 0?u:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:m}):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:V}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:G}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function h(e,o,u,R,A,T,V,G){var E=o.children;if(E!==void 0)if(R)if(ce(E)){for(R=0;R<E.length;R++)S(E[R]);Object.freeze&&Object.freeze(E)}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 S(E);if($.call(o,"key")){E=t(e);var g=Object.keys(o).filter(function(le){return le!=="key"});R=0<g.length?"{key: someKey, "+g.join(": ..., ")+": ...}":"{key: someKey}",Q[E+R]||(g=0<g.length?"{"+g.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} />`,R,E,g,E),Q[E+R]=!0)}if(E=null,u!==void 0&&(l(u),E=""+u),c(o)&&(l(o.key),E=""+o.key),"key"in o){u={};for(var B in o)B!=="key"&&(u[B]=o[B])}else u=o;return E&&f(u,typeof e=="function"?e.displayName||e.name||"Unknown":e),v(e,E,T,A,r(),u,V,G)}function S(e){typeof e=="object"&&e!==null&&e.$$typeof===p&&e._store&&(e._store.validated=1)}var y=i,p=Symbol.for("react.transitional.element"),w=Symbol.for("react.portal"),d=Symbol.for("react.fragment"),U=Symbol.for("react.strict_mode"),b=Symbol.for("react.profiler"),N=Symbol.for("react.consumer"),W=Symbol.for("react.context"),D=Symbol.for("react.forward_ref"),x=Symbol.for("react.suspense"),O=Symbol.for("react.suspense_list"),k=Symbol.for("react.memo"),F=Symbol.for("react.lazy"),P=Symbol.for("react.activity"),Y=Symbol.for("react.client.reference"),M=y.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,$=Object.prototype.hasOwnProperty,ce=Array.isArray,L=console.createTask?console.createTask:function(){return null};y={react_stack_bottom_frame:function(e){return e()}};var H,J={},X=y.react_stack_bottom_frame.bind(y,s)(),Z=L(a(s)),Q={};C.Fragment=d,C.jsx=function(e,o,u,R,A){var T=1e4>M.recentlyCreatedOwnerStacks++;return h(e,o,u,!1,R,A,T?Error("react-stack-top-frame"):X,T?L(a(e)):Z)},C.jsxs=function(e,o,u,R,A){var T=1e4>M.recentlyCreatedOwnerStacks++;return h(e,o,u,!0,R,A,T?Error("react-stack-top-frame"):X,T?L(a(e)):Z)}}()),C}process.env.NODE_ENV==="production"?z.exports=fe():z.exports=me();var _=z.exports;function de({id:t,options:n,children:l,__onRenderSpy:a}){const r=i.useMemo(()=>({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"?Re(n.telemetrySampleRate):20,telemetryActionName:n?.telemetryActionName??"render_hotspot",onHotspot:n?.onHotspot??we,includeProfilerDetails:n?.includeProfilerDetails??!0,context:n?.context??{}}),[n]),s=i.useRef([]),c=i.useRef(0),f=(v,h,S,y,p,w)=>{if(!r.enabled)return;const d=p,U=d-r.windowMs;s.current.push({t:d,d:S,bd:r.includeProfilerDetails?y:void 0,ph:h??"unknown"});const b=s.current;for(;b.length&&b[0].t<U;)b.shift();if(process.env.NODE_ENV==="test"&&console.log("[RenderDetector] buffer:",b.map(M=>M.t),"commitsInWindow:",b.length),b.length<r.minCommits)return;const N=b.length,W=b.reduce((M,$)=>M+$.d,0),D=r.windowMs/1e3,x=N/D,O=W/D;process.env.NODE_ENV==="test"&&console.log("[RenderDetector] metrics:",{commitsPerSec:x,renderMsPerSec:O,commitsInWindow:N});const k=[];if(x>r.commitsPerSecThreshold&&k.push("commits_per_sec"),O>r.renderMsPerSecThreshold&&k.push("render_ms_per_sec"),k.length===0)return;const F=c.current;if(d-F<r.cooldownMs)return;c.current=d,process.env.NODE_ENV==="test"&&console.log("[RenderDetector] HOTSPOT!",{reasons:k,now:d});const P=b[b.length-1],Y={id:t,commitsPerSec:I(x),renderMsPerSec:I(O),commitsInWindow:N,windowMs:r.windowMs,reasons:k,at:d,lastCommit:r.includeProfilerDetails?{phase:P.ph,actualDurationMs:I(P.d),baseDurationMs:P.bd!=null?I(P.bd):void 0}:void 0,context:r.context};try{r.onHotspot(Y)}catch{}if(r.telemetrySampleRate>0&&Ee(r.telemetrySampleRate))try{q.addAction(r.telemetryActionName,Y,r.telemetrySampleRate)}catch{}};if(!r.enabled)return _.jsx(_.Fragment,{children:l});const m=i.Profiler;return _.jsx(m,{id:t,onRender:a||f,children:l})}function we(){}function I(t){return Math.round(t*100)/100}function Re(t){return Number.isNaN(t)?0:Math.max(0,Math.min(100,Math.round(t)))}function Ee(t){return Math.random()*100<t}const pe=({id:t,children:n})=>{const l=ae.getUxConfig(),a=(r,s,c,f,m,v)=>{c>=l.renderSlowMs&&oe.datadogRum.addAction("render_slow",{id:t,actual_ms:Math.round(c),base_ms:Math.round(f),started_at:Math.round(m),committed_at:Math.round(v),threshold_ms:l.renderSlowMs})};return _.jsx(i.Profiler,{id:t,onRender:a,children:n})};function he({id:t,children:n,fallback:l,options:a}){const r=i.useRef({timeoutMs:a?.timeoutMs??1200,sampleRate:re(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??ne,onResolvedAfterSlow:a?.onResolvedAfterSlow??ne,alsoReportError:a?.alsoReportError??!1});i.useEffect(()=>{r.current={...r.current,timeoutMs:a?.timeoutMs??r.current.timeoutMs,sampleRate:re(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=i.useRef(null),c=()=>{const{timeoutMs:p}=r.current,w=performance.now();S(!1),s.current={fallbackStart:w,slowEmitted:!1,slowTimer:null};const d=window.setTimeout(()=>{h(w)},p);s.current.slowTimer=d},f=()=>{},m=()=>{const p=s.current;if(p){if(p.slowEmitted&&r.current.reportResolveAfterSlow){const w=Math.round(performance.now()-p.fallbackStart),d={id:t,timeoutMs:r.current.timeoutMs,fallbackStart:p.fallbackStart,fallbackVisibleMs:w};try{r.current.onResolvedAfterSlow(d)}catch{}if(r.current.sampleRate>0&&te(r.current.sampleRate))try{q.addAction(r.current.actionNames.resolved||"suspense_resolved_after_slow",d,r.current.sampleRate)}catch{}}S(!0)}},v=()=>{S(!1)};function h(p){const w=s.current;if(!w||w.slowEmitted)return;w.slowEmitted=!0;const d={id:t,timeoutMs:r.current.timeoutMs,fallbackStart:p};try{r.current.onSlow(d)}catch{}if(r.current.sampleRate>0&&te(r.current.sampleRate)){try{q.addAction(r.current.actionNames.slow||"suspense_slow",d,r.current.sampleRate)}catch{}if(r.current.alsoReportError)try{q.addError(new Error(`[suspense] ${t} exceeded ${r.current.timeoutMs}ms`),d,r.current.sampleRate)}catch{}}}function S(p){const w=s.current;w&&(w.slowTimer!=null&&(clearTimeout(w.slowTimer),w.slowTimer=null),p&&(s.current=null))}const y=i.Suspense;return _.jsx(y,{fallback:_.jsx(be,{onMount:c,onUnmount:f,children:l}),children:_.jsx(Se,{onMount:m,onUnmount:v,children:n})})}function be({onMount:t,onUnmount:n,children:l}){return i.useEffect(()=>(t(),n),[]),_.jsx(_.Fragment,{children:l})}function Se({onMount:t,onUnmount:n,children:l}){return i.useEffect(()=>(t(),n),[]),_.jsx(_.Fragment,{children:l})}function re(t){return Number.isNaN(t)?0:Math.max(0,Math.min(100,Math.round(t)))}function te(t){return Math.random()*100<t}function ne(){}function _e(t,n){const l=n?.retryAfter??"none",a=i.useRef(n?.cancelSignal??null);i.useEffect(()=>{a.current=n?.cancelSignal??null},[n?.cancelSignal]);const r=i.useCallback(async c=>{c<=0||await new Promise((f,m)=>{const v=setTimeout(f,c),h=a.current,S=()=>{clearTimeout(v),m(new DOMException("Aborted","AbortError"))};if(h){if(h.aborted)return S();h.addEventListener("abort",S,{once:!0})}})},[]),s=i.useCallback(async(c,f)=>{try{return await t.guardFetch(c,f)}catch(m){if(m instanceof se.ApiRunawayBlockedError&&(n?.onBlocked?.({key:m.key,until:m.until,windowMs:m.windowMs,maxRequests:m.maxRequests}),l==="wait")){const v=m.until-Date.now();try{return await r(v),await t.guardFetch(c,f)}catch(h){throw h}}throw m}},[t,l,r,n]);return i.useMemo(()=>s,[s])}function ve(t,n){const l=n?.retryAfter??"none",a=i.useCallback(async(r,s)=>{try{return await t.guard(r,s)}catch(c){if(c instanceof se.ApiRunawayBlockedError&&(n?.onBlocked?.({key:c.key,until:c.until,windowMs:c.windowMs,maxRequests:c.maxRequests}),l==="wait")){const f=c.until-Date.now();return f>0&&await new Promise(m=>setTimeout(m,f)),t.guard(r,s)}throw c}},[t,l,n]);return i.useMemo(()=>a,[a])}function Te(t,n){i.useEffect(()=>{ue.reportComponentMount(t,n)},[])}exports.ErrorBoundary=ie;exports.RenderDetector=de;exports.RenderProfiler=pe;exports.SuspenseWatch=he;exports.useComponentTelemetry=Te;exports.useGuardedCall=ve;exports.useGuardedFetch=_e; //# sourceMappingURL=useComponentTelemetry-BjZuufzp.cjs.map