@sentry/react-native 6.0.0-beta.0 → 6.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java +18 -11
- package/android/src/main/java/io/sentry/react/RNSentryOnDrawReporterManager.java +18 -1
- package/android/src/newarch/java/io/sentry/react/RNSentryModule.java +2 -2
- package/android/src/oldarch/java/io/sentry/react/RNSentryModule.java +2 -2
- package/dist/js/NativeRNSentry.d.ts +1 -1
- package/dist/js/NativeRNSentry.d.ts.map +1 -1
- package/dist/js/NativeRNSentry.js.map +1 -1
- package/dist/js/client.d.ts.map +1 -1
- package/dist/js/client.js +3 -0
- package/dist/js/client.js.map +1 -1
- package/dist/js/integrations/default.js +3 -3
- package/dist/js/integrations/default.js.map +1 -1
- package/dist/js/options.d.ts +5 -28
- package/dist/js/options.d.ts.map +1 -1
- package/dist/js/options.js.map +1 -1
- package/dist/js/profiling/integration.d.ts +11 -3
- package/dist/js/profiling/integration.d.ts.map +1 -1
- package/dist/js/profiling/integration.js +10 -7
- package/dist/js/profiling/integration.js.map +1 -1
- package/dist/js/replay/mobilereplay.d.ts +1 -1
- package/dist/js/replay/mobilereplay.js.map +1 -1
- package/dist/js/tools/metroconfig.d.ts +11 -2
- package/dist/js/tools/metroconfig.d.ts.map +1 -1
- package/dist/js/tools/metroconfig.js +42 -2
- package/dist/js/tools/metroconfig.js.map +1 -1
- package/dist/js/touchevents.d.ts.map +1 -1
- package/dist/js/touchevents.js +6 -2
- package/dist/js/touchevents.js.map +1 -1
- package/dist/js/tracing/gesturetracing.d.ts.map +1 -1
- package/dist/js/tracing/gesturetracing.js +6 -2
- package/dist/js/tracing/gesturetracing.js.map +1 -1
- package/dist/js/tracing/integrations/appStart.d.ts +14 -0
- package/dist/js/tracing/integrations/appStart.d.ts.map +1 -1
- package/dist/js/tracing/integrations/appStart.js +32 -2
- package/dist/js/tracing/integrations/appStart.js.map +1 -1
- package/dist/js/tracing/integrations/userInteraction.js +2 -2
- package/dist/js/tracing/integrations/userInteraction.js.map +1 -1
- package/dist/js/tracing/origin.d.ts +8 -0
- package/dist/js/tracing/origin.d.ts.map +1 -1
- package/dist/js/tracing/origin.js +8 -0
- package/dist/js/tracing/origin.js.map +1 -1
- package/dist/js/tracing/reactnativenavigation.d.ts.map +1 -1
- package/dist/js/tracing/reactnativenavigation.js +3 -1
- package/dist/js/tracing/reactnativenavigation.js.map +1 -1
- package/dist/js/tracing/reactnativeprofiler.js +3 -3
- package/dist/js/tracing/reactnativeprofiler.js.map +1 -1
- package/dist/js/tracing/reactnativetracing.d.ts.map +1 -1
- package/dist/js/tracing/reactnativetracing.js +8 -2
- package/dist/js/tracing/reactnativetracing.js.map +1 -1
- package/dist/js/tracing/reactnavigation.d.ts.map +1 -1
- package/dist/js/tracing/reactnavigation.js +4 -1
- package/dist/js/tracing/reactnavigation.js.map +1 -1
- package/dist/js/tracing/span.d.ts.map +1 -1
- package/dist/js/tracing/span.js +4 -3
- package/dist/js/tracing/span.js.map +1 -1
- package/dist/js/tracing/timetodisplay.d.ts +1 -0
- package/dist/js/tracing/timetodisplay.d.ts.map +1 -1
- package/dist/js/tracing/timetodisplay.js +16 -3
- package/dist/js/tracing/timetodisplay.js.map +1 -1
- package/dist/js/utils/environment.d.ts +2 -0
- package/dist/js/utils/environment.d.ts.map +1 -1
- package/dist/js/utils/environment.js +4 -0
- package/dist/js/utils/environment.js.map +1 -1
- package/dist/js/version.d.ts +1 -1
- package/dist/js/version.d.ts.map +1 -1
- package/dist/js/version.js +1 -1
- package/dist/js/version.js.map +1 -1
- package/dist/js/wrapper.d.ts +1 -1
- package/dist/js/wrapper.d.ts.map +1 -1
- package/dist/js/wrapper.js +2 -2
- package/dist/js/wrapper.js.map +1 -1
- package/ios/RNSentry.mm +7 -3
- package/package.json +10 -10
- package/scripts/sentry-xcode-debug-files.sh +4 -1
- package/scripts/sentry-xcode.sh +4 -1
- package/src/js/NativeRNSentry.ts +1 -1
- package/ts3.8/dist/js/NativeRNSentry.d.ts +1 -1
- package/ts3.8/dist/js/options.d.ts +5 -28
- package/ts3.8/dist/js/profiling/integration.d.ts +11 -3
- package/ts3.8/dist/js/replay/mobilereplay.d.ts +1 -1
- package/ts3.8/dist/js/tracing/integrations/appStart.d.ts +14 -0
- package/ts3.8/dist/js/tracing/origin.d.ts +8 -0
- package/ts3.8/dist/js/tracing/timetodisplay.d.ts +1 -0
- package/ts3.8/dist/js/utils/environment.d.ts +2 -0
- package/ts3.8/dist/js/version.d.ts +1 -1
- package/ts3.8/dist/js/wrapper.d.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration.js","sourceRoot":"","sources":["../../../src/js/profiling/integration.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEvE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,qCAAqC,EACrC,oCAAoC,GACrC,MAAM,SAAS,CAAC;AAEjB,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AAE3C,MAAM,QAAQ,GAAW,GAAG,CAAC;AAE7B;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAkB,GAAG,EAAE;IAC5D,IAAI,eAMS,CAAC;IACd,IAAI,sBAAiE,CAAC;IACtE,IAAI,OAAO,GAAY,KAAK,CAAC;IAE7B,MAAM,SAAS,GAAG,GAAS,EAAE;QAC3B,IAAI,OAAO,EAAE;YACX,OAAO;SACR;QACD,OAAO,GAAG,IAAI,CAAC;QAEf,IAAI,CAAC,eAAe,EAAE,EAAE;YACtB,MAAM,CAAC,GAAG,CAAC,sEAAsE,CAAC,CAAC;YACnF,OAAO;SACR;QAED,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAE3B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,UAAU,EAAE;YAC9C,OAAO;SACR;QAED,wCAAwC,EAAE,CAAC;QAC3C,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,oBAAoB,CAAC,CAAC;QAE7C,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,4BAA4B,CAAC,CAAC;QAEnD,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,QAAkB,EAAE,EAAE;YACjD,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE;gBACzB,OAAO;aACR;YAED,MAAM,oBAAoB,GAAG,oCAAoC,CAAC,QAAQ,CAAC,CAAC;YAC5E,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE;gBAChC,MAAM,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;gBACrE,OAAO;aACR;YAED,MAAM,uBAAuB,GAAmB,EAAE,CAAC;YACnD,KAAK,MAAM,mBAAmB,IAAI,oBAAoB,EAAE;gBACtD,MAAM,OAAO,GAAG,sBAAsB,CAAC,mBAAmB,CAAC,CAAC;gBAC5D,IAAI,OAAO,EAAE;oBACX,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;iBACvC;aACF;YACD,qBAAqB,CAAC,QAAQ,EAAE,uBAAuB,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,wCAAwC,GAAG,GAAS,EAAE;QAC1D,IAAI,eAAe,EAAE;YACnB,OAAO;SACR;QACD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;QACnC,UAAU,IAAI,oBAAoB,CAAC,UAAU,CAAC,CAAC;IACjD,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,CAAC,UAAgB,EAAQ,EAAE;QACtD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;YAC3B,OAAO;SACR;QAED,qBAAqB,EAAE,CAAC;QAExB,MAAM,oBAAoB,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;QAC/D,IAAI,CAAC,oBAAoB,EAAE;YACzB,OAAO;SACR;QAED,sBAAsB,GAAG,UAAU,CAAC,qBAAqB,EAAE,uBAAuB,CAAC,CAAC;QACpF,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEF,MAAM,qBAAqB,GAAG,CAAC,UAAgB,EAAW,EAAE;QAC1D,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE;YAC9B,MAAM,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC;YACzE,OAAO,KAAK,CAAC;SACd;QAED,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,MAAM,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAE9C,MAAM,kBAAkB,GACtB,OAAO,IAAI,OAAO,CAAC,YAAY,IAAI,OAAO,OAAO,CAAC,YAAY,CAAC,kBAAkB,KAAK,QAAQ;YAC5F,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,kBAAkB;YACzC,CAAC,CAAC,SAAS,CAAC;QAChB,IAAI,kBAAkB,KAAK,SAAS,EAAE;YACpC,MAAM,CAAC,GAAG,CAAC,oGAAoG,CAAC,CAAC;YACjH,OAAO,KAAK,CAAC;SACd;QAED,yCAAyC;QACzC,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,kBAAkB,EAAE;YACtC,MAAM,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;YACtE,OAAO,KAAK,CAAC;SACd;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF;;OAEG;IACH,MAAM,gBAAgB,GAAG,CAAC,UAAgB,EAAQ,EAAE;QAClD,MAAM,uBAAuB,GAAG,cAAc,EAAE,CAAC;QACjD,IAAI,CAAC,uBAAuB,EAAE;YAC5B,OAAO;SACR;QAED,eAAe,GAAG;YAChB,OAAO,EAAE,UAAU,CAAC,WAAW,EAAE,CAAC,MAAM;YACxC,UAAU,EAAE,KAAK,EAAE;YACnB,gBAAgB,EAAE,uBAAuB;SAC1C,CAAC;QACF,UAAU,CAAC,YAAY,CAAC,YAAY,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;QAClE,MAAM,CAAC,GAAG,CAAC,iCAAiC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IAC5E,CAAC,CAAC;IAEF;;OAEG;IACH,MAAM,4BAA4B,GAAG,CAAC,IAAU,EAAQ,EAAE;QACxD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;YACrB,OAAO;SACR;QAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,MAAK,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,OAAO,CAAA,EAAE;YAC1D,MAAM,CAAC,GAAG,CACR,qBAAqB,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,+CAC5C,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,OACnB,4BAA4B,CAC7B,CAAC;YACF,OAAO;SACR;QAED,qBAAqB,EAAE,CAAC;IAC1B,CAAC,CAAC;IAEF;;OAEG;IACH,MAAM,qBAAqB,GAAG,GAAS,EAAE;QACvC,2BAA2B,EAAE,CAAC;QAC9B,IAAI,eAAe,KAAK,SAAS,EAAE;YACjC,OAAO;SACR;QAED,MAAM,OAAO,GAAG,aAAa,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC;QAChE,IAAI,CAAC,OAAO,EAAE;YACZ,MAAM,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;YACvD,eAAe,GAAG,SAAS,CAAC;YAC5B,OAAO;SACR;QAED,aAAa,CAAC,GAAG,CAAC,eAAe,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAEvD,MAAM,CAAC,GAAG,CAAC,kCAAkC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;QAC3E,eAAe,GAAG,SAAS,CAAC;IAC9B,CAAC,CAAC;IAEF,MAAM,sBAAsB,GAAG,CAAC,mBAA0B,EAAuB,EAAE;;QACjF,MAAM,UAAU,GAAG,MAAA,MAAA,MAAA,mBAAmB,aAAnB,mBAAmB,uBAAnB,mBAAmB,CAAE,QAAQ,0CAAE,KAAK,0CAAE,IAAI,0CAAE,UAAU,CAAC;QAE1E,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE;YAClC,MAAM,CAAC,GAAG,CAAC,6EAA6E,CAAC,CAAC;YAC1F,OAAO,IAAI,CAAC;SACb;QAED,oGAAoG;QACpG,IAAI,MAAA,MAAA,MAAA,mBAAmB,aAAnB,mBAAmB,uBAAnB,mBAAmB,CAAE,QAAQ,0CAAE,KAAK,0CAAE,IAAI,0CAAE,UAAU,EAAE;YAC1D,OAAO,mBAAmB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;SAC3D;QAED,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC9C,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAEjC,IAAI,CAAC,OAAO,EAAE;YACZ,MAAM,CAAC,GAAG,CAAC,mCAAmC,UAAU,oBAAoB,mBAAmB,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC5G,OAAO,IAAI,CAAC;SACb;QAED,MAAM,gBAAgB,GAAG,qCAAqC,CAAC,UAAU,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACzG,MAAM,CAAC,GAAG,CAAC,+BAA+B,UAAU,oBAAoB,mBAAmB,CAAC,QAAQ,EAAE,CAAC,CAAC;QAExG,OAAO,gBAAgB,CAAC;IAC1B,CAAC,CAAC;IAEF,MAAM,2BAA2B,GAAG,GAAS,EAAE;QAC7C,sBAAsB,KAAK,SAAS,IAAI,YAAY,CAAC,sBAAsB,CAAC,CAAC;QAC7E,sBAAsB,GAAG,SAAS,CAAC;IACrC,CAAC,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,gBAAgB;QACtB,SAAS;KACV,CAAC;AACJ,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;IACxC,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,IAAI,CAAC;KACb;IAED,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,uBAA+B;IAE/B,MAAM,iBAAiB,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;IACjD,IAAI,CAAC,iBAAiB,EAAE;QACtB,OAAO,IAAI,CAAC;KACb;IACD,MAAM,qBAAqB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC;IAEpD,MAAM,aAAa,GAAG,sBAAsB,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC;IAC9E,IAAI,CAAC,aAAa,EAAE;QAClB,OAAO,IAAI,CAAC;KACb;IAED,MAAM,kBAAkB,GAAG,0BAA0B,CAAC,aAAa,CAAC,CAAC;IACrE,IAAI,CAAC,kBAAkB,EAAE;QACvB,OAAO,IAAI,CAAC;KACb;IAED,IAAI,iBAAiB,CAAC,cAAc,EAAE;QACpC,MAAM,UAAU,GAAG,qBAAqB,GAAG,uBAAuB,CAAC;QACnE,OAAO,8BAA8B,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;KACzG;SAAM,IAAI,iBAAiB,CAAC,aAAa,EAAE;QAC1C,OAAO,+BAA+B,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,aAAa,CAAC,CAAC;KAC7F;IAED,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,8BAA8B,CAC5C,MAA0B,EAC1B,aAAwC,EACxC,UAAkB;IAElB,uCACK,aAAa,KAChB,QAAQ,EAAE,SAAS,EACnB,UAAU,EAAE,MAAM,CAAC,OAAO,EAC1B,WAAW,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,EACpC,gBAAgB,EAAE,MAAM,CAAC,WAAW,CAAC,gBAAgB,IACrD;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,+BAA+B,CAC7C,MAA0B,EAC1B,MAA0B;IAE1B,uCACK,MAAM,KACT,OAAO,EAAE,iCAAiC,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,EAC/G,UAAU,EAAE;YACV,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM;SACjC,EACD,YAAY,EAAE,MAAM,CAAC,YAAY,IACjC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iCAAiC,CAC/C,MAAwB,EACxB,MAAwB,EACxB,uBAA2C;IAE3C,gCAAgC;IAChC,MAAM,CAAC,eAAe,mCAAQ,MAAM,CAAC,eAAe,GAAK,MAAM,CAAC,eAAe,CAAE,CAAC;IAClF,+BAA+B;IAC/B,MAAM,CAAC,cAAc,mCAAQ,MAAM,CAAC,cAAc,GAAK,MAAM,CAAC,cAAc,CAAE,CAAC;IAE/E,6CAA6C;IAC7C,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;IAC1C,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;IAE1C,IAAI,MAAM,CAAC,MAAM,EAAE;QACjB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE;YACjC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;gBACjB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;gBACxC,QAAQ,EAAE,QAAQ,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;aACtD,CAAC,CAAC;SACJ;KACF;IACD,MAAM,CAAC,MAAM,GAAG;QACd,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;QACxB,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,GAAG,YAAY,CAAC,CAAC;KACpF,CAAC;IACF,MAAM,CAAC,OAAO,GAAG;QACf,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;QACzB,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;aACtB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,KAAK,uBAAuB,CAAC;aAC9D,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,iCACV,MAAM,KACT,QAAQ,EAAE,YAAY,GAAG,MAAM,CAAC,QAAQ,IACxC,CAAC;KACN,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["/* eslint-disable complexity */\nimport { getActiveSpan, getClient, spanIsSampled } from '@sentry/core';\nimport type { Envelope, Event, IntegrationFn, Span, ThreadCpuProfile } from '@sentry/types';\nimport { logger, uuid4 } from '@sentry/utils';\nimport { Platform } from 'react-native';\n\nimport { isHermesEnabled } from '../utils/environment';\nimport { isRootSpan } from '../utils/span';\nimport { NATIVE } from '../wrapper';\nimport { PROFILE_QUEUE } from './cache';\nimport { MAX_PROFILE_DURATION_MS } from './constants';\nimport { convertToSentryProfile } from './convertHermesProfile';\nimport type { NativeAndroidProfileEvent, NativeProfileEvent } from './nativeTypes';\nimport type { AndroidCombinedProfileEvent, CombinedProfileEvent, HermesProfileEvent, ProfileEvent } from './types';\nimport {\n addProfilesToEnvelope,\n createHermesProfilingEvent,\n enrichCombinedProfileWithEventContext,\n findProfiledTransactionsFromEnvelope,\n} from './utils';\n\nconst INTEGRATION_NAME = 'HermesProfiling';\n\nconst MS_TO_NS: number = 1e6;\n\n/**\n * Profiling integration creates a profile for each transaction and adds it to the event envelope.\n *\n * @experimental\n */\nexport const hermesProfilingIntegration: IntegrationFn = () => {\n let _currentProfile:\n | {\n span_id: string;\n profile_id: string;\n startTimestampNs: number;\n }\n | undefined;\n let _currentProfileTimeout: ReturnType<typeof setTimeout> | undefined;\n let isReady: boolean = false;\n\n const setupOnce = (): void => {\n if (isReady) {\n return;\n }\n isReady = true;\n\n if (!isHermesEnabled()) {\n logger.log('[Profiling] Hermes is not enabled, not adding profiling integration.');\n return;\n }\n\n const client = getClient();\n\n if (!client || typeof client.on !== 'function') {\n return;\n }\n\n _startCurrentProfileForActiveTransaction();\n client.on('spanStart', _startCurrentProfile);\n\n client.on('spanEnd', _finishCurrentProfileForSpan);\n\n client.on('beforeEnvelope', (envelope: Envelope) => {\n if (!PROFILE_QUEUE.size()) {\n return;\n }\n\n const profiledTransactions = findProfiledTransactionsFromEnvelope(envelope);\n if (!profiledTransactions.length) {\n logger.log('[Profiling] no profiled transactions found in envelope');\n return;\n }\n\n const profilesToAddToEnvelope: ProfileEvent[] = [];\n for (const profiledTransaction of profiledTransactions) {\n const profile = _createProfileEventFor(profiledTransaction);\n if (profile) {\n profilesToAddToEnvelope.push(profile);\n }\n }\n addProfilesToEnvelope(envelope, profilesToAddToEnvelope);\n });\n };\n\n const _startCurrentProfileForActiveTransaction = (): void => {\n if (_currentProfile) {\n return;\n }\n const activeSpan = getActiveSpan();\n activeSpan && _startCurrentProfile(activeSpan);\n };\n\n const _startCurrentProfile = (activeSpan: Span): void => {\n if (!isRootSpan(activeSpan)) {\n return;\n }\n\n _finishCurrentProfile();\n\n const shouldStartProfiling = _shouldStartProfiling(activeSpan);\n if (!shouldStartProfiling) {\n return;\n }\n\n _currentProfileTimeout = setTimeout(_finishCurrentProfile, MAX_PROFILE_DURATION_MS);\n _startNewProfile(activeSpan);\n };\n\n const _shouldStartProfiling = (activeSpan: Span): boolean => {\n if (!spanIsSampled(activeSpan)) {\n logger.log('[Profiling] Transaction is not sampled, skipping profiling');\n return false;\n }\n\n const client = getClient();\n const options = client && client.getOptions();\n\n const profilesSampleRate =\n options && options._experiments && typeof options._experiments.profilesSampleRate === 'number'\n ? options._experiments.profilesSampleRate\n : undefined;\n if (profilesSampleRate === undefined) {\n logger.log('[Profiling] Profiling disabled, enable it by setting `profilesSampleRate` option to SDK init call.');\n return false;\n }\n\n // Check if we should sample this profile\n if (Math.random() > profilesSampleRate) {\n logger.log('[Profiling] Skip profiling transaction due to sampling.');\n return false;\n }\n\n return true;\n };\n\n /**\n * Starts a new profile and links it to the transaction.\n */\n const _startNewProfile = (activeSpan: Span): void => {\n const profileStartTimestampNs = startProfiling();\n if (!profileStartTimestampNs) {\n return;\n }\n\n _currentProfile = {\n span_id: activeSpan.spanContext().spanId,\n profile_id: uuid4(),\n startTimestampNs: profileStartTimestampNs,\n };\n activeSpan.setAttribute('profile_id', _currentProfile.profile_id);\n logger.log('[Profiling] started profiling: ', _currentProfile.profile_id);\n };\n\n /**\n * Stops current profile if the ending span is the currently profiled span.\n */\n const _finishCurrentProfileForSpan = (span: Span): void => {\n if (!isRootSpan(span)) {\n return;\n }\n\n if (span.spanContext().spanId !== _currentProfile?.span_id) {\n logger.log(\n `[Profiling] Span (${span.spanContext().spanId}) ended is not the currently profiled span (${\n _currentProfile?.span_id\n }). Not stopping profiling.`,\n );\n return;\n }\n\n _finishCurrentProfile();\n };\n\n /**\n * Stops profiling and adds the profile to the queue to be processed on beforeEnvelope.\n */\n const _finishCurrentProfile = (): void => {\n _clearCurrentProfileTimeout();\n if (_currentProfile === undefined) {\n return;\n }\n\n const profile = stopProfiling(_currentProfile.startTimestampNs);\n if (!profile) {\n logger.warn('[Profiling] Stop failed. Cleaning up...');\n _currentProfile = undefined;\n return;\n }\n\n PROFILE_QUEUE.add(_currentProfile.profile_id, profile);\n\n logger.log('[Profiling] finished profiling: ', _currentProfile.profile_id);\n _currentProfile = undefined;\n };\n\n const _createProfileEventFor = (profiledTransaction: Event): ProfileEvent | null => {\n const profile_id = profiledTransaction?.contexts?.trace?.data?.profile_id;\n\n if (typeof profile_id !== 'string') {\n logger.log('[Profiling] cannot find profile for a transaction without a profile context');\n return null;\n }\n\n // Remove the profile from the transaction context before sending, relay will take care of the rest.\n if (profiledTransaction?.contexts?.trace?.data?.profile_id) {\n delete profiledTransaction.contexts.trace.data.profile_id;\n }\n\n const profile = PROFILE_QUEUE.get(profile_id);\n PROFILE_QUEUE.delete(profile_id);\n\n if (!profile) {\n logger.log(`[Profiling] cannot find profile ${profile_id} for transaction ${profiledTransaction.event_id}`);\n return null;\n }\n\n const profileWithEvent = enrichCombinedProfileWithEventContext(profile_id, profile, profiledTransaction);\n logger.log(`[Profiling] Created profile ${profile_id} for transaction ${profiledTransaction.event_id}`);\n\n return profileWithEvent;\n };\n\n const _clearCurrentProfileTimeout = (): void => {\n _currentProfileTimeout !== undefined && clearTimeout(_currentProfileTimeout);\n _currentProfileTimeout = undefined;\n };\n\n return {\n name: INTEGRATION_NAME,\n setupOnce,\n };\n};\n\n/**\n * Starts Profilers and returns the timestamp when profiling started in nanoseconds.\n */\nexport function startProfiling(): number | null {\n const started = NATIVE.startProfiling();\n if (!started) {\n return null;\n }\n\n return Date.now() * MS_TO_NS;\n}\n\n/**\n * Stops Profilers and returns collected combined profile.\n */\nexport function stopProfiling(\n profileStartTimestampNs: number,\n): CombinedProfileEvent | AndroidCombinedProfileEvent | null {\n const collectedProfiles = NATIVE.stopProfiling();\n if (!collectedProfiles) {\n return null;\n }\n const profileEndTimestampNs = Date.now() * MS_TO_NS;\n\n const hermesProfile = convertToSentryProfile(collectedProfiles.hermesProfile);\n if (!hermesProfile) {\n return null;\n }\n\n const hermesProfileEvent = createHermesProfilingEvent(hermesProfile);\n if (!hermesProfileEvent) {\n return null;\n }\n\n if (collectedProfiles.androidProfile) {\n const durationNs = profileEndTimestampNs - profileStartTimestampNs;\n return createAndroidWithHermesProfile(hermesProfileEvent, collectedProfiles.androidProfile, durationNs);\n } else if (collectedProfiles.nativeProfile) {\n return addNativeProfileToHermesProfile(hermesProfileEvent, collectedProfiles.nativeProfile);\n }\n\n return hermesProfileEvent;\n}\n\n/**\n * Creates Android profile event with attached javascript profile.\n */\nexport function createAndroidWithHermesProfile(\n hermes: HermesProfileEvent,\n nativeAndroid: NativeAndroidProfileEvent,\n durationNs: number,\n): AndroidCombinedProfileEvent {\n return {\n ...nativeAndroid,\n platform: 'android',\n js_profile: hermes.profile,\n duration_ns: durationNs.toString(10),\n active_thread_id: hermes.transaction.active_thread_id,\n };\n}\n\n/**\n * Merges Hermes and Native profile events into one.\n */\nexport function addNativeProfileToHermesProfile(\n hermes: HermesProfileEvent,\n native: NativeProfileEvent,\n): CombinedProfileEvent {\n return {\n ...hermes,\n profile: addNativeThreadCpuProfileToHermes(hermes.profile, native.profile, hermes.transaction.active_thread_id),\n debug_meta: {\n images: native.debug_meta.images,\n },\n measurements: native.measurements,\n };\n}\n\n/**\n * Merges Hermes And Native profiles into one.\n */\nexport function addNativeThreadCpuProfileToHermes(\n hermes: ThreadCpuProfile,\n native: ThreadCpuProfile,\n hermes_active_thread_id: string | undefined,\n): CombinedProfileEvent['profile'] {\n // assumes thread ids are unique\n hermes.thread_metadata = { ...native.thread_metadata, ...hermes.thread_metadata };\n // assumes queue ids are unique\n hermes.queue_metadata = { ...native.queue_metadata, ...hermes.queue_metadata };\n\n // recalculate frames and stacks using offset\n const framesOffset = hermes.frames.length;\n const stacksOffset = hermes.stacks.length;\n\n if (native.frames) {\n for (const frame of native.frames) {\n hermes.frames.push({\n function: frame.function,\n instruction_addr: frame.instruction_addr,\n platform: Platform.OS === 'ios' ? 'cocoa' : undefined,\n });\n }\n }\n hermes.stacks = [\n ...(hermes.stacks || []),\n ...(native.stacks || []).map(stack => stack.map(frameId => frameId + framesOffset)),\n ];\n hermes.samples = [\n ...(hermes.samples || []),\n ...(native.samples || [])\n .filter(sample => sample.thread_id !== hermes_active_thread_id)\n .map(sample => ({\n ...sample,\n stack_id: stacksOffset + sample.stack_id,\n })),\n ];\n\n return hermes;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"integration.js","sourceRoot":"","sources":["../../../src/js/profiling/integration.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEvE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGxC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,qCAAqC,EACrC,oCAAoC,GACrC,MAAM,SAAS,CAAC;AAEjB,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AAE3C,MAAM,QAAQ,GAAW,GAAG,CAAC;AAW7B,MAAM,cAAc,GAAqC;IACvD,iBAAiB,EAAE,IAAI;CACxB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,cAAsC,cAAc,EAAe,EAAE;;IAC9G,MAAM,oBAAoB,GAAG,MAAA,WAAW,CAAC,iBAAiB,mCAAI,IAAI,CAAC;IACnE,IAAI,eAMS,CAAC;IACd,IAAI,sBAAiE,CAAC;IACtE,IAAI,OAAO,GAAY,KAAK,CAAC;IAE7B,MAAM,SAAS,GAAG,GAAS,EAAE;QAC3B,IAAI,OAAO,EAAE;YACX,OAAO;SACR;QACD,OAAO,GAAG,IAAI,CAAC;QAEf,IAAI,CAAC,eAAe,EAAE,EAAE;YACtB,MAAM,CAAC,GAAG,CAAC,sEAAsE,CAAC,CAAC;YACnF,OAAO;SACR;QAED,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAE3B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,UAAU,EAAE;YAC9C,OAAO;SACR;QAED,wCAAwC,EAAE,CAAC;QAC3C,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,oBAAoB,CAAC,CAAC;QAE7C,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,4BAA4B,CAAC,CAAC;QAEnD,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,QAAkB,EAAE,EAAE;YACjD,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE;gBACzB,OAAO;aACR;YAED,MAAM,oBAAoB,GAAG,oCAAoC,CAAC,QAAQ,CAAC,CAAC;YAC5E,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE;gBAChC,MAAM,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;gBACrE,OAAO;aACR;YAED,MAAM,uBAAuB,GAAmB,EAAE,CAAC;YACnD,KAAK,MAAM,mBAAmB,IAAI,oBAAoB,EAAE;gBACtD,MAAM,OAAO,GAAG,sBAAsB,CAAC,mBAAmB,CAAC,CAAC;gBAC5D,IAAI,OAAO,EAAE;oBACX,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;iBACvC;aACF;YACD,qBAAqB,CAAC,QAAQ,EAAE,uBAAuB,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,wCAAwC,GAAG,GAAS,EAAE;QAC1D,IAAI,eAAe,EAAE;YACnB,OAAO;SACR;QACD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;QACnC,UAAU,IAAI,oBAAoB,CAAC,UAAU,CAAC,CAAC;IACjD,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,CAAC,UAAgB,EAAQ,EAAE;QACtD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;YAC3B,OAAO;SACR;QAED,qBAAqB,EAAE,CAAC;QAExB,MAAM,oBAAoB,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;QAC/D,IAAI,CAAC,oBAAoB,EAAE;YACzB,OAAO;SACR;QAED,sBAAsB,GAAG,UAAU,CAAC,qBAAqB,EAAE,uBAAuB,CAAC,CAAC;QACpF,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEF,MAAM,qBAAqB,GAAG,CAAC,UAAgB,EAAW,EAAE;QAC1D,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE;YAC9B,MAAM,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC;YACzE,OAAO,KAAK,CAAC;SACd;QAED,MAAM,MAAM,GAAG,SAAS,EAAqB,CAAC;QAC9C,MAAM,OAAO,GAAG,MAAM,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAE9C,MAAM,kBAAkB,GACtB,OAAO,IAAI,OAAO,OAAO,CAAC,kBAAkB,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC;QACrG,IAAI,kBAAkB,KAAK,SAAS,EAAE;YACpC,MAAM,CAAC,GAAG,CAAC,oGAAoG,CAAC,CAAC;YACjH,OAAO,KAAK,CAAC;SACd;QAED,yCAAyC;QACzC,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,kBAAkB,EAAE;YACtC,MAAM,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;YACtE,OAAO,KAAK,CAAC;SACd;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF;;OAEG;IACH,MAAM,gBAAgB,GAAG,CAAC,UAAgB,EAAQ,EAAE;QAClD,MAAM,uBAAuB,GAAG,cAAc,CAAC,oBAAoB,CAAC,CAAC;QACrE,IAAI,CAAC,uBAAuB,EAAE;YAC5B,OAAO;SACR;QAED,eAAe,GAAG;YAChB,OAAO,EAAE,UAAU,CAAC,WAAW,EAAE,CAAC,MAAM;YACxC,UAAU,EAAE,KAAK,EAAE;YACnB,gBAAgB,EAAE,uBAAuB;SAC1C,CAAC;QACF,UAAU,CAAC,YAAY,CAAC,YAAY,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;QAClE,MAAM,CAAC,GAAG,CAAC,iCAAiC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IAC5E,CAAC,CAAC;IAEF;;OAEG;IACH,MAAM,4BAA4B,GAAG,CAAC,IAAU,EAAQ,EAAE;QACxD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;YACrB,OAAO;SACR;QAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,MAAK,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,OAAO,CAAA,EAAE;YAC1D,MAAM,CAAC,GAAG,CACR,qBAAqB,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,+CAC5C,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,OACnB,4BAA4B,CAC7B,CAAC;YACF,OAAO;SACR;QAED,qBAAqB,EAAE,CAAC;IAC1B,CAAC,CAAC;IAEF;;OAEG;IACH,MAAM,qBAAqB,GAAG,GAAS,EAAE;QACvC,2BAA2B,EAAE,CAAC;QAC9B,IAAI,eAAe,KAAK,SAAS,EAAE;YACjC,OAAO;SACR;QAED,MAAM,OAAO,GAAG,aAAa,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC;QAChE,IAAI,CAAC,OAAO,EAAE;YACZ,MAAM,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;YACvD,eAAe,GAAG,SAAS,CAAC;YAC5B,OAAO;SACR;QAED,aAAa,CAAC,GAAG,CAAC,eAAe,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAEvD,MAAM,CAAC,GAAG,CAAC,kCAAkC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;QAC3E,eAAe,GAAG,SAAS,CAAC;IAC9B,CAAC,CAAC;IAEF,MAAM,sBAAsB,GAAG,CAAC,mBAA0B,EAAuB,EAAE;;QACjF,MAAM,UAAU,GAAG,MAAA,MAAA,MAAA,mBAAmB,aAAnB,mBAAmB,uBAAnB,mBAAmB,CAAE,QAAQ,0CAAE,KAAK,0CAAE,IAAI,0CAAE,UAAU,CAAC;QAE1E,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE;YAClC,MAAM,CAAC,GAAG,CAAC,6EAA6E,CAAC,CAAC;YAC1F,OAAO,IAAI,CAAC;SACb;QAED,oGAAoG;QACpG,IAAI,MAAA,MAAA,MAAA,mBAAmB,aAAnB,mBAAmB,uBAAnB,mBAAmB,CAAE,QAAQ,0CAAE,KAAK,0CAAE,IAAI,0CAAE,UAAU,EAAE;YAC1D,OAAO,mBAAmB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;SAC3D;QAED,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC9C,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAEjC,IAAI,CAAC,OAAO,EAAE;YACZ,MAAM,CAAC,GAAG,CAAC,mCAAmC,UAAU,oBAAoB,mBAAmB,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC5G,OAAO,IAAI,CAAC;SACb;QAED,MAAM,gBAAgB,GAAG,qCAAqC,CAAC,UAAU,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACzG,MAAM,CAAC,GAAG,CAAC,+BAA+B,UAAU,oBAAoB,mBAAmB,CAAC,QAAQ,EAAE,CAAC,CAAC;QAExG,OAAO,gBAAgB,CAAC;IAC1B,CAAC,CAAC;IAEF,MAAM,2BAA2B,GAAG,GAAS,EAAE;QAC7C,sBAAsB,KAAK,SAAS,IAAI,YAAY,CAAC,sBAAsB,CAAC,CAAC;QAC7E,sBAAsB,GAAG,SAAS,CAAC;IACrC,CAAC,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,gBAAgB;QACtB,SAAS;KACV,CAAC;AACJ,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,iBAA0B;IACvD,MAAM,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;IACzD,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,IAAI,CAAC;KACb;IAED,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,uBAA+B;IAE/B,MAAM,iBAAiB,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;IACjD,IAAI,CAAC,iBAAiB,EAAE;QACtB,OAAO,IAAI,CAAC;KACb;IACD,MAAM,qBAAqB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC;IAEpD,MAAM,aAAa,GAAG,sBAAsB,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC;IAC9E,IAAI,CAAC,aAAa,EAAE;QAClB,OAAO,IAAI,CAAC;KACb;IAED,MAAM,kBAAkB,GAAG,0BAA0B,CAAC,aAAa,CAAC,CAAC;IACrE,IAAI,CAAC,kBAAkB,EAAE;QACvB,OAAO,IAAI,CAAC;KACb;IAED,IAAI,iBAAiB,CAAC,cAAc,EAAE;QACpC,MAAM,UAAU,GAAG,qBAAqB,GAAG,uBAAuB,CAAC;QACnE,OAAO,8BAA8B,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;KACzG;SAAM,IAAI,iBAAiB,CAAC,aAAa,EAAE;QAC1C,OAAO,+BAA+B,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,aAAa,CAAC,CAAC;KAC7F;IAED,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,8BAA8B,CAC5C,MAA0B,EAC1B,aAAwC,EACxC,UAAkB;IAElB,uCACK,aAAa,KAChB,QAAQ,EAAE,SAAS,EACnB,UAAU,EAAE,MAAM,CAAC,OAAO,EAC1B,WAAW,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,EACpC,gBAAgB,EAAE,MAAM,CAAC,WAAW,CAAC,gBAAgB,IACrD;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,+BAA+B,CAC7C,MAA0B,EAC1B,MAA0B;IAE1B,uCACK,MAAM,KACT,OAAO,EAAE,iCAAiC,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,EAC/G,UAAU,EAAE;YACV,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM;SACjC,EACD,YAAY,EAAE,MAAM,CAAC,YAAY,IACjC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iCAAiC,CAC/C,MAAwB,EACxB,MAAwB,EACxB,uBAA2C;IAE3C,gCAAgC;IAChC,MAAM,CAAC,eAAe,mCAAQ,MAAM,CAAC,eAAe,GAAK,MAAM,CAAC,eAAe,CAAE,CAAC;IAClF,+BAA+B;IAC/B,MAAM,CAAC,cAAc,mCAAQ,MAAM,CAAC,cAAc,GAAK,MAAM,CAAC,cAAc,CAAE,CAAC;IAE/E,6CAA6C;IAC7C,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;IAC1C,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;IAE1C,IAAI,MAAM,CAAC,MAAM,EAAE;QACjB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE;YACjC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;gBACjB,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;gBACxC,QAAQ,EAAE,QAAQ,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;aACtD,CAAC,CAAC;SACJ;KACF;IACD,MAAM,CAAC,MAAM,GAAG;QACd,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;QACxB,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,GAAG,YAAY,CAAC,CAAC;KACpF,CAAC;IACF,MAAM,CAAC,OAAO,GAAG;QACf,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;QACzB,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;aACtB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,KAAK,uBAAuB,CAAC;aAC9D,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,iCACV,MAAM,KACT,QAAQ,EAAE,YAAY,GAAG,MAAM,CAAC,QAAQ,IACxC,CAAC;KACN,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["/* eslint-disable complexity */\nimport { getActiveSpan, getClient, spanIsSampled } from '@sentry/core';\nimport type { Envelope, Event, Integration, Span, ThreadCpuProfile } from '@sentry/types';\nimport { logger, uuid4 } from '@sentry/utils';\nimport { Platform } from 'react-native';\n\nimport type { ReactNativeClient } from '../client';\nimport { isHermesEnabled } from '../utils/environment';\nimport { isRootSpan } from '../utils/span';\nimport { NATIVE } from '../wrapper';\nimport { PROFILE_QUEUE } from './cache';\nimport { MAX_PROFILE_DURATION_MS } from './constants';\nimport { convertToSentryProfile } from './convertHermesProfile';\nimport type { NativeAndroidProfileEvent, NativeProfileEvent } from './nativeTypes';\nimport type { AndroidCombinedProfileEvent, CombinedProfileEvent, HermesProfileEvent, ProfileEvent } from './types';\nimport {\n addProfilesToEnvelope,\n createHermesProfilingEvent,\n enrichCombinedProfileWithEventContext,\n findProfiledTransactionsFromEnvelope,\n} from './utils';\n\nconst INTEGRATION_NAME = 'HermesProfiling';\n\nconst MS_TO_NS: number = 1e6;\n\nexport interface HermesProfilingOptions {\n /**\n * Enable or disable profiling of native (iOS and Android) threads\n *\n * @default true\n */\n platformProfilers?: boolean;\n}\n\nconst defaultOptions: Required<HermesProfilingOptions> = {\n platformProfilers: true,\n};\n\n/**\n * Profiling integration creates a profile for each transaction and adds it to the event envelope.\n *\n * @experimental\n */\nexport const hermesProfilingIntegration = (initOptions: HermesProfilingOptions = defaultOptions): Integration => {\n const usePlatformProfilers = initOptions.platformProfilers ?? true;\n let _currentProfile:\n | {\n span_id: string;\n profile_id: string;\n startTimestampNs: number;\n }\n | undefined;\n let _currentProfileTimeout: ReturnType<typeof setTimeout> | undefined;\n let isReady: boolean = false;\n\n const setupOnce = (): void => {\n if (isReady) {\n return;\n }\n isReady = true;\n\n if (!isHermesEnabled()) {\n logger.log('[Profiling] Hermes is not enabled, not adding profiling integration.');\n return;\n }\n\n const client = getClient();\n\n if (!client || typeof client.on !== 'function') {\n return;\n }\n\n _startCurrentProfileForActiveTransaction();\n client.on('spanStart', _startCurrentProfile);\n\n client.on('spanEnd', _finishCurrentProfileForSpan);\n\n client.on('beforeEnvelope', (envelope: Envelope) => {\n if (!PROFILE_QUEUE.size()) {\n return;\n }\n\n const profiledTransactions = findProfiledTransactionsFromEnvelope(envelope);\n if (!profiledTransactions.length) {\n logger.log('[Profiling] no profiled transactions found in envelope');\n return;\n }\n\n const profilesToAddToEnvelope: ProfileEvent[] = [];\n for (const profiledTransaction of profiledTransactions) {\n const profile = _createProfileEventFor(profiledTransaction);\n if (profile) {\n profilesToAddToEnvelope.push(profile);\n }\n }\n addProfilesToEnvelope(envelope, profilesToAddToEnvelope);\n });\n };\n\n const _startCurrentProfileForActiveTransaction = (): void => {\n if (_currentProfile) {\n return;\n }\n const activeSpan = getActiveSpan();\n activeSpan && _startCurrentProfile(activeSpan);\n };\n\n const _startCurrentProfile = (activeSpan: Span): void => {\n if (!isRootSpan(activeSpan)) {\n return;\n }\n\n _finishCurrentProfile();\n\n const shouldStartProfiling = _shouldStartProfiling(activeSpan);\n if (!shouldStartProfiling) {\n return;\n }\n\n _currentProfileTimeout = setTimeout(_finishCurrentProfile, MAX_PROFILE_DURATION_MS);\n _startNewProfile(activeSpan);\n };\n\n const _shouldStartProfiling = (activeSpan: Span): boolean => {\n if (!spanIsSampled(activeSpan)) {\n logger.log('[Profiling] Transaction is not sampled, skipping profiling');\n return false;\n }\n\n const client = getClient<ReactNativeClient>();\n const options = client && client.getOptions();\n\n const profilesSampleRate =\n options && typeof options.profilesSampleRate === 'number' ? options.profilesSampleRate : undefined;\n if (profilesSampleRate === undefined) {\n logger.log('[Profiling] Profiling disabled, enable it by setting `profilesSampleRate` option to SDK init call.');\n return false;\n }\n\n // Check if we should sample this profile\n if (Math.random() > profilesSampleRate) {\n logger.log('[Profiling] Skip profiling transaction due to sampling.');\n return false;\n }\n\n return true;\n };\n\n /**\n * Starts a new profile and links it to the transaction.\n */\n const _startNewProfile = (activeSpan: Span): void => {\n const profileStartTimestampNs = startProfiling(usePlatformProfilers);\n if (!profileStartTimestampNs) {\n return;\n }\n\n _currentProfile = {\n span_id: activeSpan.spanContext().spanId,\n profile_id: uuid4(),\n startTimestampNs: profileStartTimestampNs,\n };\n activeSpan.setAttribute('profile_id', _currentProfile.profile_id);\n logger.log('[Profiling] started profiling: ', _currentProfile.profile_id);\n };\n\n /**\n * Stops current profile if the ending span is the currently profiled span.\n */\n const _finishCurrentProfileForSpan = (span: Span): void => {\n if (!isRootSpan(span)) {\n return;\n }\n\n if (span.spanContext().spanId !== _currentProfile?.span_id) {\n logger.log(\n `[Profiling] Span (${span.spanContext().spanId}) ended is not the currently profiled span (${\n _currentProfile?.span_id\n }). Not stopping profiling.`,\n );\n return;\n }\n\n _finishCurrentProfile();\n };\n\n /**\n * Stops profiling and adds the profile to the queue to be processed on beforeEnvelope.\n */\n const _finishCurrentProfile = (): void => {\n _clearCurrentProfileTimeout();\n if (_currentProfile === undefined) {\n return;\n }\n\n const profile = stopProfiling(_currentProfile.startTimestampNs);\n if (!profile) {\n logger.warn('[Profiling] Stop failed. Cleaning up...');\n _currentProfile = undefined;\n return;\n }\n\n PROFILE_QUEUE.add(_currentProfile.profile_id, profile);\n\n logger.log('[Profiling] finished profiling: ', _currentProfile.profile_id);\n _currentProfile = undefined;\n };\n\n const _createProfileEventFor = (profiledTransaction: Event): ProfileEvent | null => {\n const profile_id = profiledTransaction?.contexts?.trace?.data?.profile_id;\n\n if (typeof profile_id !== 'string') {\n logger.log('[Profiling] cannot find profile for a transaction without a profile context');\n return null;\n }\n\n // Remove the profile from the transaction context before sending, relay will take care of the rest.\n if (profiledTransaction?.contexts?.trace?.data?.profile_id) {\n delete profiledTransaction.contexts.trace.data.profile_id;\n }\n\n const profile = PROFILE_QUEUE.get(profile_id);\n PROFILE_QUEUE.delete(profile_id);\n\n if (!profile) {\n logger.log(`[Profiling] cannot find profile ${profile_id} for transaction ${profiledTransaction.event_id}`);\n return null;\n }\n\n const profileWithEvent = enrichCombinedProfileWithEventContext(profile_id, profile, profiledTransaction);\n logger.log(`[Profiling] Created profile ${profile_id} for transaction ${profiledTransaction.event_id}`);\n\n return profileWithEvent;\n };\n\n const _clearCurrentProfileTimeout = (): void => {\n _currentProfileTimeout !== undefined && clearTimeout(_currentProfileTimeout);\n _currentProfileTimeout = undefined;\n };\n\n return {\n name: INTEGRATION_NAME,\n setupOnce,\n };\n};\n\n/**\n * Starts Profilers and returns the timestamp when profiling started in nanoseconds.\n */\nexport function startProfiling(platformProfilers: boolean): number | null {\n const started = NATIVE.startProfiling(platformProfilers);\n if (!started) {\n return null;\n }\n\n return Date.now() * MS_TO_NS;\n}\n\n/**\n * Stops Profilers and returns collected combined profile.\n */\nexport function stopProfiling(\n profileStartTimestampNs: number,\n): CombinedProfileEvent | AndroidCombinedProfileEvent | null {\n const collectedProfiles = NATIVE.stopProfiling();\n if (!collectedProfiles) {\n return null;\n }\n const profileEndTimestampNs = Date.now() * MS_TO_NS;\n\n const hermesProfile = convertToSentryProfile(collectedProfiles.hermesProfile);\n if (!hermesProfile) {\n return null;\n }\n\n const hermesProfileEvent = createHermesProfilingEvent(hermesProfile);\n if (!hermesProfileEvent) {\n return null;\n }\n\n if (collectedProfiles.androidProfile) {\n const durationNs = profileEndTimestampNs - profileStartTimestampNs;\n return createAndroidWithHermesProfile(hermesProfileEvent, collectedProfiles.androidProfile, durationNs);\n } else if (collectedProfiles.nativeProfile) {\n return addNativeProfileToHermesProfile(hermesProfileEvent, collectedProfiles.nativeProfile);\n }\n\n return hermesProfileEvent;\n}\n\n/**\n * Creates Android profile event with attached javascript profile.\n */\nexport function createAndroidWithHermesProfile(\n hermes: HermesProfileEvent,\n nativeAndroid: NativeAndroidProfileEvent,\n durationNs: number,\n): AndroidCombinedProfileEvent {\n return {\n ...nativeAndroid,\n platform: 'android',\n js_profile: hermes.profile,\n duration_ns: durationNs.toString(10),\n active_thread_id: hermes.transaction.active_thread_id,\n };\n}\n\n/**\n * Merges Hermes and Native profile events into one.\n */\nexport function addNativeProfileToHermesProfile(\n hermes: HermesProfileEvent,\n native: NativeProfileEvent,\n): CombinedProfileEvent {\n return {\n ...hermes,\n profile: addNativeThreadCpuProfileToHermes(hermes.profile, native.profile, hermes.transaction.active_thread_id),\n debug_meta: {\n images: native.debug_meta.images,\n },\n measurements: native.measurements,\n };\n}\n\n/**\n * Merges Hermes And Native profiles into one.\n */\nexport function addNativeThreadCpuProfileToHermes(\n hermes: ThreadCpuProfile,\n native: ThreadCpuProfile,\n hermes_active_thread_id: string | undefined,\n): CombinedProfileEvent['profile'] {\n // assumes thread ids are unique\n hermes.thread_metadata = { ...native.thread_metadata, ...hermes.thread_metadata };\n // assumes queue ids are unique\n hermes.queue_metadata = { ...native.queue_metadata, ...hermes.queue_metadata };\n\n // recalculate frames and stacks using offset\n const framesOffset = hermes.frames.length;\n const stacksOffset = hermes.stacks.length;\n\n if (native.frames) {\n for (const frame of native.frames) {\n hermes.frames.push({\n function: frame.function,\n instruction_addr: frame.instruction_addr,\n platform: Platform.OS === 'ios' ? 'cocoa' : undefined,\n });\n }\n }\n hermes.stacks = [\n ...(hermes.stacks || []),\n ...(native.stacks || []).map(stack => stack.map(frameId => frameId + framesOffset)),\n ];\n hermes.samples = [\n ...(hermes.samples || []),\n ...(native.samples || [])\n .filter(sample => sample.thread_id !== hermes_active_thread_id)\n .map(sample => ({\n ...sample,\n stack_id: stacksOffset + sample.stack_id,\n })),\n ];\n\n return hermes;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mobilereplay.js","sourceRoot":"","sources":["../../../src/js/replay/mobilereplay.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Client, DynamicSamplingContext, Event, Integration } from '@sentry/types';\nimport { logger } from '@sentry/utils';\n\nimport { isHardCrash } from '../misc';\nimport { hasHooks } from '../utils/clientutils';\nimport { isExpoGo, notMobileOs } from '../utils/environment';\nimport { NATIVE } from '../wrapper';\nimport { enrichXhrBreadcrumbsForMobileReplay } from './xhrUtils';\n\nexport const MOBILE_REPLAY_INTEGRATION_NAME = 'MobileReplay';\n\nexport interface MobileReplayOptions {\n /**\n * Mask all text in recordings\n *\n * @default true\n */\n maskAllText?: boolean;\n\n /**\n * Mask all
|
|
1
|
+
{"version":3,"file":"mobilereplay.js","sourceRoot":"","sources":["../../../src/js/replay/mobilereplay.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Client, DynamicSamplingContext, Event, Integration } from '@sentry/types';\nimport { logger } from '@sentry/utils';\n\nimport { isHardCrash } from '../misc';\nimport { hasHooks } from '../utils/clientutils';\nimport { isExpoGo, notMobileOs } from '../utils/environment';\nimport { NATIVE } from '../wrapper';\nimport { enrichXhrBreadcrumbsForMobileReplay } from './xhrUtils';\n\nexport const MOBILE_REPLAY_INTEGRATION_NAME = 'MobileReplay';\n\nexport interface MobileReplayOptions {\n /**\n * Mask all text in recordings\n *\n * @default true\n */\n maskAllText?: boolean;\n\n /**\n * Mask all images in recordings\n *\n * @default true\n */\n maskAllImages?: boolean;\n\n /**\n * Mask all vector graphics in recordings\n * Supports `react-native-svg`\n *\n * @default true\n */\n maskAllVectors?: boolean;\n}\n\nconst defaultOptions: Required<MobileReplayOptions> = {\n maskAllText: true,\n maskAllImages: true,\n maskAllVectors: true,\n};\n\ntype MobileReplayIntegration = Integration & {\n options: Required<MobileReplayOptions>;\n};\n\n/**\n * The Mobile Replay Integration, let's you adjust the default mobile replay options.\n * To be passed to `Sentry.init` with `replaysOnErrorSampleRate` or `replaysSessionSampleRate`.\n *\n * ```javascript\n * Sentry.init({\n * _experiments: {\n * replaysOnErrorSampleRate: 1.0,\n * replaysSessionSampleRate: 1.0,\n * },\n * integrations: [mobileReplayIntegration({\n * // Adjust the default options\n * })],\n * });\n * ```\n *\n * @experimental\n */\nexport const mobileReplayIntegration = (initOptions: MobileReplayOptions = defaultOptions): MobileReplayIntegration => {\n if (isExpoGo()) {\n logger.warn(\n `[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} is not supported in Expo Go. Use EAS Build or \\`expo prebuild\\` to enable it.`,\n );\n }\n if (notMobileOs()) {\n logger.warn(`[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} is not supported on this platform.`);\n }\n\n if (isExpoGo() || notMobileOs()) {\n return mobileReplayIntegrationNoop();\n }\n\n const options = { ...defaultOptions, ...initOptions };\n\n async function processEvent(event: Event): Promise<Event> {\n const hasException = event.exception && event.exception.values && event.exception.values.length > 0;\n if (!hasException) {\n // Event is not an error, will not capture replay\n return event;\n }\n\n const recordingReplayId = NATIVE.getCurrentReplayId();\n if (recordingReplayId) {\n logger.debug(\n `[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} assign already recording replay ${recordingReplayId} for event ${event.event_id}.`,\n );\n return event;\n }\n\n const replayId = await NATIVE.captureReplay(isHardCrash(event));\n if (!replayId) {\n logger.debug(`[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} not sampled for event ${event.event_id}.`);\n return event;\n }\n\n return event;\n }\n\n function setup(client: Client): void {\n if (!hasHooks(client)) {\n return;\n }\n\n client.on('createDsc', (dsc: DynamicSamplingContext) => {\n if (dsc.replay_id) {\n return;\n }\n\n // TODO: For better performance, we should emit replayId changes on native, and hold the replayId value in JS\n const currentReplayId = NATIVE.getCurrentReplayId();\n if (currentReplayId) {\n dsc.replay_id = currentReplayId;\n }\n });\n\n client.on('beforeAddBreadcrumb', enrichXhrBreadcrumbsForMobileReplay);\n }\n\n // TODO: When adding manual API, ensure overlap with the web replay so users can use the same API interchangeably\n // https://github.com/getsentry/sentry-javascript/blob/develop/packages/replay-internal/src/integration.ts#L45\n return {\n name: MOBILE_REPLAY_INTEGRATION_NAME,\n setupOnce() {\n /* Noop */\n },\n setup,\n processEvent,\n options: options,\n };\n};\n\nconst mobileReplayIntegrationNoop = (): MobileReplayIntegration => {\n return {\n name: MOBILE_REPLAY_INTEGRATION_NAME,\n setupOnce() {\n /* Noop */\n },\n options: defaultOptions,\n };\n};\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MetroConfig } from 'metro
|
|
1
|
+
import type { MetroConfig } from 'metro';
|
|
2
2
|
import type { DefaultConfigOptions } from './vendor/expo/expoconfig';
|
|
3
3
|
export * from './sentryMetroSerializer';
|
|
4
4
|
export interface SentryMetroConfigOptions {
|
|
@@ -7,6 +7,11 @@ export interface SentryMetroConfigOptions {
|
|
|
7
7
|
* @default false
|
|
8
8
|
*/
|
|
9
9
|
annotateReactComponents?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Adds the Sentry replay package for web.
|
|
12
|
+
* @default true
|
|
13
|
+
*/
|
|
14
|
+
includeWebReplay?: boolean;
|
|
10
15
|
}
|
|
11
16
|
export interface SentryExpoConfigOptions {
|
|
12
17
|
/**
|
|
@@ -20,7 +25,7 @@ export interface SentryExpoConfigOptions {
|
|
|
20
25
|
* Adds Debug ID to the output bundle and source maps.
|
|
21
26
|
* Collapses Sentry frames from the stack trace view in LogBox.
|
|
22
27
|
*/
|
|
23
|
-
export declare function withSentryConfig(config: MetroConfig, { annotateReactComponents }?: SentryMetroConfigOptions): MetroConfig;
|
|
28
|
+
export declare function withSentryConfig(config: MetroConfig, { annotateReactComponents, includeWebReplay }?: SentryMetroConfigOptions): MetroConfig;
|
|
24
29
|
/**
|
|
25
30
|
* This function returns Default Expo configuration with Sentry plugins.
|
|
26
31
|
*/
|
|
@@ -29,6 +34,10 @@ export declare function getSentryExpoConfig(projectRoot: string, options?: Defau
|
|
|
29
34
|
* Adds Sentry Babel transformer to the Metro config.
|
|
30
35
|
*/
|
|
31
36
|
export declare function withSentryBabelTransformer(config: MetroConfig): MetroConfig;
|
|
37
|
+
/**
|
|
38
|
+
* Includes `@sentry/replay` packages based on the `includeWebReplay` flag and current bundle `platform`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function withSentryResolver(config: MetroConfig, includeWebReplay: boolean | undefined): MetroConfig;
|
|
32
41
|
/**
|
|
33
42
|
* Collapses Sentry internal frames from the stack trace view in LogBox.
|
|
34
43
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metroconfig.d.ts","sourceRoot":"","sources":["../../../src/js/tools/metroconfig.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metroconfig.d.ts","sourceRoot":"","sources":["../../../src/js/tools/metroconfig.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAsC,MAAM,OAAO,CAAC;AAQ7E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACrE,cAAc,yBAAyB,CAAC;AAIxC,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,mBAAmB,CAAC;CAC/C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EACnB,EAAE,uBAA+B,EAAE,gBAAuB,EAAE,GAAE,wBAA6B,GAC1F,WAAW,CAeb;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,oBAAoB,GAAG,uBAAuB,GAAG,wBAA6B,GACtF,WAAW,CAsBb;AAsBD;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CA2B3E;AA4BD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,OAAO,GAAG,SAAS,GAAG,WAAW,CA+C1G;AAQD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAiC1E"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
-
exports.withSentryFramesCollapsed = exports.withSentryBabelTransformer = exports.getSentryExpoConfig = exports.withSentryConfig = void 0;
|
|
2
|
+
exports.withSentryFramesCollapsed = exports.withSentryResolver = exports.withSentryBabelTransformer = exports.getSentryExpoConfig = exports.withSentryConfig = void 0;
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const utils_1 = require("@sentry/utils");
|
|
5
5
|
const process = require("process");
|
|
@@ -15,7 +15,7 @@ tslib_1.__exportStar(require("./sentryMetroSerializer"), exports);
|
|
|
15
15
|
* Adds Debug ID to the output bundle and source maps.
|
|
16
16
|
* Collapses Sentry frames from the stack trace view in LogBox.
|
|
17
17
|
*/
|
|
18
|
-
function withSentryConfig(config, { annotateReactComponents = false } = {}) {
|
|
18
|
+
function withSentryConfig(config, { annotateReactComponents = false, includeWebReplay = true } = {}) {
|
|
19
19
|
setSentryMetroDevServerEnvFlag();
|
|
20
20
|
let newConfig = config;
|
|
21
21
|
newConfig = withSentryDebugId(newConfig);
|
|
@@ -23,6 +23,9 @@ function withSentryConfig(config, { annotateReactComponents = false } = {}) {
|
|
|
23
23
|
if (annotateReactComponents) {
|
|
24
24
|
newConfig = withSentryBabelTransformer(newConfig);
|
|
25
25
|
}
|
|
26
|
+
if (includeWebReplay === false) {
|
|
27
|
+
newConfig = withSentryResolver(newConfig, includeWebReplay);
|
|
28
|
+
}
|
|
26
29
|
return newConfig;
|
|
27
30
|
}
|
|
28
31
|
exports.withSentryConfig = withSentryConfig;
|
|
@@ -40,6 +43,9 @@ function getSentryExpoConfig(projectRoot, options = {}) {
|
|
|
40
43
|
if (options.annotateReactComponents) {
|
|
41
44
|
newConfig = withSentryBabelTransformer(newConfig);
|
|
42
45
|
}
|
|
46
|
+
if (options.includeWebReplay === false) {
|
|
47
|
+
newConfig = withSentryResolver(newConfig, options.includeWebReplay);
|
|
48
|
+
}
|
|
43
49
|
return newConfig;
|
|
44
50
|
}
|
|
45
51
|
exports.getSentryExpoConfig = getSentryExpoConfig;
|
|
@@ -82,6 +88,40 @@ function withSentryDebugId(config) {
|
|
|
82
88
|
// The default serializer is sync
|
|
83
89
|
return Object.assign(Object.assign({}, config), { serializer: Object.assign(Object.assign({}, config.serializer), { customSerializer }) });
|
|
84
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Includes `@sentry/replay` packages based on the `includeWebReplay` flag and current bundle `platform`.
|
|
93
|
+
*/
|
|
94
|
+
function withSentryResolver(config, includeWebReplay) {
|
|
95
|
+
var _a;
|
|
96
|
+
const originalResolver = (_a = config.resolver) === null || _a === void 0 ? void 0 : _a.resolveRequest;
|
|
97
|
+
const sentryResolverRequest = (context, moduleName, platform, oldMetroModuleName) => {
|
|
98
|
+
if ((includeWebReplay === false ||
|
|
99
|
+
(includeWebReplay === undefined && (platform === 'android' || platform === 'ios'))) &&
|
|
100
|
+
(oldMetroModuleName !== null && oldMetroModuleName !== void 0 ? oldMetroModuleName : moduleName).includes('@sentry/replay')) {
|
|
101
|
+
return { type: 'empty' };
|
|
102
|
+
}
|
|
103
|
+
if (originalResolver) {
|
|
104
|
+
return oldMetroModuleName
|
|
105
|
+
? originalResolver(context, moduleName, platform, oldMetroModuleName)
|
|
106
|
+
: originalResolver(context, moduleName, platform);
|
|
107
|
+
}
|
|
108
|
+
// Prior 0.68, resolve context.resolveRequest is sentryResolver itself, where on later version it is the default resolver.
|
|
109
|
+
if (context.resolveRequest === sentryResolverRequest) {
|
|
110
|
+
// eslint-disable-next-line no-console
|
|
111
|
+
console.error(`Error: [@sentry/react-native/metro] Can not resolve the defaultResolver on Metro older than 0.68.
|
|
112
|
+
Please follow one of the following options:
|
|
113
|
+
- Include your resolverRequest on your metroconfig.
|
|
114
|
+
- Update your Metro version to 0.68 or higher.
|
|
115
|
+
- Set includeWebReplay as true on your metro config.
|
|
116
|
+
- If you are still facing issues, report the issue at http://www.github.com/getsentry/sentry-react-native/issues`);
|
|
117
|
+
// Return required for test.
|
|
118
|
+
return process.exit(-1);
|
|
119
|
+
}
|
|
120
|
+
return context.resolveRequest(context, moduleName, platform);
|
|
121
|
+
};
|
|
122
|
+
return Object.assign(Object.assign({}, config), { resolver: Object.assign(Object.assign({}, config.resolver), { resolveRequest: sentryResolverRequest }) });
|
|
123
|
+
}
|
|
124
|
+
exports.withSentryResolver = withSentryResolver;
|
|
85
125
|
/**
|
|
86
126
|
* Collapses Sentry internal frames from the stack trace view in LogBox.
|
|
87
127
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metroconfig.js","sourceRoot":"","sources":["../../../src/js/tools/metroconfig.ts"],"names":[],"mappings":"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","sourcesContent":["import { logger } from '@sentry/utils';\nimport type { MixedOutput, Module, ReadOnlyGraph } from 'metro';\nimport type { MetroConfig } from 'metro-config';\nimport * as process from 'process';\nimport { env } from 'process';\n\nimport { enableLogger } from './enableLogger';\nimport { cleanDefaultBabelTransformerPath, saveDefaultBabelTransformerPath } from './sentryBabelTransformerUtils';\nimport { createSentryMetroSerializer, unstable_beforeAssetSerializationPlugin } from './sentryMetroSerializer';\nimport type { DefaultConfigOptions } from './vendor/expo/expoconfig';\n\nexport * from './sentryMetroSerializer';\n\nenableLogger();\n\nexport interface SentryMetroConfigOptions {\n /**\n * Annotates React components with Sentry data.\n * @default false\n */\n annotateReactComponents?: boolean;\n}\n\nexport interface SentryExpoConfigOptions {\n /**\n * Pass a custom `getDefaultConfig` function to override the default Expo configuration getter.\n */\n getDefaultConfig?: typeof getSentryExpoConfig;\n}\n\n/**\n * Adds Sentry to the Metro config.\n *\n * Adds Debug ID to the output bundle and source maps.\n * Collapses Sentry frames from the stack trace view in LogBox.\n */\nexport function withSentryConfig(\n config: MetroConfig,\n { annotateReactComponents = false }: SentryMetroConfigOptions = {},\n): MetroConfig {\n setSentryMetroDevServerEnvFlag();\n\n let newConfig = config;\n\n newConfig = withSentryDebugId(newConfig);\n newConfig = withSentryFramesCollapsed(newConfig);\n if (annotateReactComponents) {\n newConfig = withSentryBabelTransformer(newConfig);\n }\n\n return newConfig;\n}\n\n/**\n * This function returns Default Expo configuration with Sentry plugins.\n */\nexport function getSentryExpoConfig(\n projectRoot: string,\n options: DefaultConfigOptions & SentryExpoConfigOptions & SentryMetroConfigOptions = {},\n): MetroConfig {\n setSentryMetroDevServerEnvFlag();\n\n const getDefaultConfig = options.getDefaultConfig || loadExpoMetroConfigModule().getDefaultConfig;\n const config = getDefaultConfig(projectRoot, {\n ...options,\n unstable_beforeAssetSerializationPlugins: [\n ...(options.unstable_beforeAssetSerializationPlugins || []),\n unstable_beforeAssetSerializationPlugin,\n ],\n });\n\n let newConfig = withSentryFramesCollapsed(config);\n if (options.annotateReactComponents) {\n newConfig = withSentryBabelTransformer(newConfig);\n }\n\n return newConfig;\n}\n\nfunction loadExpoMetroConfigModule(): {\n getDefaultConfig: (\n projectRoot: string,\n options: {\n unstable_beforeAssetSerializationPlugins?: ((serializationInput: {\n graph: ReadOnlyGraph<MixedOutput>;\n premodules: Module[];\n debugId?: string;\n }) => Module[])[];\n },\n ) => MetroConfig;\n} {\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n return require('expo/metro-config');\n } catch (e) {\n throw new Error('Unable to load `expo/metro-config`. Make sure you have Expo installed.');\n }\n}\n\n/**\n * Adds Sentry Babel transformer to the Metro config.\n */\nexport function withSentryBabelTransformer(config: MetroConfig): MetroConfig {\n const defaultBabelTransformerPath = config.transformer && config.transformer.babelTransformerPath;\n logger.debug('Default Babel transformer path from `config.transformer`:', defaultBabelTransformerPath);\n\n if (!defaultBabelTransformerPath) {\n // This has to be console.warn because the options is enabled but won't be used\n // eslint-disable-next-line no-console\n console.warn('`transformer.babelTransformerPath` is undefined.');\n // eslint-disable-next-line no-console\n console.warn('Sentry Babel transformer cannot be used. Not adding it...');\n return config;\n }\n\n if (defaultBabelTransformerPath) {\n saveDefaultBabelTransformerPath(defaultBabelTransformerPath);\n process.on('exit', () => {\n cleanDefaultBabelTransformerPath();\n });\n }\n\n return {\n ...config,\n transformer: {\n ...config.transformer,\n babelTransformerPath: require.resolve('./sentryBabelTransformer'),\n },\n };\n}\n\ntype MetroCustomSerializer = Required<Required<MetroConfig>['serializer']>['customSerializer'] | undefined;\n\nfunction withSentryDebugId(config: MetroConfig): MetroConfig {\n const customSerializer = createSentryMetroSerializer(\n config.serializer?.customSerializer || undefined,\n ) as MetroCustomSerializer;\n // MetroConfig types customSerializers as async only, but sync returns are also supported\n // The default serializer is sync\n\n return {\n ...config,\n serializer: {\n ...config.serializer,\n customSerializer,\n },\n };\n}\n\ntype MetroFrame = Parameters<Required<Required<MetroConfig>['symbolicator']>['customizeFrame']>[0];\ntype MetroCustomizeFrame = { readonly collapse?: boolean };\ntype MetroCustomizeFrameReturnValue =\n | ReturnType<Required<Required<MetroConfig>['symbolicator']>['customizeFrame']>\n | undefined;\n\n/**\n * Collapses Sentry internal frames from the stack trace view in LogBox.\n */\nexport function withSentryFramesCollapsed(config: MetroConfig): MetroConfig {\n const originalCustomizeFrame = config.symbolicator?.customizeFrame;\n const collapseSentryInternalFrames = (frame: MetroFrame): boolean =>\n typeof frame.file === 'string' &&\n (frame.file.includes('node_modules/@sentry/utils/cjs/instrument.js') ||\n frame.file.includes('node_modules/@sentry/utils/cjs/logger.js'));\n\n const customizeFrame = (frame: MetroFrame): MetroCustomizeFrameReturnValue => {\n const originalOrSentryCustomizeFrame = (\n originalCustomization: MetroCustomizeFrame | undefined,\n ): MetroCustomizeFrame => ({\n ...originalCustomization,\n collapse: (originalCustomization && originalCustomization.collapse) || collapseSentryInternalFrames(frame),\n });\n\n const maybePromiseCustomization = (originalCustomizeFrame && originalCustomizeFrame(frame)) || undefined;\n\n if (maybePromiseCustomization !== undefined && 'then' in maybePromiseCustomization) {\n return maybePromiseCustomization.then<MetroCustomizeFrame>(originalCustomization =>\n originalOrSentryCustomizeFrame(originalCustomization),\n );\n }\n\n return originalOrSentryCustomizeFrame(maybePromiseCustomization);\n };\n\n return {\n ...config,\n symbolicator: {\n ...config.symbolicator,\n customizeFrame,\n },\n };\n}\n\n/**\n * Sets the `___SENTRY_METRO_DEV_SERVER___` environment flag.\n * This is used to determine if the SDK is running in Node in Metro Dev Server.\n * For example during static routes generation in `expo-router`.\n */\nfunction setSentryMetroDevServerEnvFlag(): void {\n env.___SENTRY_METRO_DEV_SERVER___ = 'true';\n}\n"]}
|
|
1
|
+
{"version":3,"file":"metroconfig.js","sourceRoot":"","sources":["../../../src/js/tools/metroconfig.ts"],"names":[],"mappings":";;;AAAA,yCAAuC;AAGvC,mCAAmC;AACnC,qCAA8B;AAE9B,iDAA8C;AAC9C,+EAAkH;AAClH,mEAA+G;AAE/G,kEAAwC;AAExC,IAAA,2BAAY,GAAE,CAAC;AAsBf;;;;;GAKG;AACH,SAAgB,gBAAgB,CAC9B,MAAmB,EACnB,EAAE,uBAAuB,GAAG,KAAK,EAAE,gBAAgB,GAAG,IAAI,KAA+B,EAAE;IAE3F,8BAA8B,EAAE,CAAC;IAEjC,IAAI,SAAS,GAAG,MAAM,CAAC;IAEvB,SAAS,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACzC,SAAS,GAAG,yBAAyB,CAAC,SAAS,CAAC,CAAC;IACjD,IAAI,uBAAuB,EAAE;QAC3B,SAAS,GAAG,0BAA0B,CAAC,SAAS,CAAC,CAAC;KACnD;IACD,IAAI,gBAAgB,KAAK,KAAK,EAAE;QAC9B,SAAS,GAAG,kBAAkB,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;KAC7D;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAlBD,4CAkBC;AAED;;GAEG;AACH,SAAgB,mBAAmB,CACjC,WAAmB,EACnB,UAAqF,EAAE;IAEvF,8BAA8B,EAAE,CAAC;IAEjC,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,yBAAyB,EAAE,CAAC,gBAAgB,CAAC;IAClG,MAAM,MAAM,GAAG,gBAAgB,CAAC,WAAW,kCACtC,OAAO,KACV,wCAAwC,EAAE;YACxC,GAAG,CAAC,OAAO,CAAC,wCAAwC,IAAI,EAAE,CAAC;YAC3D,+DAAuC;SACxC,IACD,CAAC;IAEH,IAAI,SAAS,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClD,IAAI,OAAO,CAAC,uBAAuB,EAAE;QACnC,SAAS,GAAG,0BAA0B,CAAC,SAAS,CAAC,CAAC;KACnD;IAED,IAAI,OAAO,CAAC,gBAAgB,KAAK,KAAK,EAAE;QACtC,SAAS,GAAG,kBAAkB,CAAC,SAAS,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;KACrE;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAzBD,kDAyBC;AAED,SAAS,yBAAyB;IAYhC,IAAI;QACF,8DAA8D;QAC9D,OAAO,OAAO,CAAC,mBAAmB,CAAC,CAAC;KACrC;IAAC,OAAO,CAAC,EAAE;QACV,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAC;KAC3F;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,0BAA0B,CAAC,MAAmB;IAC5D,MAAM,2BAA2B,GAAG,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC;IAClG,cAAM,CAAC,KAAK,CAAC,2DAA2D,EAAE,2BAA2B,CAAC,CAAC;IAEvG,IAAI,CAAC,2BAA2B,EAAE;QAChC,+EAA+E;QAC/E,sCAAsC;QACtC,OAAO,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;QACjE,sCAAsC;QACtC,OAAO,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;QAC1E,OAAO,MAAM,CAAC;KACf;IAED,IAAI,2BAA2B,EAAE;QAC/B,IAAA,6DAA+B,EAAC,2BAA2B,CAAC,CAAC;QAC7D,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;YACtB,IAAA,8DAAgC,GAAE,CAAC;QACrC,CAAC,CAAC,CAAC;KACJ;IAED,uCACK,MAAM,KACT,WAAW,kCACN,MAAM,CAAC,WAAW,KACrB,oBAAoB,EAAE,OAAO,CAAC,OAAO,CAAC,0BAA0B,CAAC,OAEnE;AACJ,CAAC;AA3BD,gEA2BC;AAID,SAAS,iBAAiB,CAAC,MAAmB;;IAC5C,MAAM,gBAAgB,GAAG,IAAA,mDAA2B,EAClD,CAAA,MAAA,MAAM,CAAC,UAAU,0CAAE,gBAAgB,KAAI,SAAS,CACxB,CAAC;IAC3B,yFAAyF;IACzF,iCAAiC;IAEjC,uCACK,MAAM,KACT,UAAU,kCACL,MAAM,CAAC,UAAU,KACpB,gBAAgB,OAElB;AACJ,CAAC;AAUD;;GAEG;AACH,SAAgB,kBAAkB,CAAC,MAAmB,EAAE,gBAAqC;;IAC3F,MAAM,gBAAgB,GAAG,MAAA,MAAM,CAAC,QAAQ,0CAAE,cAA2E,CAAC;IAEtH,MAAM,qBAAqB,GAAmB,CAC5C,OAAgC,EAChC,UAAkB,EAClB,QAAuB,EACvB,kBAA2B,EAC3B,EAAE;QACF,IACE,CAAC,gBAAgB,KAAK,KAAK;YACzB,CAAC,gBAAgB,KAAK,SAAS,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC;YACrF,CAAC,kBAAkB,aAAlB,kBAAkB,cAAlB,kBAAkB,GAAI,UAAU,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAC7D;YACA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAgB,CAAC;SACxC;QACD,IAAI,gBAAgB,EAAE;YACpB,OAAO,kBAAkB;gBACvB,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,kBAAkB,CAAC;gBACrE,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;SACrD;QAED,0HAA0H;QAC1H,IAAI,OAAO,CAAC,cAAc,KAAK,qBAAqB,EAAE;YACpD,sCAAsC;YACtC,OAAO,CAAC,KAAK,CACX;;;;;iHAKyG,CAC1G,CAAC;YACF,4BAA4B;YAC5B,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;SACzB;QAED,OAAO,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC/D,CAAC,CAAC;IAEF,uCACK,MAAM,KACT,QAAQ,kCACH,MAAM,CAAC,QAAQ,KAClB,cAAc,EAAE,qBAAqB,OAEvC;AACJ,CAAC;AA/CD,gDA+CC;AAQD;;GAEG;AACH,SAAgB,yBAAyB,CAAC,MAAmB;;IAC3D,MAAM,sBAAsB,GAAG,MAAA,MAAM,CAAC,YAAY,0CAAE,cAAc,CAAC;IACnE,MAAM,4BAA4B,GAAG,CAAC,KAAiB,EAAW,EAAE,CAClE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAC9B,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,8CAA8C,CAAC;YAClE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,0CAA0C,CAAC,CAAC,CAAC;IAErE,MAAM,cAAc,GAAG,CAAC,KAAiB,EAAkC,EAAE;QAC3E,MAAM,8BAA8B,GAAG,CACrC,qBAAsD,EACjC,EAAE,CAAC,iCACrB,qBAAqB,KACxB,QAAQ,EAAE,CAAC,qBAAqB,IAAI,qBAAqB,CAAC,QAAQ,CAAC,IAAI,4BAA4B,CAAC,KAAK,CAAC,IAC1G,CAAC;QAEH,MAAM,yBAAyB,GAAG,CAAC,sBAAsB,IAAI,sBAAsB,CAAC,KAAK,CAAC,CAAC,IAAI,SAAS,CAAC;QAEzG,IAAI,yBAAyB,KAAK,SAAS,IAAI,MAAM,IAAI,yBAAyB,EAAE;YAClF,OAAO,yBAAyB,CAAC,IAAI,CAAsB,qBAAqB,CAAC,EAAE,CACjF,8BAA8B,CAAC,qBAAqB,CAAC,CACtD,CAAC;SACH;QAED,OAAO,8BAA8B,CAAC,yBAAyB,CAAC,CAAC;IACnE,CAAC,CAAC;IAEF,uCACK,MAAM,KACT,YAAY,kCACP,MAAM,CAAC,YAAY,KACtB,cAAc,OAEhB;AACJ,CAAC;AAjCD,8DAiCC;AAED;;;;GAIG;AACH,SAAS,8BAA8B;IACrC,aAAG,CAAC,6BAA6B,GAAG,MAAM,CAAC;AAC7C,CAAC","sourcesContent":["import { logger } from '@sentry/utils';\nimport type { MetroConfig, MixedOutput, Module, ReadOnlyGraph } from 'metro';\nimport type { CustomResolutionContext, CustomResolver, Resolution } from 'metro-resolver';\nimport * as process from 'process';\nimport { env } from 'process';\n\nimport { enableLogger } from './enableLogger';\nimport { cleanDefaultBabelTransformerPath, saveDefaultBabelTransformerPath } from './sentryBabelTransformerUtils';\nimport { createSentryMetroSerializer, unstable_beforeAssetSerializationPlugin } from './sentryMetroSerializer';\nimport type { DefaultConfigOptions } from './vendor/expo/expoconfig';\nexport * from './sentryMetroSerializer';\n\nenableLogger();\n\nexport interface SentryMetroConfigOptions {\n /**\n * Annotates React components with Sentry data.\n * @default false\n */\n annotateReactComponents?: boolean;\n /**\n * Adds the Sentry replay package for web.\n * @default true\n */\n includeWebReplay?: boolean;\n}\n\nexport interface SentryExpoConfigOptions {\n /**\n * Pass a custom `getDefaultConfig` function to override the default Expo configuration getter.\n */\n getDefaultConfig?: typeof getSentryExpoConfig;\n}\n\n/**\n * Adds Sentry to the Metro config.\n *\n * Adds Debug ID to the output bundle and source maps.\n * Collapses Sentry frames from the stack trace view in LogBox.\n */\nexport function withSentryConfig(\n config: MetroConfig,\n { annotateReactComponents = false, includeWebReplay = true }: SentryMetroConfigOptions = {},\n): MetroConfig {\n setSentryMetroDevServerEnvFlag();\n\n let newConfig = config;\n\n newConfig = withSentryDebugId(newConfig);\n newConfig = withSentryFramesCollapsed(newConfig);\n if (annotateReactComponents) {\n newConfig = withSentryBabelTransformer(newConfig);\n }\n if (includeWebReplay === false) {\n newConfig = withSentryResolver(newConfig, includeWebReplay);\n }\n\n return newConfig;\n}\n\n/**\n * This function returns Default Expo configuration with Sentry plugins.\n */\nexport function getSentryExpoConfig(\n projectRoot: string,\n options: DefaultConfigOptions & SentryExpoConfigOptions & SentryMetroConfigOptions = {},\n): MetroConfig {\n setSentryMetroDevServerEnvFlag();\n\n const getDefaultConfig = options.getDefaultConfig || loadExpoMetroConfigModule().getDefaultConfig;\n const config = getDefaultConfig(projectRoot, {\n ...options,\n unstable_beforeAssetSerializationPlugins: [\n ...(options.unstable_beforeAssetSerializationPlugins || []),\n unstable_beforeAssetSerializationPlugin,\n ],\n });\n\n let newConfig = withSentryFramesCollapsed(config);\n if (options.annotateReactComponents) {\n newConfig = withSentryBabelTransformer(newConfig);\n }\n\n if (options.includeWebReplay === false) {\n newConfig = withSentryResolver(newConfig, options.includeWebReplay);\n }\n\n return newConfig;\n}\n\nfunction loadExpoMetroConfigModule(): {\n getDefaultConfig: (\n projectRoot: string,\n options: {\n unstable_beforeAssetSerializationPlugins?: ((serializationInput: {\n graph: ReadOnlyGraph<MixedOutput>;\n premodules: Module[];\n debugId?: string;\n }) => Module[])[];\n },\n ) => MetroConfig;\n} {\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n return require('expo/metro-config');\n } catch (e) {\n throw new Error('Unable to load `expo/metro-config`. Make sure you have Expo installed.');\n }\n}\n\n/**\n * Adds Sentry Babel transformer to the Metro config.\n */\nexport function withSentryBabelTransformer(config: MetroConfig): MetroConfig {\n const defaultBabelTransformerPath = config.transformer && config.transformer.babelTransformerPath;\n logger.debug('Default Babel transformer path from `config.transformer`:', defaultBabelTransformerPath);\n\n if (!defaultBabelTransformerPath) {\n // This has to be console.warn because the options is enabled but won't be used\n // eslint-disable-next-line no-console\n console.warn('`transformer.babelTransformerPath` is undefined.');\n // eslint-disable-next-line no-console\n console.warn('Sentry Babel transformer cannot be used. Not adding it...');\n return config;\n }\n\n if (defaultBabelTransformerPath) {\n saveDefaultBabelTransformerPath(defaultBabelTransformerPath);\n process.on('exit', () => {\n cleanDefaultBabelTransformerPath();\n });\n }\n\n return {\n ...config,\n transformer: {\n ...config.transformer,\n babelTransformerPath: require.resolve('./sentryBabelTransformer'),\n },\n };\n}\n\ntype MetroCustomSerializer = Required<Required<MetroConfig>['serializer']>['customSerializer'] | undefined;\n\nfunction withSentryDebugId(config: MetroConfig): MetroConfig {\n const customSerializer = createSentryMetroSerializer(\n config.serializer?.customSerializer || undefined,\n ) as MetroCustomSerializer;\n // MetroConfig types customSerializers as async only, but sync returns are also supported\n // The default serializer is sync\n\n return {\n ...config,\n serializer: {\n ...config.serializer,\n customSerializer,\n },\n };\n}\n\n// Based on: https://github.com/facebook/metro/blob/c21daba415ea26511e157f794689caab9abe8236/packages/metro-resolver/src/resolve.js#L86-L91\ntype CustomResolverBeforeMetro068 = (\n context: CustomResolutionContext,\n realModuleName: string,\n platform: string | null,\n moduleName?: string,\n) => Resolution;\n\n/**\n * Includes `@sentry/replay` packages based on the `includeWebReplay` flag and current bundle `platform`.\n */\nexport function withSentryResolver(config: MetroConfig, includeWebReplay: boolean | undefined): MetroConfig {\n const originalResolver = config.resolver?.resolveRequest as CustomResolver | CustomResolverBeforeMetro068 | undefined;\n\n const sentryResolverRequest: CustomResolver = (\n context: CustomResolutionContext,\n moduleName: string,\n platform: string | null,\n oldMetroModuleName?: string,\n ) => {\n if (\n (includeWebReplay === false ||\n (includeWebReplay === undefined && (platform === 'android' || platform === 'ios'))) &&\n (oldMetroModuleName ?? moduleName).includes('@sentry/replay')\n ) {\n return { type: 'empty' } as Resolution;\n }\n if (originalResolver) {\n return oldMetroModuleName\n ? originalResolver(context, moduleName, platform, oldMetroModuleName)\n : originalResolver(context, moduleName, platform);\n }\n\n // Prior 0.68, resolve context.resolveRequest is sentryResolver itself, where on later version it is the default resolver.\n if (context.resolveRequest === sentryResolverRequest) {\n // eslint-disable-next-line no-console\n console.error(\n `Error: [@sentry/react-native/metro] Can not resolve the defaultResolver on Metro older than 0.68.\nPlease follow one of the following options:\n- Include your resolverRequest on your metroconfig.\n- Update your Metro version to 0.68 or higher.\n- Set includeWebReplay as true on your metro config.\n- If you are still facing issues, report the issue at http://www.github.com/getsentry/sentry-react-native/issues`,\n );\n // Return required for test.\n return process.exit(-1);\n }\n\n return context.resolveRequest(context, moduleName, platform);\n };\n\n return {\n ...config,\n resolver: {\n ...config.resolver,\n resolveRequest: sentryResolverRequest,\n },\n };\n}\n\ntype MetroFrame = Parameters<Required<Required<MetroConfig>['symbolicator']>['customizeFrame']>[0];\ntype MetroCustomizeFrame = { readonly collapse?: boolean };\ntype MetroCustomizeFrameReturnValue =\n | ReturnType<Required<Required<MetroConfig>['symbolicator']>['customizeFrame']>\n | undefined;\n\n/**\n * Collapses Sentry internal frames from the stack trace view in LogBox.\n */\nexport function withSentryFramesCollapsed(config: MetroConfig): MetroConfig {\n const originalCustomizeFrame = config.symbolicator?.customizeFrame;\n const collapseSentryInternalFrames = (frame: MetroFrame): boolean =>\n typeof frame.file === 'string' &&\n (frame.file.includes('node_modules/@sentry/utils/cjs/instrument.js') ||\n frame.file.includes('node_modules/@sentry/utils/cjs/logger.js'));\n\n const customizeFrame = (frame: MetroFrame): MetroCustomizeFrameReturnValue => {\n const originalOrSentryCustomizeFrame = (\n originalCustomization: MetroCustomizeFrame | undefined,\n ): MetroCustomizeFrame => ({\n ...originalCustomization,\n collapse: (originalCustomization && originalCustomization.collapse) || collapseSentryInternalFrames(frame),\n });\n\n const maybePromiseCustomization = (originalCustomizeFrame && originalCustomizeFrame(frame)) || undefined;\n\n if (maybePromiseCustomization !== undefined && 'then' in maybePromiseCustomization) {\n return maybePromiseCustomization.then<MetroCustomizeFrame>(originalCustomization =>\n originalOrSentryCustomizeFrame(originalCustomization),\n );\n }\n\n return originalOrSentryCustomizeFrame(maybePromiseCustomization);\n };\n\n return {\n ...config,\n symbolicator: {\n ...config.symbolicator,\n customizeFrame,\n },\n };\n}\n\n/**\n * Sets the `___SENTRY_METRO_DEV_SERVER___` environment flag.\n * This is used to determine if the SDK is running in Node in Metro Dev Server.\n * For example during static routes generation in `expo-router`.\n */\nfunction setSentryMetroDevServerEnvFlag(): void {\n env.___SENTRY_METRO_DEV_SERVER___ = 'true';\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"touchevents.d.ts","sourceRoot":"","sources":["../../src/js/touchevents.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"touchevents.d.ts","sourceRoot":"","sources":["../../src/js/touchevents.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,MAAM,MAAM,uBAAuB,GAAG;IACpC;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IACrC;;;OAGG;IACH,mBAAmB,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAC7C;;OAEG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAqCF;;GAEG;AACH,cAAM,kBAAmB,SAAQ,KAAK,CAAC,SAAS,CAAC,uBAAuB,CAAC;IACvE,OAAc,WAAW,EAAE,MAAM,CAAiC;IAClE,OAAc,YAAY,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAK1D;IAEF,SAAgB,IAAI,EAAE,MAAM,CAAwB;IAEpD;;OAEG;IACI,iBAAiB,IAAI,IAAI;IAKhC;;OAEG;IACI,MAAM,IAAI,KAAK,CAAC,SAAS;IAYhC;;OAEG;IACH,OAAO,CAAC,cAAc;IAkBtB;;OAEG;IACH,OAAO,CAAC,cAAc;IAoBtB;;;OAGG;IAEH,OAAO,CAAC,aAAa;IAyCrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAuB1B;AA0DD;;;;GAIG;AACH,QAAA,MAAM,sBAAsB,mBAEV,MAAM,aAAa,CAAC,GAAG,CAAC,kBACxB,uBAAuB,KACtC,MAAM,iBAUR,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,CAAC"}
|
package/dist/js/touchevents.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { addBreadcrumb, getClient } from '@sentry/core';
|
|
1
|
+
import { addBreadcrumb, getClient, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
|
|
2
2
|
import { dropUndefinedKeys, logger } from '@sentry/utils';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { StyleSheet, View } from 'react-native';
|
|
5
5
|
import { createIntegration } from './integrations/factory';
|
|
6
6
|
import { startUserInteractionSpan } from './tracing/integrations/userInteraction';
|
|
7
7
|
import { UI_ACTION_TOUCH } from './tracing/ops';
|
|
8
|
+
import { SPAN_ORIGIN_AUTO_INTERACTION } from './tracing/origin';
|
|
8
9
|
const touchEventStyles = StyleSheet.create({
|
|
9
10
|
wrapperView: {
|
|
10
11
|
flex: 1,
|
|
@@ -104,10 +105,13 @@ class TouchEventBoundary extends React.Component {
|
|
|
104
105
|
if (touchPath.length > 0) {
|
|
105
106
|
this._logTouchEvent(touchPath, label);
|
|
106
107
|
}
|
|
107
|
-
startUserInteractionSpan({
|
|
108
|
+
const span = startUserInteractionSpan({
|
|
108
109
|
elementId: label,
|
|
109
110
|
op: UI_ACTION_TOUCH,
|
|
110
111
|
});
|
|
112
|
+
if (span) {
|
|
113
|
+
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_ORIGIN_AUTO_INTERACTION);
|
|
114
|
+
}
|
|
111
115
|
}
|
|
112
116
|
/**
|
|
113
117
|
* Pushes the name to the componentTreeNames array if it is not ignored.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"touchevents.js","sourceRoot":"","sources":["../../src/js/touchevents.tsx"],"names":[],"mappings":"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","sourcesContent":["import { addBreadcrumb, getClient } from '@sentry/core';\nimport type { SeverityLevel } from '@sentry/types';\nimport { dropUndefinedKeys, logger } from '@sentry/utils';\nimport * as React from 'react';\nimport type { GestureResponderEvent } from 'react-native';\nimport { StyleSheet, View } from 'react-native';\n\nimport { createIntegration } from './integrations/factory';\nimport { startUserInteractionSpan } from './tracing/integrations/userInteraction';\nimport { UI_ACTION_TOUCH } from './tracing/ops';\n\nexport type TouchEventBoundaryProps = {\n /**\n * The category assigned to the breadcrumb that is logged by the touch event.\n */\n breadcrumbCategory?: string;\n /**\n * The type assigned to the breadcrumb that is logged by the touch event.\n */\n breadcrumbType?: string;\n /**\n * The max number of components to display when logging a touch's component tree.\n */\n maxComponentTreeSize?: number;\n /**\n * Component name(s) to ignore when logging the touch event. This prevents unhelpful logs such as\n * \"Touch event within element: View\" where you still can't tell which View it occurred in.\n */\n ignoreNames?: Array<string | RegExp>;\n /**\n * Deprecated, use ignoreNames instead\n * @deprecated\n */\n ignoredDisplayNames?: Array<string | RegExp>;\n /**\n * React Node wrapped by TouchEventBoundary.\n */\n children?: React.ReactNode;\n /**\n * Label Name used to identify the touched element.\n */\n labelName?: string;\n};\n\nconst touchEventStyles = StyleSheet.create({\n wrapperView: {\n flex: 1,\n },\n});\n\nconst DEFAULT_BREADCRUMB_CATEGORY = 'touch';\nconst DEFAULT_BREADCRUMB_TYPE = 'user';\nconst DEFAULT_MAX_COMPONENT_TREE_SIZE = 20;\n\nconst SENTRY_LABEL_PROP_KEY = 'sentry-label';\nconst SENTRY_COMPONENT_PROP_KEY = 'data-sentry-component';\nconst SENTRY_ELEMENT_PROP_KEY = 'data-sentry-element';\nconst SENTRY_FILE_PROP_KEY = 'data-sentry-source-file';\n\ninterface ElementInstance {\n elementType?: {\n displayName?: string;\n name?: string;\n };\n memoizedProps?: Record<string, unknown>;\n return?: ElementInstance;\n}\n\ninterface TouchedComponentInfo {\n name?: string;\n label?: string;\n element?: string;\n file?: string;\n}\n\ninterface PrivateGestureResponderEvent extends GestureResponderEvent {\n _targetInst?: ElementInstance;\n}\n\n/**\n * Boundary to log breadcrumbs for interaction events.\n */\nclass TouchEventBoundary extends React.Component<TouchEventBoundaryProps> {\n public static displayName: string = '__Sentry.TouchEventBoundary';\n public static defaultProps: Partial<TouchEventBoundaryProps> = {\n breadcrumbCategory: DEFAULT_BREADCRUMB_CATEGORY,\n breadcrumbType: DEFAULT_BREADCRUMB_TYPE,\n ignoreNames: [],\n maxComponentTreeSize: DEFAULT_MAX_COMPONENT_TREE_SIZE,\n };\n\n public readonly name: string = 'TouchEventBoundary';\n\n /**\n * Registers the TouchEventBoundary as a Sentry Integration.\n */\n public componentDidMount(): void {\n const client = getClient();\n client?.addIntegration?.(createIntegration(this.name));\n }\n\n /**\n *\n */\n public render(): React.ReactNode {\n return (\n <View\n style={touchEventStyles.wrapperView}\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onTouchStart={this._onTouchStart.bind(this) as any}\n >\n {this.props.children}\n </View>\n );\n }\n\n /**\n * Logs the touch event given the component tree names and a label.\n */\n private _logTouchEvent(touchPath: TouchedComponentInfo[], label?: string): void {\n const level = 'info' as SeverityLevel;\n\n const root = touchPath[0];\n const detail = label ? label : `${root.name}${root.file ? ` (${root.file})` : ''}`;\n\n const crumb = {\n category: this.props.breadcrumbCategory,\n data: { path: touchPath },\n level: level,\n message: `Touch event within element: ${detail}`,\n type: this.props.breadcrumbType,\n };\n addBreadcrumb(crumb);\n\n logger.log(`[TouchEvents] ${crumb.message}`);\n }\n\n /**\n * Checks if the name is supposed to be ignored.\n */\n private _isNameIgnored(name: string): boolean {\n let ignoreNames = this.props.ignoreNames || [];\n // eslint-disable-next-line deprecation/deprecation\n if (this.props.ignoredDisplayNames) {\n // This is to make it compatible with prior version.\n // eslint-disable-next-line deprecation/deprecation\n ignoreNames = [...ignoreNames, ...this.props.ignoredDisplayNames];\n }\n\n return ignoreNames.some(\n (ignoreName: string | RegExp) =>\n (typeof ignoreName === 'string' && name === ignoreName) ||\n (ignoreName instanceof RegExp && name.match(ignoreName)),\n );\n }\n\n // Originally was going to clean the names of any HOCs as well but decided that it might hinder debugging effectively. Will leave here in case\n // private readonly _cleanName = (name: string): string =>\n // name.replace(/.*\\(/g, \"\").replace(/\\)/g, \"\");\n\n /**\n * Traverses through the component tree when a touch happens and logs it.\n * @param e\n */\n // eslint-disable-next-line complexity\n private _onTouchStart(e: PrivateGestureResponderEvent): void {\n if (!e._targetInst) {\n return;\n }\n\n let currentInst: ElementInstance | undefined = e._targetInst;\n const touchPath: TouchedComponentInfo[] = [];\n\n while (\n currentInst &&\n // maxComponentTreeSize will always be defined as we have a defaultProps. But ts needs a check so this is here.\n this.props.maxComponentTreeSize &&\n touchPath.length < this.props.maxComponentTreeSize\n ) {\n if (\n // If the loop gets to the boundary itself, break.\n currentInst.elementType?.displayName === TouchEventBoundary.displayName\n ) {\n break;\n }\n\n const info = getTouchedComponentInfo(currentInst, this.props.labelName);\n this._pushIfNotIgnored(touchPath, info);\n\n currentInst = currentInst.return;\n }\n\n const label = touchPath.find(info => info.label)?.label;\n if (touchPath.length > 0) {\n this._logTouchEvent(touchPath, label);\n }\n\n startUserInteractionSpan({\n elementId: label,\n op: UI_ACTION_TOUCH,\n });\n }\n\n /**\n * Pushes the name to the componentTreeNames array if it is not ignored.\n */\n private _pushIfNotIgnored(touchPath: TouchedComponentInfo[], value: TouchedComponentInfo | undefined): boolean {\n if (!value) {\n return false;\n }\n\n if (!value.name && !value.label) {\n return false;\n }\n if (value.name && this._isNameIgnored(value.name)) {\n return false;\n }\n if (value.label && this._isNameIgnored(value.label)) {\n return false;\n }\n\n // Deduplicate same subsequent items.\n if (touchPath.length > 0 && JSON.stringify(touchPath[touchPath.length - 1]) === JSON.stringify(value)) {\n return false;\n }\n\n touchPath.push(value);\n return true;\n }\n}\n\nfunction getTouchedComponentInfo(currentInst: ElementInstance, labelKey: string | undefined): TouchedComponentInfo | undefined {\n const displayName = currentInst.elementType?.displayName;\n\n const props = currentInst.memoizedProps;\n if (!props) {\n // Early return if no props are available, as we can't extract any useful information\n if (displayName) {\n return {\n name: displayName,\n };\n }\n return undefined;\n }\n\n return dropUndefinedKeys<TouchedComponentInfo>({\n // provided by @sentry/babel-plugin-component-annotate\n name: getComponentName(props) || displayName,\n element: getElementName(props),\n file: getFileName(props),\n\n // `sentry-label` or user defined label key\n label: getLabelValue(props, labelKey),\n });\n}\n\nfunction getComponentName(props: Record<string, unknown>): string | undefined {\n return typeof props[SENTRY_COMPONENT_PROP_KEY] === 'string' &&\n props[SENTRY_COMPONENT_PROP_KEY].length > 0 &&\n props[SENTRY_COMPONENT_PROP_KEY] !== 'unknown' &&\n props[SENTRY_COMPONENT_PROP_KEY] || undefined;\n}\n\nfunction getElementName(props: Record<string, unknown>): string | undefined {\n return typeof props[SENTRY_ELEMENT_PROP_KEY] === 'string' &&\n props[SENTRY_ELEMENT_PROP_KEY].length > 0 &&\n props[SENTRY_ELEMENT_PROP_KEY] !== 'unknown' &&\n props[SENTRY_ELEMENT_PROP_KEY] || undefined;\n}\n\nfunction getFileName(props: Record<string, unknown>): string | undefined {\n return typeof props[SENTRY_FILE_PROP_KEY] === 'string' &&\n props[SENTRY_FILE_PROP_KEY].length > 0 &&\n props[SENTRY_FILE_PROP_KEY] !== 'unknown' &&\n props[SENTRY_FILE_PROP_KEY] || undefined;\n}\n\nfunction getLabelValue(props: Record<string, unknown>, labelKey: string | undefined): string | undefined {\n return typeof props[SENTRY_LABEL_PROP_KEY] === 'string' && props[SENTRY_LABEL_PROP_KEY].length > 0\n ? props[SENTRY_LABEL_PROP_KEY] as string\n // For some reason type narrowing doesn't work as expected with indexing when checking it all in one go in\n // the \"check-label\" if sentence, so we have to assign it to a variable here first\n : typeof labelKey === 'string' && typeof props[labelKey] == 'string' && (props[labelKey] as string).length > 0\n ? props[labelKey] as string\n : undefined;\n}\n\n/**\n * Convenience Higher-Order-Component for TouchEventBoundary\n * @param WrappedComponent any React Component\n * @param boundaryProps TouchEventBoundaryProps\n */\nconst withTouchEventBoundary = (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n InnerComponent: React.ComponentType<any>,\n boundaryProps?: TouchEventBoundaryProps,\n): React.FunctionComponent => {\n const WrappedComponent: React.FunctionComponent = props => (\n <TouchEventBoundary {...(boundaryProps ?? {})}>\n <InnerComponent {...props} />\n </TouchEventBoundary>\n );\n\n WrappedComponent.displayName = 'WithTouchEventBoundary';\n\n return WrappedComponent;\n};\n\nexport { TouchEventBoundary, withTouchEventBoundary };\n"]}
|
|
1
|
+
{"version":3,"file":"touchevents.js","sourceRoot":"","sources":["../../src/js/touchevents.tsx"],"names":[],"mappings":"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","sourcesContent":["import { addBreadcrumb, getClient, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';\nimport type { SeverityLevel } from '@sentry/types';\nimport { dropUndefinedKeys, logger } from '@sentry/utils';\nimport * as React from 'react';\nimport type { GestureResponderEvent } from 'react-native';\nimport { StyleSheet, View } from 'react-native';\n\nimport { createIntegration } from './integrations/factory';\nimport { startUserInteractionSpan } from './tracing/integrations/userInteraction';\nimport { UI_ACTION_TOUCH } from './tracing/ops';\nimport { SPAN_ORIGIN_AUTO_INTERACTION } from './tracing/origin';\n\nexport type TouchEventBoundaryProps = {\n /**\n * The category assigned to the breadcrumb that is logged by the touch event.\n */\n breadcrumbCategory?: string;\n /**\n * The type assigned to the breadcrumb that is logged by the touch event.\n */\n breadcrumbType?: string;\n /**\n * The max number of components to display when logging a touch's component tree.\n */\n maxComponentTreeSize?: number;\n /**\n * Component name(s) to ignore when logging the touch event. This prevents unhelpful logs such as\n * \"Touch event within element: View\" where you still can't tell which View it occurred in.\n */\n ignoreNames?: Array<string | RegExp>;\n /**\n * Deprecated, use ignoreNames instead\n * @deprecated\n */\n ignoredDisplayNames?: Array<string | RegExp>;\n /**\n * React Node wrapped by TouchEventBoundary.\n */\n children?: React.ReactNode;\n /**\n * Label Name used to identify the touched element.\n */\n labelName?: string;\n};\n\nconst touchEventStyles = StyleSheet.create({\n wrapperView: {\n flex: 1,\n },\n});\n\nconst DEFAULT_BREADCRUMB_CATEGORY = 'touch';\nconst DEFAULT_BREADCRUMB_TYPE = 'user';\nconst DEFAULT_MAX_COMPONENT_TREE_SIZE = 20;\n\nconst SENTRY_LABEL_PROP_KEY = 'sentry-label';\nconst SENTRY_COMPONENT_PROP_KEY = 'data-sentry-component';\nconst SENTRY_ELEMENT_PROP_KEY = 'data-sentry-element';\nconst SENTRY_FILE_PROP_KEY = 'data-sentry-source-file';\n\ninterface ElementInstance {\n elementType?: {\n displayName?: string;\n name?: string;\n };\n memoizedProps?: Record<string, unknown>;\n return?: ElementInstance;\n}\n\ninterface TouchedComponentInfo {\n name?: string;\n label?: string;\n element?: string;\n file?: string;\n}\n\ninterface PrivateGestureResponderEvent extends GestureResponderEvent {\n _targetInst?: ElementInstance;\n}\n\n/**\n * Boundary to log breadcrumbs for interaction events.\n */\nclass TouchEventBoundary extends React.Component<TouchEventBoundaryProps> {\n public static displayName: string = '__Sentry.TouchEventBoundary';\n public static defaultProps: Partial<TouchEventBoundaryProps> = {\n breadcrumbCategory: DEFAULT_BREADCRUMB_CATEGORY,\n breadcrumbType: DEFAULT_BREADCRUMB_TYPE,\n ignoreNames: [],\n maxComponentTreeSize: DEFAULT_MAX_COMPONENT_TREE_SIZE,\n };\n\n public readonly name: string = 'TouchEventBoundary';\n\n /**\n * Registers the TouchEventBoundary as a Sentry Integration.\n */\n public componentDidMount(): void {\n const client = getClient();\n client?.addIntegration?.(createIntegration(this.name));\n }\n\n /**\n *\n */\n public render(): React.ReactNode {\n return (\n <View\n style={touchEventStyles.wrapperView}\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onTouchStart={this._onTouchStart.bind(this) as any}\n >\n {this.props.children}\n </View>\n );\n }\n\n /**\n * Logs the touch event given the component tree names and a label.\n */\n private _logTouchEvent(touchPath: TouchedComponentInfo[], label?: string): void {\n const level = 'info' as SeverityLevel;\n\n const root = touchPath[0];\n const detail = label ? label : `${root.name}${root.file ? ` (${root.file})` : ''}`;\n\n const crumb = {\n category: this.props.breadcrumbCategory,\n data: { path: touchPath },\n level: level,\n message: `Touch event within element: ${detail}`,\n type: this.props.breadcrumbType,\n };\n addBreadcrumb(crumb);\n\n logger.log(`[TouchEvents] ${crumb.message}`);\n }\n\n /**\n * Checks if the name is supposed to be ignored.\n */\n private _isNameIgnored(name: string): boolean {\n let ignoreNames = this.props.ignoreNames || [];\n // eslint-disable-next-line deprecation/deprecation\n if (this.props.ignoredDisplayNames) {\n // This is to make it compatible with prior version.\n // eslint-disable-next-line deprecation/deprecation\n ignoreNames = [...ignoreNames, ...this.props.ignoredDisplayNames];\n }\n\n return ignoreNames.some(\n (ignoreName: string | RegExp) =>\n (typeof ignoreName === 'string' && name === ignoreName) ||\n (ignoreName instanceof RegExp && name.match(ignoreName)),\n );\n }\n\n // Originally was going to clean the names of any HOCs as well but decided that it might hinder debugging effectively. Will leave here in case\n // private readonly _cleanName = (name: string): string =>\n // name.replace(/.*\\(/g, \"\").replace(/\\)/g, \"\");\n\n /**\n * Traverses through the component tree when a touch happens and logs it.\n * @param e\n */\n // eslint-disable-next-line complexity\n private _onTouchStart(e: PrivateGestureResponderEvent): void {\n if (!e._targetInst) {\n return;\n }\n\n let currentInst: ElementInstance | undefined = e._targetInst;\n const touchPath: TouchedComponentInfo[] = [];\n\n while (\n currentInst &&\n // maxComponentTreeSize will always be defined as we have a defaultProps. But ts needs a check so this is here.\n this.props.maxComponentTreeSize &&\n touchPath.length < this.props.maxComponentTreeSize\n ) {\n if (\n // If the loop gets to the boundary itself, break.\n currentInst.elementType?.displayName === TouchEventBoundary.displayName\n ) {\n break;\n }\n\n const info = getTouchedComponentInfo(currentInst, this.props.labelName);\n this._pushIfNotIgnored(touchPath, info);\n\n currentInst = currentInst.return;\n }\n\n const label = touchPath.find(info => info.label)?.label;\n if (touchPath.length > 0) {\n this._logTouchEvent(touchPath, label);\n }\n\n const span = startUserInteractionSpan({\n elementId: label,\n op: UI_ACTION_TOUCH,\n });\n if (span) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_ORIGIN_AUTO_INTERACTION);\n }\n }\n\n /**\n * Pushes the name to the componentTreeNames array if it is not ignored.\n */\n private _pushIfNotIgnored(touchPath: TouchedComponentInfo[], value: TouchedComponentInfo | undefined): boolean {\n if (!value) {\n return false;\n }\n\n if (!value.name && !value.label) {\n return false;\n }\n if (value.name && this._isNameIgnored(value.name)) {\n return false;\n }\n if (value.label && this._isNameIgnored(value.label)) {\n return false;\n }\n\n // Deduplicate same subsequent items.\n if (touchPath.length > 0 && JSON.stringify(touchPath[touchPath.length - 1]) === JSON.stringify(value)) {\n return false;\n }\n\n touchPath.push(value);\n return true;\n }\n}\n\nfunction getTouchedComponentInfo(currentInst: ElementInstance, labelKey: string | undefined): TouchedComponentInfo | undefined {\n const displayName = currentInst.elementType?.displayName;\n\n const props = currentInst.memoizedProps;\n if (!props) {\n // Early return if no props are available, as we can't extract any useful information\n if (displayName) {\n return {\n name: displayName,\n };\n }\n return undefined;\n }\n\n return dropUndefinedKeys<TouchedComponentInfo>({\n // provided by @sentry/babel-plugin-component-annotate\n name: getComponentName(props) || displayName,\n element: getElementName(props),\n file: getFileName(props),\n\n // `sentry-label` or user defined label key\n label: getLabelValue(props, labelKey),\n });\n}\n\nfunction getComponentName(props: Record<string, unknown>): string | undefined {\n return typeof props[SENTRY_COMPONENT_PROP_KEY] === 'string' &&\n props[SENTRY_COMPONENT_PROP_KEY].length > 0 &&\n props[SENTRY_COMPONENT_PROP_KEY] !== 'unknown' &&\n props[SENTRY_COMPONENT_PROP_KEY] || undefined;\n}\n\nfunction getElementName(props: Record<string, unknown>): string | undefined {\n return typeof props[SENTRY_ELEMENT_PROP_KEY] === 'string' &&\n props[SENTRY_ELEMENT_PROP_KEY].length > 0 &&\n props[SENTRY_ELEMENT_PROP_KEY] !== 'unknown' &&\n props[SENTRY_ELEMENT_PROP_KEY] || undefined;\n}\n\nfunction getFileName(props: Record<string, unknown>): string | undefined {\n return typeof props[SENTRY_FILE_PROP_KEY] === 'string' &&\n props[SENTRY_FILE_PROP_KEY].length > 0 &&\n props[SENTRY_FILE_PROP_KEY] !== 'unknown' &&\n props[SENTRY_FILE_PROP_KEY] || undefined;\n}\n\nfunction getLabelValue(props: Record<string, unknown>, labelKey: string | undefined): string | undefined {\n return typeof props[SENTRY_LABEL_PROP_KEY] === 'string' && props[SENTRY_LABEL_PROP_KEY].length > 0\n ? props[SENTRY_LABEL_PROP_KEY] as string\n // For some reason type narrowing doesn't work as expected with indexing when checking it all in one go in\n // the \"check-label\" if sentence, so we have to assign it to a variable here first\n : typeof labelKey === 'string' && typeof props[labelKey] == 'string' && (props[labelKey] as string).length > 0\n ? props[labelKey] as string\n : undefined;\n}\n\n/**\n * Convenience Higher-Order-Component for TouchEventBoundary\n * @param WrappedComponent any React Component\n * @param boundaryProps TouchEventBoundaryProps\n */\nconst withTouchEventBoundary = (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n InnerComponent: React.ComponentType<any>,\n boundaryProps?: TouchEventBoundaryProps,\n): React.FunctionComponent => {\n const WrappedComponent: React.FunctionComponent = props => (\n <TouchEventBoundary {...(boundaryProps ?? {})}>\n <InnerComponent {...props} />\n </TouchEventBoundary>\n );\n\n WrappedComponent.displayName = 'WithTouchEventBoundary';\n\n return WrappedComponent;\n};\n\nexport { TouchEventBoundary, withTouchEventBoundary };\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gesturetracing.d.ts","sourceRoot":"","sources":["../../../src/js/tracing/gesturetracing.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gesturetracing.d.ts","sourceRoot":"","sources":["../../../src/js/tracing/gesturetracing.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,2BAA2B,YAAY,CAAC;AACrD,eAAO,MAAM,uBAAuB,SAAS,CAAC;AAE9C,eAAO,MAAM,sBAAsB,QAA0B,CAAC;AAC9D,eAAO,MAAM,uBAAuB,YAAY,CAAC;AAwBjD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ;AACzC;;;GAGG;AACH,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,QAAQ,GAChB,QAAQ,CA+CV"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { addBreadcrumb } from '@sentry/core';
|
|
1
|
+
import { addBreadcrumb, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
|
|
2
2
|
import { logger } from '@sentry/utils';
|
|
3
3
|
import { startUserInteractionSpan } from './integrations/userInteraction';
|
|
4
4
|
import { UI_ACTION } from './ops';
|
|
5
|
+
import { SPAN_ORIGIN_AUTO_INTERACTION } from './origin';
|
|
5
6
|
export const DEFAULT_BREADCRUMB_CATEGORY = 'gesture';
|
|
6
7
|
export const DEFAULT_BREADCRUMB_TYPE = 'user';
|
|
7
8
|
export const GESTURE_POSTFIX_LENGTH = 'GestureHandler'.length;
|
|
@@ -36,7 +37,10 @@ label, gesture) {
|
|
|
36
37
|
: ACTION_GESTURE_FALLBACK;
|
|
37
38
|
const originalOnBegin = gestureCandidate.handlers.onBegin;
|
|
38
39
|
gesture.handlers.onBegin = (event) => {
|
|
39
|
-
startUserInteractionSpan({ elementId: label, op: `${UI_ACTION}.${name}` });
|
|
40
|
+
const span = startUserInteractionSpan({ elementId: label, op: `${UI_ACTION}.${name}` });
|
|
41
|
+
if (span) {
|
|
42
|
+
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_ORIGIN_AUTO_INTERACTION);
|
|
43
|
+
}
|
|
40
44
|
addGestureBreadcrumb(`Gesture ${label} begin.`, { event, name });
|
|
41
45
|
if (originalOnBegin) {
|
|
42
46
|
originalOnBegin(event);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gesturetracing.js","sourceRoot":"","sources":["../../../src/js/tracing/gesturetracing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"gesturetracing.js","sourceRoot":"","sources":["../../../src/js/tracing/gesturetracing.ts"],"names":[],"mappings":"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","sourcesContent":["import { addBreadcrumb, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';\nimport type { Breadcrumb } from '@sentry/types';\nimport { logger } from '@sentry/utils';\n\nimport { startUserInteractionSpan } from './integrations/userInteraction';\nimport { UI_ACTION } from './ops';\nimport { SPAN_ORIGIN_AUTO_INTERACTION } from './origin';\n\nexport const DEFAULT_BREADCRUMB_CATEGORY = 'gesture';\nexport const DEFAULT_BREADCRUMB_TYPE = 'user';\n\nexport const GESTURE_POSTFIX_LENGTH = 'GestureHandler'.length;\nexport const ACTION_GESTURE_FALLBACK = 'gesture';\n\n/**\n * Internal interface following RNGH 2 Gesture Event API.\n * We need to use this to avoid importing RNGH 2 types and depending on it.\n * https://github.com/software-mansion/react-native-gesture-handler/blob/f0868f7ccf678c947ef65519ebf97ae149a10289/src/handlers/gestures/gesture.ts#L55\n * @hidden\n */\ntype GestureEvent = Record<string, unknown>;\n\n/**\n * Internal interface for RNGH 2 Gesture API.\n * We need to use this to avoid importing RNGH 2 types and depending on it.\n * https://github.com/software-mansion/react-native-gesture-handler/blob/2.9.0/src/handlers/gestures/gesture.ts#L120\n * @hidden\n */\ninterface BaseGesture {\n handlers?: {\n onBegin?: (event: GestureEvent) => void;\n onEnd?: (event: GestureEvent) => void;\n };\n handlerName: string;\n}\n\n/**\n * Patches React Native Gesture Handler v2 Gesture to start a transaction on gesture begin with the appropriate label.\n * Example: ShoppingCartScreen.dismissGesture\n */\nexport function sentryTraceGesture<GestureT>(\n /**\n * Label of the gesture to be used in transaction name.\n * Example: dismissGesture\n */\n label: string,\n gesture: GestureT,\n): GestureT {\n const gestureCandidate = gesture as unknown as BaseGesture | undefined | null;\n if (!gestureCandidate) {\n logger.warn('[GestureTracing] Gesture can not be undefined');\n return gesture;\n }\n if (!gestureCandidate.handlers) {\n logger.warn(\n '[GestureTracing] Can not wrap gesture without handlers. If you want to wrap a gesture composition wrap individual gestures.',\n );\n return gesture;\n }\n if (!label) {\n logger.warn('[GestureTracing] Can not wrap gesture without name.');\n return gesture;\n }\n const name =\n gestureCandidate.handlerName.length > GESTURE_POSTFIX_LENGTH\n ? gestureCandidate.handlerName\n .substring(0, gestureCandidate.handlerName.length - GESTURE_POSTFIX_LENGTH)\n .toLowerCase()\n : ACTION_GESTURE_FALLBACK;\n\n const originalOnBegin = gestureCandidate.handlers.onBegin;\n (gesture as unknown as Required<BaseGesture>).handlers.onBegin = (event: GestureEvent) => {\n const span = startUserInteractionSpan({ elementId: label, op: `${UI_ACTION}.${name}` });\n if (span) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_ORIGIN_AUTO_INTERACTION);\n }\n\n addGestureBreadcrumb(`Gesture ${label} begin.`, { event, name });\n\n if (originalOnBegin) {\n originalOnBegin(event);\n }\n };\n\n const originalOnEnd = gestureCandidate.handlers.onEnd;\n (gesture as unknown as Required<BaseGesture>).handlers.onEnd = (event: GestureEvent) => {\n addGestureBreadcrumb(`Gesture ${label} end.`, { event, name });\n\n if (originalOnEnd) {\n originalOnEnd(event);\n }\n };\n\n return gesture;\n}\n\nfunction addGestureBreadcrumb(\n message: string,\n options: {\n event: Record<string, unknown> | undefined | null;\n name: string;\n },\n): void {\n const { event, name } = options;\n const crumb: Breadcrumb = {\n message,\n level: 'info',\n type: DEFAULT_BREADCRUMB_TYPE,\n category: DEFAULT_BREADCRUMB_CATEGORY,\n };\n\n if (event) {\n const data: Record<string, unknown> = {\n gesture: name,\n };\n for (const key of Object.keys(GestureEventKeys)) {\n const eventKey = GestureEventKeys[key as keyof typeof GestureEventKeys];\n if (eventKey in event) {\n data[eventKey] = event[eventKey];\n }\n }\n crumb.data = data;\n }\n\n addBreadcrumb(crumb);\n\n logger.log(`[GestureTracing] ${crumb.message}`);\n}\n\n/**\n * Selected keys from RNGH 2 Gesture Event API.\n * We only want to send relevant data to save on payload size.\n * @hidden\n */\nconst GestureEventKeys = {\n NUMBER_OF_POINTERS: 'numberOfPointers',\n NUMBER_OF_TOUCHES: 'numberOfTouches',\n FORCE: 'force',\n FORCE_CHANGE: 'forceChange',\n ROTATION: 'rotation',\n ROTATION_CHANGE: 'rotationChange',\n SCALE: 'scale',\n SCALE_CHANGE: 'scaleChange',\n DURATION: 'duration',\n VELOCITY: 'velocity',\n VELOCITY_X: 'velocityX',\n VELOCITY_Y: 'velocityY',\n} as const;\n"]}
|
|
@@ -7,11 +7,25 @@ export type AppStartIntegration = Integration & {
|
|
|
7
7
|
* Used automatically by `Sentry.wrap` and `Sentry.ReactNativeProfiler`.
|
|
8
8
|
*/
|
|
9
9
|
export declare function captureAppStart(): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* For internal use only.
|
|
12
|
+
*
|
|
13
|
+
* @private
|
|
14
|
+
*/
|
|
15
|
+
export declare function _captureAppStart({ isManual }: {
|
|
16
|
+
isManual: boolean;
|
|
17
|
+
}): Promise<void>;
|
|
10
18
|
/**
|
|
11
19
|
* Sets the root component first constructor call timestamp.
|
|
12
20
|
* Used automatically by `Sentry.wrap` and `Sentry.ReactNativeProfiler`.
|
|
13
21
|
*/
|
|
14
22
|
export declare function setRootComponentCreationTimestampMs(timestampMs: number): void;
|
|
23
|
+
/**
|
|
24
|
+
* For internal use only.
|
|
25
|
+
*
|
|
26
|
+
* @private
|
|
27
|
+
*/
|
|
28
|
+
export declare function _setRootComponentCreationTimestampMs(timestampMs: number): void;
|
|
15
29
|
/**
|
|
16
30
|
* For internal use only.
|
|
17
31
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appStart.d.ts","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/appStart.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"appStart.d.ts","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/appStart.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAiB,WAAW,EAA8B,MAAM,eAAe,CAAC;AAsB5F,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG;IAC9C,yBAAyB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD,CAAC;AAqBF;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzF;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAM7E;AAED;;;;GAIG;AACH,wBAAgB,oCAAoC,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAG9E;AAED;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,gBAAiB,MAAM,KAAG,IAGhE,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,sCAAsC,IAAI,IAAI,CAE7D;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB;IAG9B;;;;;OAKG;iBACU,OAAO;MACb,mBAyMR,CAAC"}
|