@dynatrace/react-native-plugin 2.331.1 → 2.333.1
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/README.md +96 -6
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +7 -1
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.kt +1 -0
- package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +1 -0
- package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +2 -1
- package/files/plugin.gradle +1 -1
- package/instrumentation/DynatraceInstrumentation.js +1 -1
- package/instrumentation/jsx/CreateElement.js +106 -6
- package/instrumentation/jsx/JsxDevRuntime.js +2 -6
- package/instrumentation/jsx/JsxRuntime.js +2 -6
- package/instrumentation/libs/withOnPressMonitoring.js +49 -3
- package/ios/DynatraceRNBridge.mm +8 -1
- package/lib/core/Application.js +2 -0
- package/lib/core/Dynatrace.js +2 -1
- package/lib/core/UserPrivacyOptions.js +8 -1
- package/lib/core/configuration/ConfigurationHandler.js +21 -0
- package/lib/features/ui-interaction/Config.js +36 -0
- package/lib/features/ui-interaction/IUserInteractionEvent.js +16 -0
- package/lib/features/ui-interaction/Plugin.js +945 -0
- package/lib/features/ui-interaction/RootDetection.js +51 -0
- package/lib/features/ui-interaction/RootWrapper.js +236 -0
- package/lib/features/ui-interaction/Run.js +34 -0
- package/lib/features/ui-interaction/Runtime.js +1494 -0
- package/lib/features/ui-interaction/Types.js +75 -0
- package/lib/next/Dynatrace.js +1 -1
- package/lib/next/configuration/INativeRuntimeConfiguration.js +1 -0
- package/lib/next/configuration/RuntimeConfigurationObserver.js +47 -12
- package/lib/next/events/EventPipeline.js +9 -0
- package/package.json +19 -10
- package/react-native-dynatrace.podspec +1 -1
- package/scripts/Config.js +1 -0
- package/src/lib/core/interface/NativeDynatraceBridge.ts +1 -0
- package/types.d.ts +22 -9
package/README.md
CHANGED
|
@@ -13,6 +13,7 @@ If you want to start using this plugin and are not a Dynatrace customer yet, hea
|
|
|
13
13
|
* User actions for onPress and onLongPress (Touchables, Buttons, Pickers, RefreshControl, Pressable)
|
|
14
14
|
* User actions for class and functional components (lifecycle events such as render(), didMount() and didUpdate())
|
|
15
15
|
* Reporting React Native errors
|
|
16
|
+
* UI Interaction feature toggle via `react.userInteraction` (enable/disable user interaction capturing at runtime)
|
|
16
17
|
* Manual instrumentation
|
|
17
18
|
* Typescript bindings to add manual instrumentation
|
|
18
19
|
* New React-Native architecture
|
|
@@ -26,15 +27,15 @@ If you want to start using this plugin and are not a Dynatrace customer yet, hea
|
|
|
26
27
|
* Android Gradle plugin version 7.0+
|
|
27
28
|
* Java 11
|
|
28
29
|
* Kotlin 2.0.21 - see [Kotlin Compatibility Note](#kotlin-compatibility-note)
|
|
29
|
-
* Jetpack Compose 1.4 - 1.
|
|
30
|
+
* Jetpack Compose 1.4 - 1.10 - see [Compose Compatibility Note](#compose-compatibility-note)
|
|
30
31
|
* For iOS users: Minimum iOS 12
|
|
31
32
|
* NodeJS 16.0.0+ since our dependencies require NodeJS 16.0.0
|
|
32
33
|
|
|
33
34
|
## Agent Versions
|
|
34
35
|
This agent versions are configured in this plugin:
|
|
35
36
|
|
|
36
|
-
* Android Agent: 8.
|
|
37
|
-
* iOS Agent: 8.
|
|
37
|
+
* Android Agent: 8.333.1.1006
|
|
38
|
+
* iOS Agent: 8.333.1.1005
|
|
38
39
|
|
|
39
40
|
## Quick Setup
|
|
40
41
|
|
|
@@ -64,12 +65,14 @@ This agent versions are configured in this plugin:
|
|
|
64
65
|
* [Set beacon headers](#setting-beacon-headers)
|
|
65
66
|
* [Exclude Individual JSX Elements](#exclude-individual-jsx-elements)
|
|
66
67
|
* [New RUM experience](#new-rum-experience)
|
|
68
|
+
* [User Interaction](#user-interaction)
|
|
67
69
|
* [Send Event](#send-event)
|
|
68
70
|
* [Send Session Property Event](#send-session-property-event)
|
|
69
71
|
* [Event Modifier](#event-modifier)
|
|
70
72
|
* [Send Exception Event](#send-exception-event)
|
|
71
73
|
* [Send HTTP Request Event](#send-http-request-event)
|
|
72
74
|
* [View Monitoring](#view-monitoring)
|
|
75
|
+
* [User Interaction](#user-interaction-1)
|
|
73
76
|
* [React Native Symbolication](#react-native-symbolication)
|
|
74
77
|
* [NPX Commands](#npx-commands)
|
|
75
78
|
* [npx instrumentDynatrace](#npx-instrumentdynatrace)
|
|
@@ -89,6 +92,7 @@ This agent versions are configured in this plugin:
|
|
|
89
92
|
* [Bundle Name and Version](#bundle-name-and-version)
|
|
90
93
|
* [Navigation](#navigation)
|
|
91
94
|
* [Source Map](#source-map)
|
|
95
|
+
* [User Interaction](#user-interaction-1)
|
|
92
96
|
* [Android block](#android-block)
|
|
93
97
|
* [iOS block](#ios-block)
|
|
94
98
|
* [Lifecycle modes](#lifecycle)
|
|
@@ -427,7 +431,7 @@ import { Dynatrace, DynatraceWebRequestTiming } from '@dynatrace/react-native-pl
|
|
|
427
431
|
const action = Dynatrace.enterManualAction('API Data Fetch');
|
|
428
432
|
const url = 'https://api.example.com/data';
|
|
429
433
|
const tag = await action.getRequestTag(url);
|
|
430
|
-
const timing = new DynatraceWebRequestTiming(
|
|
434
|
+
const timing = new DynatraceWebRequestTiming(tag, url);
|
|
431
435
|
|
|
432
436
|
try {
|
|
433
437
|
timing.startWebRequestTiming();
|
|
@@ -457,7 +461,7 @@ import { Dynatrace, DynatraceWebRequestTiming } from '@dynatrace/react-native-pl
|
|
|
457
461
|
const action = Dynatrace.enterManualAction('API Data Upload');
|
|
458
462
|
const url = 'https://api.example.com/upload';
|
|
459
463
|
const tag = await action.getRequestTag(url);
|
|
460
|
-
const timing = new DynatraceWebRequestTiming(
|
|
464
|
+
const timing = new DynatraceWebRequestTiming(tag, url);
|
|
461
465
|
const requestData = JSON.stringify({ key: 'value' });
|
|
462
466
|
|
|
463
467
|
try {
|
|
@@ -1012,6 +1016,42 @@ Dynatrace.sendEvent(new EventData()
|
|
|
1012
1016
|
Dynatrace.startView("UserProfileDetailed");
|
|
1013
1017
|
```
|
|
1014
1018
|
|
|
1019
|
+
### User Interaction
|
|
1020
|
+
|
|
1021
|
+
User Interaction is an automatic instrumentation feature that captures touch and press events in your React Native application without requiring any manual API calls. When enabled, the plugin instruments your UI components at build time and sends structured interaction events to Dynatrace at runtime.
|
|
1022
|
+
|
|
1023
|
+
To enable this feature, see the [User Interaction configuration](#user-interaction-1) section.
|
|
1024
|
+
|
|
1025
|
+
#### Produced data
|
|
1026
|
+
|
|
1027
|
+
Each captured interaction produces an event describing what the user touched and where. The event includes:
|
|
1028
|
+
|
|
1029
|
+
- **Element name** — the resolved label of the touched element, derived from its visible text, accessibility label, component name, or test ID.
|
|
1030
|
+
- **Component type** — the type of the UI component that was touched (e.g. `Pressable`).
|
|
1031
|
+
- **Element path** — a stable path through the component tree that uniquely identifies the element (e.g. `App/View[1]/Pressable[1]`).
|
|
1032
|
+
- **Interaction type** — how the user interacted (e.g. `touch`).
|
|
1033
|
+
- **Position** — the screen coordinates where the touch occurred.
|
|
1034
|
+
|
|
1035
|
+
In some cases, a **responder** is also included. The responder is the component that ultimately handled the user's touch — for example, a `Pressable` that received the press event. It carries the same name, component type, and path information as the touched element, and can differ when a touch is visually on a child element but handled by a parent.
|
|
1036
|
+
|
|
1037
|
+
#### Example event
|
|
1038
|
+
|
|
1039
|
+
```json
|
|
1040
|
+
{
|
|
1041
|
+
"characteristics.has_user_interaction": true,
|
|
1042
|
+
"ui_element.detected_name": "LoginButton",
|
|
1043
|
+
"ui_element.components": ["Pressable"],
|
|
1044
|
+
"ui_element.id": "App/View[1]/Pressable[1]",
|
|
1045
|
+
"ui_element.name_origin": "component",
|
|
1046
|
+
"interaction.type": "touch",
|
|
1047
|
+
"positions": [{ "x": 120, "y": 460 }],
|
|
1048
|
+
"ui_element.responder.detected_name": "Pressable",
|
|
1049
|
+
"ui_element.responder.components": ["Pressable"],
|
|
1050
|
+
"ui_element.responder.id": "App/View[1]/Pressable[1]",
|
|
1051
|
+
"ui_element.responder.name_origin": "component"
|
|
1052
|
+
}
|
|
1053
|
+
```
|
|
1054
|
+
|
|
1015
1055
|
### React Native Symbolication
|
|
1016
1056
|
|
|
1017
1057
|
Dynatrace can automatically symbolicate JavaScript stack traces captured by the plugin using sourcemaps. This allows you to view human-readable file names, line numbers, and column information in your crash reports.
|
|
@@ -1229,6 +1269,7 @@ The `react` configuration block contains all settings regarding the react instru
|
|
|
1229
1269
|
|
|
1230
1270
|
```js
|
|
1231
1271
|
react : {
|
|
1272
|
+
|
|
1232
1273
|
input : {
|
|
1233
1274
|
instrument(filename) => {
|
|
1234
1275
|
return true;
|
|
@@ -1269,6 +1310,47 @@ react: {
|
|
|
1269
1310
|
|
|
1270
1311
|
This activates the debug mode. You will get more console output during instrumentation and at runtime.
|
|
1271
1312
|
|
|
1313
|
+
|
|
1314
|
+
### User Interaction
|
|
1315
|
+
|
|
1316
|
+
```js
|
|
1317
|
+
react: {
|
|
1318
|
+
userInteraction: true // set it to true here if you want to enable UI interaction, default value is false
|
|
1319
|
+
}
|
|
1320
|
+
```
|
|
1321
|
+
|
|
1322
|
+
Enables or disables the UI interaction (user interaction) feature.
|
|
1323
|
+
Set to false to disable capturing of user interactions (e.g., touch/click actions) produced by the React Native UI interaction instrumentation.
|
|
1324
|
+
|
|
1325
|
+
#### What customers will observe after enabling UI Interaction
|
|
1326
|
+
|
|
1327
|
+
After setting `react.userInteraction: true` and rebuilding with instrumentation, the expected flow is:
|
|
1328
|
+
|
|
1329
|
+
1. Build-time instrumentation wraps supported UI elements and app root entrypoints.
|
|
1330
|
+
2. At runtime, touch/press interactions are captured and converted into UI interaction events.
|
|
1331
|
+
3. Events are processed by the plugin event pipeline and sent to Dynatrace.
|
|
1332
|
+
4. In Dynatrace, customers can analyze captured user interactions (for example, touch-driven behavior and related UI element context).
|
|
1333
|
+
|
|
1334
|
+
Notes:
|
|
1335
|
+
|
|
1336
|
+
- No extra UI needs to be added in customer screens for standard automatic capture.
|
|
1337
|
+
- If `react.debug` is enabled, additional debug output can appear during instrumentation/runtime.
|
|
1338
|
+
|
|
1339
|
+
#### Runtime switching (config + remote configuration observer)
|
|
1340
|
+
|
|
1341
|
+
UI Interaction can be controlled by two layers:
|
|
1342
|
+
|
|
1343
|
+
1. **Build/config layer (`dynatrace.config.js`)**
|
|
1344
|
+
- `react.userInteraction: true|false` controls whether the UI Interaction instrumentation feature is applied.
|
|
1345
|
+
|
|
1346
|
+
2. **Runtime remote layer (`RuntimeConfigurationObserver`)**
|
|
1347
|
+
- Runtime emission checks the remote flag `touch_interaction_enabled`.
|
|
1348
|
+
- If remote flag is present, it is used as the source of truth.
|
|
1349
|
+
- If remote flag is temporarily unavailable, the plugin falls back to the last known good remote value.
|
|
1350
|
+
- If no remote value was received yet, runtime defaults to enabled behavior.
|
|
1351
|
+
|
|
1352
|
+
In short: local config enables the feature path, while remote configuration can dynamically allow/deny event emission at runtime.
|
|
1353
|
+
|
|
1272
1354
|
#### Error Handler
|
|
1273
1355
|
|
|
1274
1356
|
```js
|
|
@@ -1825,7 +1907,7 @@ In summary, ensure your build fulfills our Kotlin 2.0.21 requirement while simul
|
|
|
1825
1907
|
|
|
1826
1908
|
## Compose Compatibility Note
|
|
1827
1909
|
|
|
1828
|
-
Our Android Agent currently supports **Jetpack Compose 1.4 - 1.
|
|
1910
|
+
Our Android Agent currently supports **Jetpack Compose 1.4 - 1.10**. If you are using an incompatible version of Jetpack Compose, you may encounter the following error message during build:
|
|
1829
1911
|
|
|
1830
1912
|
```
|
|
1831
1913
|
Could not resolve all dependencies for configuration ':app:debugCompileClasspath'.
|
|
@@ -1972,6 +2054,14 @@ If you are struggling with a problem, submit a support ticket to Dynatrace (supp
|
|
|
1972
2054
|
<br/><br/>
|
|
1973
2055
|
## Changelog
|
|
1974
2056
|
|
|
2057
|
+
Latest
|
|
2058
|
+
|
|
2059
|
+
2.333.1
|
|
2060
|
+
* Jetpack Compose support range extended to 1.4 - 1.10 see [Compose Compatibility Note](#compose-compatibility-note)
|
|
2061
|
+
* Updated Android (8.333.1.1006) & iOS Agent (8.333.1.1005)
|
|
2062
|
+
* Added Configuration flag to enable/disable the [User Interaction feature](#user-interaction-1).
|
|
2063
|
+
* Added [User Interaction feature](#user-interaction) to collect UI interaction data such as touches, providing insights into user behavior
|
|
2064
|
+
|
|
1975
2065
|
2.331.1
|
|
1976
2066
|
* Updated Android (8.331.1.1004) & iOS Agent (8.331.1.1008)
|
|
1977
2067
|
|
package/android/build.gradle
CHANGED
|
@@ -72,7 +72,7 @@ repositories {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
dependencies {
|
|
75
|
-
implementation 'com.dynatrace.agent:agent-android:8.
|
|
75
|
+
implementation 'com.dynatrace.agent:agent-android:8.333.1.1006'
|
|
76
76
|
implementation "com.facebook.react:react-native:${safeExtGet('reactNative', '+')}"
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -75,6 +75,7 @@ class DynatraceRNBridgeImpl(
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
Dynatrace.startup(reactApplicationContext, builder.buildConfiguration())
|
|
78
|
+
|
|
78
79
|
promise.resolve(true)
|
|
79
80
|
}
|
|
80
81
|
}
|
|
@@ -383,6 +384,9 @@ class DynatraceRNBridgeImpl(
|
|
|
383
384
|
)!!
|
|
384
385
|
)
|
|
385
386
|
)
|
|
387
|
+
if (userPrivacyOptions.hasKey("_screenRecordOptedIn")) {
|
|
388
|
+
optionsBuilder.withScreenRecordOptedIn(userPrivacyOptions.getBoolean("_screenRecordOptedIn"))
|
|
389
|
+
}
|
|
386
390
|
Dynatrace.applyUserPrivacyOptions(
|
|
387
391
|
optionsBuilder
|
|
388
392
|
.build()
|
|
@@ -396,6 +400,7 @@ class DynatraceRNBridgeImpl(
|
|
|
396
400
|
val privacyMap = Arguments.createMap()
|
|
397
401
|
privacyMap.putString("dataCollectionLevel", options.dataCollectionLevel.name)
|
|
398
402
|
privacyMap.putBoolean("crashReportingOptedIn", options.isCrashReportingOptedIn)
|
|
403
|
+
privacyMap.putBoolean("screenRecordOptedIn", options.isScreenRecordOptedIn)
|
|
399
404
|
promise.resolve(privacyMap)
|
|
400
405
|
}
|
|
401
406
|
}
|
|
@@ -446,4 +451,5 @@ class DynatraceRNBridgeImpl(
|
|
|
446
451
|
private fun shouldWorkOnAndroid(platform: String?): Boolean {
|
|
447
452
|
return platform == null || platform == PLATFORM_ANDROID || platform == ""
|
|
448
453
|
}
|
|
449
|
-
|
|
454
|
+
|
|
455
|
+
}
|
package/files/plugin.gradle
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var a,n=require("@babel/runtime/helpers/interopRequireDefault"),e=n(require("@babel/runtime/helpers/toConsumableArray")),c=(Object.defineProperty(exports,"t",{value:!0}),exports.instrument=void 0,require("path")),u=require("jscodeshift"),i=require("jscodeshift/src/Collection"),r=require("../scripts/FileOperationHelper"),l=require("../scripts/PathsConstants"),f=require("../lib/core/util/GetValuesFromPackage"),t=require("../scripts/util/InstrumentUtil"),o=require("./libs/react-native/Touchables.InstrInfo"),s=require("./libs/react-native/RefreshControl.InstrInfo"),v=require("./libs/react-native/Switch.InstrInfo"),d=require("./libs/community/gesture-handler/Touchables.InstrInfo"),p=require("./libs/community/Picker.InstrInfo"),m=require("./model/Types"),g=require("./parser/ParserUtil"),y=((n=>{n[n.i=-1]="Filtered",n[n.u=0]="Normal",n[n.o=1]="ReactNative",n[n.l=2]="React",n[n.v=3]="ReactNativeCssInterop"})(a=a||{}),[]),q=(y.push.apply(y,(0,e.default)(o.instrumentationInfo)),y.push.apply(y,(0,e.default)(s.instrumentationInfo)),y.push.apply(y,(0,e.default)(v.instrumentationInfo)),y.push.apply(y,(0,e.default)(d.instrumentationInfo)),y.push.apply(y,(0,e.default)(p.instrumentationInfo)),["AppRegistry","AppRegistryImpl","renderApplication","ExceptionsManager"]),b="@dynatrace/react-native-plugin/instrumentation/libs",instrument=function(n,e,r){e=O(e);var t=z(e);if(t!==a.i){var i=!1,u=N(e,n);if(t===a.l)U(u),i=!0;else if(t===a.o)e.endsWith("AppRegistryImpl.js")?null!=r&&r.autoStart&&V(u)&&(i=!0):e.endsWith("AppRegistry.js")?null!=r&&r.autoStart&&w(u)&&(i=!0):e.endsWith("renderApplication.js")?(A(u),i=!0):e.endsWith("ExceptionsManager.js")&&(o=void 0!==r&&r.autoStart&&r.errorHandler.enabled,J(u,r.errorHandler.reportFatalErrorAsCrash,o),i=!0);else if(t===a.v)i=G(u)||i;else{var o=k(e,r);if(r.navigation.enabled&&L(e,u))i=!0;else{if(!o.input&&!o.lifecycle)return null!=r&&r.debug&&console.log("Dynatrace - Filtered All: ".concat(e)),I(e),n;o.lifecycle&&A(u)&&(i=!0),o.input&&y.forEach(function(n){n=X(u,n);u=n.root,i=i||n.p})}}i?(n=u.toSource({quote:"single"}),h(n,e)):I(e),null!=r&&r.debug&&i&&console.log("Dynatrace - Modified Filename: "+e)}else e.includes(c.join("@dynatrace","react-native-plugin"))&&e.endsWith(c.join("lib","core","configuration","ConfigurationPreset.js"))&&void 0!==r&&(t=(0,f.getHostAppBundleInfo)(l.default.getPackageJsonFile()),o=N(e,n),void 0!==r.lifecycle&&x(o,"getLifecycleUpdate",r.lifecycle.includeUpdate),void 0!==r.debug&&x(o,"getLogLevel",r.debug?0:1),void 0!==r.bundleName?x(o,"getBundleName",r.bundleName):null!==t&&x(o,"getBundleName",null==t?void 0:t.name),void 0!==r.bundleVersion?x(o,"getBundleVersion",r.bundleVersion):null!==t&&x(o,"getBundleVersion",null==t?void 0:t.version),void 0!==r.input&&void 0!==r.input.actionNamePrivacy&&x(o,"getActionNamePrivacy",r.input.actionNamePrivacy),void 0!==r.errorHandler&&(x(o,"isErrorHandlerEnabled",r.errorHandler.enabled),x(o,"isReportFatalErrorAsCrash",r.errorHandler.reportFatalErrorAsCrash)),r.autoStart&&x(o,"isAutoStartupEnabled",r.autoStart),n=o.toSource({quote:"single"}),h(n,e));return n},L=(exports.instrument=instrument,function(n,e){return!!T(n,e)&&(n="import { monitorNavigation } from '".concat(b,"/react-navigation/ReactNavigation';"),e.find(u.ImportDeclaration).at(0).insertBefore(n),!0)}),T=function(n,e){var r=!1;return n.includes("@react-navigation")&&n.includes("core")&&(n.includes("BaseNavigationContainer.js")||n.includes("BaseNavigationContainer.tsx"))&&e.find(u.VariableDeclarator,{id:{name:"getRootState"}}).forEach(function(n){r=!0,n.parent.insertAfter("monitorNavigation(getRootState);")}),r},A=function(n){var e=n.findJSXElements(),t=!1;return 0<e.length&&(n.find(u.FunctionDeclaration).forEach(function(n){var e,r=(0,i.fromPaths)([n]);0<r.findJSXElements().length&&null!=n&&null!=n.value&&null!=n.value.id&&n.value.id.name.toString()&&(e=r.find(u.ClassDeclaration),r=r.find(u.ClassExpression),0===e.length)&&0===r.length&&(j(n,m.Types.FunctionalComponent,n.value.id.name.toString()),t=!0)}),n.find(u.ClassDeclaration).forEach(function(n){0<(0,i.fromPaths)([n]).findJSXElements().length&&null!=n&&null!=n.value&&n.value.id&&n.value.id.name.toString()&&(j(n,m.Types.ClassComponent,n.value.id.name.toString()),t=!0)}),n.find(u.ArrowFunctionExpression).forEach(function(n){0<(0,i.fromPaths)([n]).findJSXElements().length&&null!=n.parent&&null!=n.parent.value&&null!=n.parent.value.id&&null!=n.parent.value.id.name&&(j(n,m.Types.FunctionalComponent,n.parent.value.id.name),t=!0)}),n.find(u.FunctionExpression).forEach(function(n){0<(0,i.fromPaths)([n]).findJSXElements().length&&null!=n.parent&&null!=n.parent.value&&null!=n.parent.value.id&&null!=n.parent.value.id.name&&(j(n,m.Types.FunctionalComponent,n.parent.value.id.name),t=!0)})),t},j=function(n,e,r){for(e=u.expressionStatement(u.assignmentExpression("=",u.memberExpression(u.identifier(r),u.identifier("_dtInfo")),M(e,r)));"body"!==(null==n?void 0:n.parentPath.name);)n=n.parentPath;void 0!==n.parentPath&&n.insertAfter(e)},M=function(n,e){return u.objectExpression([u.objectProperty(u.identifier("type"),u.numericLiteral(n)),u.objectProperty(u.identifier("name"),u.stringLiteral(e))])},x=function(n,e,r){var n=n.find(u.Identifier).filter(function(n){return n.node.name===e});1===n.length&&"ReturnStatement"===(n=n.paths()[0].parent.value.body.body[0]).type&&("boolean"==typeof r&&(n.argument=u.booleanLiteral(r)),"string"==typeof r&&(n.argument=u.stringLiteral(r)),"number"==typeof r)&&(n.argument=u.numericLiteral(r))},N=function(n,e){return u.withParser((0,g.chooseParser)(n,e))(e)},O=function(n){return c.isAbsolute(n)?n.replace(l.default.getApplicationPath()+c.sep,""):n},I=function(n){try{var e=c.join(l.default.getBuildPath(),n+t.INSTRUMENTED_FILE_EXTENSION);r.default.checkIfFileExistsSync(e),r.default.deleteFileSync(e)}catch(n){}},h=function(n,e){e=c.join(l.default.getBuildPath(),e);try{r.default.checkIfFileExistsSync(c.dirname(e))}catch(n){r.default.createDirectorySync(c.dirname(e))}r.default.writeTextToFileSync(e+t.INSTRUMENTED_FILE_EXTENSION,n)},k=function(n,e){var r={input:!1,lifecycle:!1};return void 0!==e&&(void 0!==e.lifecycle&&void 0!==e.lifecycle.instrument&&e.lifecycle.instrument(n)&&(r.lifecycle=!0),void 0!==e.input)&&void 0!==e.input.instrument&&e.input.instrument(n)&&(r.input=!0),r},U=function(n){var e,n=n.find(u.Program);1===n.length&&(e=u.expressionStatement(u.callExpression(u.memberExpression(u.callExpression(u.identifier("require"),[u.stringLiteral("@dynatrace/react-native-plugin/instrumentation/jsx/ElementHelper")]),u.identifier("instrumentCreateElement")),[u.memberExpression(u.identifier("module"),u.identifier("exports"))])),n.paths()[0].node.body.push(e))},V=function(n){var e=n.find(u.FunctionDeclaration,{id:{name:"runApplication"}});return 1===e.length&&(D(n,{m:"_DynatraceApplicationHandler",module:"@dynatrace/react-native-plugin",reference:"ApplicationHandler"}),R(e.get().value.body.body,0,_("_DynatraceApplicationHandler","startup",[])),!0)},w=function(n){var e=n.find(u.ObjectMethod,{key:{name:"runApplication"}});return 1===e.length&&(D(n,{m:"_DynatraceApplicationHandler",module:"@dynatrace/react-native-plugin",reference:"ApplicationHandler"}),R(e.get().value.body.body,0,_("_DynatraceApplicationHandler","startup",[])),!0)},J=function(n,r,t){var i=u;n.find(i.FunctionDeclaration,{id:{name:"handleException"}}).forEach(function(n){var e=i.callExpression(i.memberExpression(i.callExpression(i.identifier("require"),[i.literal("@dynatrace/react-native-plugin/lib/core/ErrorHandler")]),i.identifier("reportErrorToDynatrace")),[i.identifier("e"),i.identifier("isFatal"),i.literal(r),i.literal(t)]),e=i.expressionStatement(i.callExpression(i.identifier("setTimeout"),[i.arrowFunctionExpression([],i.blockStatement(n.node.body.body)),e]));n.node.body.body=[e]})},G=function(n){var e=!1,n=n.find(u.CallExpression,{callee:{name:"require"}});return n.find(u.Literal,{value:"react/jsx-runtime"}).replaceWith(function(n){n=n.node;return n.value="@dynatrace/react-native-plugin/jsx-runtime",e=!0,n}),n.find(u.Literal,{value:"react/jsx-dev-runtime"}).replaceWith(function(n){n=n.node;return n.value="@dynatrace/react-native-plugin/jsx-dev-runtime",e=!0,n}),e},R=function(n,e){for(var r=arguments.length,t=new Array(2<r?r-2:0),i=2;i<r;i++)t[i-2]=arguments[i];return n.splice.apply(n,[e,0].concat(t))},z=function(n){if(n.includes("@dynatrace"))return a.i;var e=c.extname(n);if(".js"!==e&&".ts"!==e&&".tsx"!==e&&".jsx"!==e)return a.i;for(var r=c.parse(n),t=r.dir.split(c.sep),i=0;i<t.length;i++)if("node_modules"===t[i]){if("react-native"===t[i+1]||"create-react-class"===t[i+1]||"react-clone-referenced-element"===t[i+1])return q.includes(r.name)?a.o:a.i;if("react"===t[i+1]&&"index"===r.name)return a.l;if("react-native-css-interop"===t[i+1]&&("jsx-runtime"===r.name||"jsx-dev-runtime"===r.name))return a.v}return a.u},K=function(n,e,r){var t=Q(n,e,r);return W(n,e,r)||t},Q=function(n,e,r){var t=Y(n,e);return 0<t.length&&(void 0!==(t=H(t,e.reference,!1))&&(r.m=t.localName),tn(n,r),!0)},W=function(n,e,r){var t=C(n,e.module);if(1===t.length){t=H(t,e.reference,!0);if(void 0!==t)return un(n,r.defaultImport,t.localName,"ImportNamespaceSpecifier"===t.type),!0}return!1},X=function(n,e){var r=JSON.parse(JSON.stringify(e.new));return{root:n,p:K(n,e.old,r)||Z(n,e.old,e.new.defaultImport)}},Y=function(n,e){return n.find(u.ImportDeclaration).filter(function(n){return n.node.source.value===e.module&&null!=n.node.specifiers&&n.node.specifiers.some(function(n){return E(n)&&n.imported.name===e.reference||n.local&&n.local.name===e.reference})})},E=function(n){return void 0!==n.imported},Z=function(n,e,r){var t=!1;return n.find(u.CallExpression).filter(function(n){return $(n.node.callee)&&nn(n.node.arguments[0])&&n.node.arguments[0].value===e.module&&void 0!==n.parent}).forEach(function(n){(void 0===n.parent.value.property||void 0!==n.parent.value.property&&void 0!==n.parent.value.property.name&&n.parent.value.property.name===e.reference)&&(n.node.arguments[0].value=r,t=t||!0)}),t},$=function(n){return"require"===n.name},nn=function(n){return"StringLiteral"===n.type||"Literal"===n.type},C=function(n,e){return n.find(u.ImportDeclaration).filter(function(n){return n.node.source.value===e})},H=function(n,r,t){var i;return n.forEach(function(n){void 0!==n.node.specifiers&&(n.node.specifiers=n.node.specifiers.filter(function(n){var e;return E(n)&&!t?((e=n.imported.name!==r)||null==n.local||n.imported.name===n.local.name||(i={localName:n.local.name.toString(),type:n.type}),e):!(!E(n)&&t&&(null!=n.local&&(i={localName:n.local.name.toString(),type:n.type}),1))}),0===n.node.specifiers.length)&&n.prune()}),i},en=function(n,e){n.find(u.ImportDeclaration).filter(function(n){return n.node.source.value===e.module}).forEach(function(n){null!=n.node.specifiers&&n.node.specifiers.push(P(e))})},rn=function(n,e,r){n.find(u.ImportDeclaration).filter(function(n){return n.node.source.value===e}).forEach(function(n){null!=n.node.specifiers&&n.node.specifiers.push(r)})},S=function(n,e,r){var t=n.find(u.ImportDeclaration);0<t.length?u(t.paths()[0]).insertAfter(B(e,r)):1===(t=n.find(u.Program)).length&&t.paths()[0].node.body.unshift(B(e,r))},tn=function(n,e){0<C(n,e.module).length?en(n,e):S(n,e.module,[P(e)])},un=function(n,e,r,t){var i=C(n,e),t=(t?vn:sn)(r);0<i.length?rn(n,e,t):S(n,e,[t])},D=function(n,e){n=n.find(u.VariableDeclaration);0<n.length&&u(n.paths()[0]).insertAfter(an(e))},_=function(n,e,r){return u.expressionStatement(on(n,e,r))},on=function(n,e,r){return u.callExpression(fn(n,e),r)},an=function(n){return u.variableDeclaration("var",[cn(n)])},cn=function(n){return u.variableDeclarator(void 0!==n.m?u.identifier(n.m):u.identifier(n.reference),(0<n.reference.length?ln:F)(n))},ln=function(n){return u.memberExpression(F(n),u.identifier(n.reference))},fn=function(n,e){return u.memberExpression(u.identifier(n),u.identifier(e))},F=function(n){return u.callExpression(u.identifier("require"),[u.literal(n.module)])},B=function(n,e){return u.importDeclaration(e,u.literal(n))},P=function(n){return void 0!==n.m?u.importSpecifier(u.identifier(n.reference),u.identifier(n.m)):u.importSpecifier(u.identifier(n.reference))},sn=function(n){return u.importDefaultSpecifier(u.identifier(n))},vn=function(n){return u.importNamespaceSpecifier(u.identifier(n))};
|
|
1
|
+
var n=require("@babel/runtime/helpers/interopRequireDefault"),e=n(require("@babel/runtime/helpers/toConsumableArray"));function v(n,e){var r,t,i,u,o="undefined"!=typeof Symbol&&n[Symbol.iterator]||n["@@iterator"];if(o)return i=!(t=!0),{s:function(){o=o.call(n)},n:function(){var n=o.next();return t=n.done,n},e:function(n){i=!0,r=n},f:function(){try{t||null==o.return||o.return()}finally{if(i)throw r}}};if(Array.isArray(n)||(o=a(n))||e&&n&&"number"==typeof n.length)return o&&(n=o),u=0,{s:e=function(){},n:function(){return u>=n.length?{done:!0}:{done:!1,value:n[u++]}},e:function(n){throw n},f:e};throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function a(n,e){var r;if(n)return"string"==typeof n?t(n,e):"Map"===(r="Object"===(r={}.toString.call(n).slice(8,-1))&&n.constructor?n.constructor.name:r)||"Set"===r?Array.from(n):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?t(n,e):void 0}function t(n,e){(null==e||e>n.length)&&(e=n.length);for(var r=0,t=Array(e);r<e;r++)t[r]=n[r];return t}Object.defineProperty(exports,"t",{value:!0}),exports.instrument=void 0;var d,p=require("path"),u=require("jscodeshift"),i=require("jscodeshift/src/Collection"),r=require("../scripts/FileOperationHelper"),m=require("../scripts/PathsConstants"),y=require("../lib/core/util/GetValuesFromPackage"),o=require("../scripts/util/InstrumentUtil"),g=require("../lib/features/ui-interaction/Run"),c=require("./libs/react-native/Touchables.InstrInfo"),l=require("./libs/react-native/RefreshControl.InstrInfo"),f=require("./libs/react-native/Switch.InstrInfo"),s=require("./libs/community/gesture-handler/Touchables.InstrInfo"),P=require("./libs/community/Picker.InstrInfo"),b=require("./model/Types"),T=require("./parser/ParserUtil"),q=((n=>{n[n.i=-1]="Filtered",n[n.u=0]="Normal",n[n.o=1]="ReactNative",n[n.l=2]="React",n[n.v=3]="ReactNativeCssInterop"})(d=d||{}),[]),L=(q.push.apply(q,(0,e.default)(c.instrumentationInfo)),q.push.apply(q,(0,e.default)(l.instrumentationInfo)),q.push.apply(q,(0,e.default)(f.instrumentationInfo)),q.push.apply(q,(0,e.default)(s.instrumentationInfo)),q.push.apply(q,(0,e.default)(P.instrumentationInfo)),new Set(["AppRegistry","AppRegistryImpl","renderApplication","ExceptionsManager"])),M="@dynatrace/react-native-plugin/instrumentation/libs",instrument=function(n,e,r){e=V(e);var t=W(e);if(t!==d.i){var i=!1,u=I(e,n);if(t===d.l)G(u),i=!0;else if(t===d.o)e.endsWith("AppRegistryImpl.js")?null!=r&&r.autoStart&&$(u)&&(i=!0):e.endsWith("AppRegistry.js")?null!=r&&r.autoStart&&z(u)&&(i=!0):e.endsWith("renderApplication.js")?(A(u),i=!0):e.endsWith("ExceptionsManager.js")&&(o=void 0!==r&&r.autoStart&&r.errorHandler.enabled,K(u,r.errorHandler.reportFatalErrorAsCrash,o),i=!0);else if(t===d.v)i=Q(u)||i;else{var o=J(e,r),t=[{isEnabled:function(n,e){return!0===(null==e?void 0:e.userInteraction)},p:function(n,e,r){return(0,g.runDTUserInteraction)(n,e,r)}}].filter(function(n){return n.isEnabled(e,r)});if(r.navigation.enabled&&O(e,u))i=!0;else{if(!o.input&&!o.lifecycle&&0===t.length)return null!=r&&r.debug&&console.log("Dynatrace - Filtered All: ".concat(e)),x(e),n;o.lifecycle&&A(u)&&(i=!0),o.input&&q.forEach(function(n){n=nn(u,n);u=n.root,i=i||n.m})}var a,c=v(t);try{for(c.s();!(a=c.n()).done;){var l=a.value;try{var f=l.p(u,e,r),u=f.root;f.m&&(i=!0)}catch(n){var s=n instanceof Error?n.stack||n.message:String(n);null!=r&&r.debug&&console.log("[DynatraceInstrumentationRaw]: Feature instrumentation failed for ".concat(e,": ").concat(s))}}}catch(n){c.e(n)}finally{c.f()}}var o=i?u.toSource({quote:"single"}):n;i?N(n=o,e):x(e),null!=r&&r.debug&&i&&console.log("Dynatrace - Modified Filename: "+e)}else e.includes(p.join("@dynatrace","react-native-plugin"))&&e.endsWith(p.join("lib","core","configuration","ConfigurationPreset.js"))&&void 0!==r&&(t=(0,y.getHostAppBundleInfo)(m.default.getPackageJsonFile()),o=I(e,n),void 0!==r.lifecycle&&j(o,"getLifecycleUpdate",r.lifecycle.includeUpdate),void 0!==r.debug&&j(o,"getLogLevel",r.debug?0:1),void 0!==r.bundleName?j(o,"getBundleName",r.bundleName):null!==t&&j(o,"getBundleName",null==t?void 0:t.name),void 0!==r.bundleVersion?j(o,"getBundleVersion",r.bundleVersion):null!==t&&j(o,"getBundleVersion",null==t?void 0:t.version),void 0!==r.input&&void 0!==r.input.actionNamePrivacy&&j(o,"getActionNamePrivacy",r.input.actionNamePrivacy),void 0!==r.errorHandler&&(j(o,"isErrorHandlerEnabled",r.errorHandler.enabled),j(o,"isReportFatalErrorAsCrash",r.errorHandler.reportFatalErrorAsCrash)),r.autoStart&&j(o,"isAutoStartupEnabled",r.autoStart),n=o.toSource({quote:"single"}),N(n,e));return n},O=(exports.instrument=instrument,function(n,e){return!!U(n,e)&&(n="import { monitorNavigation } from '".concat(M,"/react-navigation/ReactNavigation';"),e.find(u.ImportDeclaration).at(0).insertBefore(n),!0)}),U=function(n,e){var r=!1;return n.includes("@react-navigation")&&n.includes("core")&&(n.includes("BaseNavigationContainer.js")||n.includes("BaseNavigationContainer.tsx"))&&e.find(u.VariableDeclarator,{id:{name:"getRootState"}}).forEach(function(n){r=!0,n.parent.insertAfter("monitorNavigation(getRootState);")}),r},A=function(n){var e=n.findJSXElements(),t=!1;return 0<e.length&&(n.find(u.FunctionDeclaration).forEach(function(n){var e,r=(0,i.fromPaths)([n]);0<r.findJSXElements().length&&null!=n&&null!=n.value&&null!=n.value.id&&n.value.id.name.toString()&&(e=r.find(u.ClassDeclaration),r=r.find(u.ClassExpression),0===e.length)&&0===r.length&&(h(n,b.Types.FunctionalComponent,n.value.id.name.toString()),t=!0)}),n.find(u.ClassDeclaration).forEach(function(n){0<(0,i.fromPaths)([n]).findJSXElements().length&&null!=n&&null!=n.value&&n.value.id&&n.value.id.name.toString()&&(h(n,b.Types.ClassComponent,n.value.id.name.toString()),t=!0)}),n.find(u.ArrowFunctionExpression).forEach(function(n){0<(0,i.fromPaths)([n]).findJSXElements().length&&null!=n.parent&&null!=n.parent.value&&null!=n.parent.value.id&&null!=n.parent.value.id.name&&(h(n,b.Types.FunctionalComponent,n.parent.value.id.name),t=!0)}),n.find(u.FunctionExpression).forEach(function(n){0<(0,i.fromPaths)([n]).findJSXElements().length&&null!=n.parent&&null!=n.parent.value&&null!=n.parent.value.id&&null!=n.parent.value.id.name&&(h(n,b.Types.FunctionalComponent,n.parent.value.id.name),t=!0)})),t},h=function(n,e,r){for(e=u.expressionStatement(u.assignmentExpression("=",u.memberExpression(u.identifier(r),u.identifier("_dtInfo")),k(e,r)));"body"!==(null==n?void 0:n.parentPath.name);)n=n.parentPath;void 0!==n.parentPath&&n.insertAfter(e)},k=function(n,e){return u.objectExpression([u.objectProperty(u.identifier("type"),u.numericLiteral(n)),u.objectProperty(u.identifier("name"),u.stringLiteral(e))])},j=function(n,e,r){var n=n.find(u.Identifier).filter(function(n){return n.node.name===e});1===n.length&&"ReturnStatement"===(n=n.paths()[0].parent.value.body.body[0]).type&&("boolean"==typeof r&&(n.argument=u.booleanLiteral(r)),"string"==typeof r&&(n.argument=u.stringLiteral(r)),"number"==typeof r)&&(n.argument=u.numericLiteral(r))},I=function(n,e){return u.withParser((0,T.chooseParser)(n,e))(e)},V=function(n){return p.isAbsolute(n)?n.replace(m.default.getApplicationPath()+p.sep,""):n},x=function(n){try{var e=p.join(m.default.getBuildPath(),n+o.INSTRUMENTED_FILE_EXTENSION);r.default.checkIfFileExistsSync(e),r.default.deleteFileSync(e)}catch(n){}},N=function(n,e){e=p.join(m.default.getBuildPath(),e);try{r.default.checkIfFileExistsSync(p.dirname(e))}catch(n){r.default.createDirectorySync(p.dirname(e))}r.default.writeTextToFileSync(e+o.INSTRUMENTED_FILE_EXTENSION,n)},J=function(n,e){var r={input:!1,lifecycle:!1};return void 0!==e&&(void 0!==e.lifecycle&&void 0!==e.lifecycle.instrument&&e.lifecycle.instrument(n)&&(r.lifecycle=!0),void 0!==e.input)&&void 0!==e.input.instrument&&e.input.instrument(n)&&(r.input=!0),r},G=function(n){var e,n=n.find(u.Program);1===n.length&&(e=u.expressionStatement(u.callExpression(u.memberExpression(u.callExpression(u.identifier("require"),[u.stringLiteral("@dynatrace/react-native-plugin/instrumentation/jsx/ElementHelper")]),u.identifier("instrumentCreateElement")),[u.memberExpression(u.identifier("module"),u.identifier("exports"))])),n.paths()[0].node.body.push(e))},$=function(n){var e=n.find(u.FunctionDeclaration,{id:{name:"runApplication"}});return 1===e.length&&(D(n,{g:"_DynatraceApplicationHandler",module:"@dynatrace/react-native-plugin",reference:"ApplicationHandler"}),R(e.get().value.body.body,0,w("_DynatraceApplicationHandler","startup",[])),!0)},z=function(n){var e=n.find(u.ObjectMethod,{key:{name:"runApplication"}});return 1===e.length&&(D(n,{g:"_DynatraceApplicationHandler",module:"@dynatrace/react-native-plugin",reference:"ApplicationHandler"}),R(e.get().value.body.body,0,w("_DynatraceApplicationHandler","startup",[])),!0)},K=function(n,r,t){var i=u;n.find(i.FunctionDeclaration,{id:{name:"handleException"}}).forEach(function(n){var e=i.callExpression(i.memberExpression(i.callExpression(i.identifier("require"),[i.literal("@dynatrace/react-native-plugin/lib/core/ErrorHandler")]),i.identifier("reportErrorToDynatrace")),[i.identifier("e"),i.identifier("isFatal"),i.literal(r),i.literal(t)]),e=i.expressionStatement(i.callExpression(i.identifier("setTimeout"),[i.arrowFunctionExpression([],i.blockStatement(n.node.body.body)),e]));n.node.body.body=[e]})},Q=function(n){var e=!1,n=n.find(u.CallExpression,{callee:{name:"require"}});return n.find(u.Literal,{value:"react/jsx-runtime"}).replaceWith(function(n){n=n.node;return n.value="@dynatrace/react-native-plugin/jsx-runtime",e=!0,n}),n.find(u.Literal,{value:"react/jsx-dev-runtime"}).replaceWith(function(n){n=n.node;return n.value="@dynatrace/react-native-plugin/jsx-dev-runtime",e=!0,n}),e},R=function(n,e){for(var r=arguments.length,t=new Array(2<r?r-2:0),i=2;i<r;i++)t[i-2]=arguments[i];return n.splice.apply(n,[e,0].concat(t))},W=function(n){if(n.includes("@dynatrace"))return d.i;var e=p.extname(n);if(".js"!==e&&".ts"!==e&&".tsx"!==e&&".jsx"!==e)return d.i;for(var r=p.parse(n),t=r.dir.split(p.sep),i=0;i<t.length;i++)if("node_modules"===t[i]){if("react-native"===t[i+1]||"create-react-class"===t[i+1]||"react-clone-referenced-element"===t[i+1])return L.has(r.name)?d.o:d.i;if("react"===t[i+1]&&"index"===r.name)return d.l;if("react-native-css-interop"===t[i+1]&&("jsx-runtime"===r.name||"jsx-dev-runtime"===r.name))return d.v}return d.u},X=function(n,e,r){var t=Y(n,e,r);return Z(n,e,r)||t},Y=function(n,e,r){var t=en(n,e);return 0<t.length&&(void 0!==(t=C(t,e.reference,!1))&&(r.g=t.localName),cn(n,r),!0)},Z=function(n,e,r){var t=E(n,e.module);if(1===t.length){t=C(t,e.reference,!0);if(void 0!==t)return ln(n,r.defaultImport,t.localName,"ImportNamespaceSpecifier"===t.type),!0}return!1},nn=function(n,e){var r=JSON.parse(JSON.stringify(e.new));return{root:n,m:X(n,e.old,r)||rn(n,e.old,e.new.defaultImport)}},en=function(n,e){return n.find(u.ImportDeclaration).filter(function(n){return n.node.source.value===e.module&&null!=n.node.specifiers&&n.node.specifiers.some(function(n){return S(n)&&n.imported.name===e.reference||n.local&&n.local.name===e.reference})})},S=function(n){return void 0!==n.imported},rn=function(n,e,r){var t=!1;return n.find(u.CallExpression).filter(function(n){return tn(n.node.callee)&&un(n.node.arguments[0])&&n.node.arguments[0].value===e.module&&void 0!==n.parent}).forEach(function(n){(void 0===n.parent.value.property||void 0!==n.parent.value.property&&void 0!==n.parent.value.property.name&&n.parent.value.property.name===e.reference)&&(n.node.arguments[0].value=r,t=t||!0)}),t},tn=function(n){return"require"===n.name},un=function(n){return"StringLiteral"===n.type||"Literal"===n.type},E=function(n,e){return n.find(u.ImportDeclaration).filter(function(n){return n.node.source.value===e})},C=function(n,r,t){var i;return n.forEach(function(n){void 0!==n.node.specifiers&&(n.node.specifiers=n.node.specifiers.filter(function(n){var e;return S(n)&&!t?((e=n.imported.name!==r)||null==n.local||n.imported.name===n.local.name||(i={localName:n.local.name.toString(),type:n.type}),e):!(!S(n)&&t&&(null!=n.local&&(i={localName:n.local.name.toString(),type:n.type}),1))}),0===n.node.specifiers.length)&&n.prune()}),i},on=function(n,e){n.find(u.ImportDeclaration).filter(function(n){return n.node.source.value===e.module}).forEach(function(n){null!=n.node.specifiers&&n.node.specifiers.push(B(e))})},an=function(n,e,r){n.find(u.ImportDeclaration).filter(function(n){return n.node.source.value===e}).forEach(function(n){null!=n.node.specifiers&&n.node.specifiers.push(r)})},H=function(n,e,r){var t=n.find(u.ImportDeclaration);0<t.length?u(t.paths()[0]).insertAfter(_(e,r)):1===(t=n.find(u.Program)).length&&t.paths()[0].node.body.unshift(_(e,r))},cn=function(n,e){0<E(n,e.module).length?on(n,e):H(n,e.module,[B(e)])},ln=function(n,e,r,t){var i=E(n,e),t=(t?yn:mn)(r);0<i.length?an(n,e,t):H(n,e,[t])},D=function(n,e){n=n.find(u.VariableDeclaration);0<n.length&&u(n.paths()[0]).insertAfter(sn(e))},w=function(n,e,r){return u.expressionStatement(fn(n,e,r))},fn=function(n,e,r){return u.callExpression(pn(n,e),r)},sn=function(n){return u.variableDeclaration("var",[vn(n)])},vn=function(n){return u.variableDeclarator(void 0!==n.g?u.identifier(n.g):u.identifier(n.reference),(0<n.reference.length?dn:F)(n))},dn=function(n){return u.memberExpression(F(n),u.identifier(n.reference))},pn=function(n,e){return u.memberExpression(u.identifier(n),u.identifier(e))},F=function(n){return u.callExpression(u.identifier("require"),[u.literal(n.module)])},_=function(n,e){return u.importDeclaration(e,u.literal(n))},B=function(n){return void 0!==n.g?u.importSpecifier(u.identifier(n.reference),u.identifier(n.g)):u.importSpecifier(u.identifier(n.reference))},mn=function(n){return u.importDefaultSpecifier(u.identifier(n))},yn=function(n){return u.importNamespaceSpecifier(u.identifier(n))};
|
|
@@ -1,29 +1,129 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createElement = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
4
5
|
const Types_1 = require("../model/Types");
|
|
5
6
|
const ElementHelper_1 = require("./ElementHelper");
|
|
6
7
|
const ClassComponent_1 = require("./components/ClassComponent");
|
|
7
8
|
const FunctionalComponent_1 = require("./components/FunctionalComponent");
|
|
8
|
-
const
|
|
9
|
+
const PRESS_PROP_KEYS = [
|
|
10
|
+
'onPress',
|
|
11
|
+
'onLongPress',
|
|
12
|
+
'onPressIn',
|
|
13
|
+
'onPressOut',
|
|
14
|
+
'onTap',
|
|
15
|
+
'onClick',
|
|
16
|
+
];
|
|
17
|
+
const getGlobalPressHook = () => {
|
|
18
|
+
const g = (typeof globalThis !== 'undefined' && globalThis) ||
|
|
19
|
+
(typeof global !== 'undefined' && global) ||
|
|
20
|
+
(typeof window !== 'undefined' && window) ||
|
|
21
|
+
undefined;
|
|
22
|
+
return g === null || g === void 0 ? void 0 : g.__DT_UI_PLUGIN_PRESS_HOOK__;
|
|
23
|
+
};
|
|
24
|
+
const getDisplayName = (type) => {
|
|
25
|
+
if (!type) {
|
|
26
|
+
return 'Unknown';
|
|
27
|
+
}
|
|
28
|
+
if (typeof type === 'string') {
|
|
29
|
+
return type;
|
|
30
|
+
}
|
|
31
|
+
return (type.displayName ||
|
|
32
|
+
type.name ||
|
|
33
|
+
(type.constructor && type.constructor.name) ||
|
|
34
|
+
'Anonymous');
|
|
35
|
+
};
|
|
36
|
+
const guessTouchableName = (type, props) => {
|
|
37
|
+
if (!props) {
|
|
38
|
+
return getDisplayName(type);
|
|
39
|
+
}
|
|
40
|
+
if (typeof props.dtActionName === 'string' && props.dtActionName.length) {
|
|
41
|
+
return props.dtActionName;
|
|
42
|
+
}
|
|
43
|
+
if (typeof props.title === 'string' && props.title.length) {
|
|
44
|
+
return props.title;
|
|
45
|
+
}
|
|
46
|
+
if (typeof props.accessibilityLabel === 'string' &&
|
|
47
|
+
props.accessibilityLabel.length) {
|
|
48
|
+
return props.accessibilityLabel;
|
|
49
|
+
}
|
|
50
|
+
if (typeof props.testID === 'string' && props.testID.length) {
|
|
51
|
+
return props.testID;
|
|
52
|
+
}
|
|
53
|
+
return getDisplayName(type);
|
|
54
|
+
};
|
|
55
|
+
const mapHandlerToPhase = (handler) => {
|
|
56
|
+
if (handler === 'onPressIn') {
|
|
57
|
+
return 'press-in';
|
|
58
|
+
}
|
|
59
|
+
if (handler === 'onPressOut') {
|
|
60
|
+
return 'press-out';
|
|
61
|
+
}
|
|
62
|
+
return 'press';
|
|
63
|
+
};
|
|
64
|
+
const attachPressHookToProps = (type, props) => {
|
|
65
|
+
if (!props) {
|
|
66
|
+
return props;
|
|
67
|
+
}
|
|
68
|
+
const hook = getGlobalPressHook();
|
|
69
|
+
if (!hook) {
|
|
70
|
+
return props;
|
|
71
|
+
}
|
|
72
|
+
let cloned = null;
|
|
73
|
+
const wrapOne = (key) => {
|
|
74
|
+
const orig = props[key];
|
|
75
|
+
if (typeof orig !== 'function') {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (!cloned) {
|
|
79
|
+
cloned = Object.assign({}, props);
|
|
80
|
+
}
|
|
81
|
+
cloned[key] = (...args) => {
|
|
82
|
+
var _a;
|
|
83
|
+
try {
|
|
84
|
+
const evt = args[0];
|
|
85
|
+
const nativeEvent = (_a = evt === null || evt === void 0 ? void 0 : evt.nativeEvent) !== null && _a !== void 0 ? _a : evt;
|
|
86
|
+
const touchableName = guessTouchableName(type, props);
|
|
87
|
+
hook({
|
|
88
|
+
phase: mapHandlerToPhase(key),
|
|
89
|
+
handler: key,
|
|
90
|
+
touchableName,
|
|
91
|
+
nativeEvent,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
const errorMsg = e instanceof Error ? e.stack || e.message : String(e);
|
|
96
|
+
console.log(`[CreateElement]: DT press hook failed: ${errorMsg}`);
|
|
97
|
+
}
|
|
98
|
+
return orig(...args);
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
for (const key of PRESS_PROP_KEYS) {
|
|
102
|
+
wrapOne(key);
|
|
103
|
+
}
|
|
104
|
+
return cloned || props;
|
|
105
|
+
};
|
|
9
106
|
const createElement = (type, props, ...children) => {
|
|
10
|
-
|
|
107
|
+
const patchedProps = attachPressHookToProps(type, props);
|
|
108
|
+
if (type != null &&
|
|
109
|
+
type._dtInfo != null &&
|
|
110
|
+
!(0, ElementHelper_1.isDtActionIgnore)(patchedProps)) {
|
|
11
111
|
if (type._dtInfo.type === Types_1.Types.FunctionalComponent) {
|
|
12
112
|
return (0, react_1.createElement)(FunctionalComponent_1.DynatraceFunctionalComponent, {
|
|
13
|
-
children: (0, react_1.createElement)(type,
|
|
113
|
+
children: (0, react_1.createElement)(type, patchedProps, ...children),
|
|
14
114
|
});
|
|
15
115
|
}
|
|
16
116
|
else if (type._dtInfo.type === Types_1.Types.ClassComponent &&
|
|
17
117
|
type.prototype !== undefined &&
|
|
18
118
|
type.prototype.isReactComponent !== undefined) {
|
|
19
119
|
return (0, react_1.createElement)(ClassComponent_1.DynatraceClassComponent, {
|
|
20
|
-
children: (0, react_1.createElement)(type,
|
|
120
|
+
children: (0, react_1.createElement)(type, patchedProps, ...children),
|
|
21
121
|
});
|
|
22
122
|
}
|
|
23
123
|
else {
|
|
24
|
-
(0, ElementHelper_1.modifyElement)(type,
|
|
124
|
+
(0, ElementHelper_1.modifyElement)(type, patchedProps);
|
|
25
125
|
}
|
|
26
126
|
}
|
|
27
|
-
return (0, react_1.createElement)(type,
|
|
127
|
+
return (0, react_1.createElement)(type, patchedProps, ...children);
|
|
28
128
|
};
|
|
29
129
|
exports.createElement = createElement;
|
|
@@ -11,9 +11,7 @@ try {
|
|
|
11
11
|
args[0]._dtInfo !== undefined &&
|
|
12
12
|
!(0, ElementHelper_1.isDtActionIgnore)(args[1])) {
|
|
13
13
|
if (args[0]._dtInfo.type === Types_1.Types.FunctionalComponent) {
|
|
14
|
-
const wrapperProps = {
|
|
15
|
-
children: ReactDevRuntime.jsxDEV(...args),
|
|
16
|
-
};
|
|
14
|
+
const wrapperProps = Object.assign(Object.assign({}, args[1]), { children: ReactDevRuntime.jsxDEV(...args) });
|
|
17
15
|
wrapperProps.dtActionName =
|
|
18
16
|
args[1] !== undefined && args[1].dtActionName !== undefined
|
|
19
17
|
? args[1].dtActionName
|
|
@@ -28,9 +26,7 @@ try {
|
|
|
28
26
|
else if (args[0]._dtInfo.type === Types_1.Types.ClassComponent &&
|
|
29
27
|
args[0].prototype !== undefined &&
|
|
30
28
|
args[0].prototype.isReactComponent !== undefined) {
|
|
31
|
-
const wrapperProps = {
|
|
32
|
-
children: ReactDevRuntime.jsxDEV(...args),
|
|
33
|
-
};
|
|
29
|
+
const wrapperProps = Object.assign(Object.assign({}, args[1]), { children: ReactDevRuntime.jsxDEV(...args) });
|
|
34
30
|
if (args[2] !== undefined) {
|
|
35
31
|
return ReactDevRuntime.jsxDEV(ClassComponent_1.DynatraceClassComponent, wrapperProps, args[2] + '_dt');
|
|
36
32
|
}
|
|
@@ -10,9 +10,7 @@ const instrumentJsxCall = (jsxFunction) => (...args) => {
|
|
|
10
10
|
args[0]._dtInfo !== undefined &&
|
|
11
11
|
!(0, ElementHelper_1.isDtActionIgnore)(args[1])) {
|
|
12
12
|
if (args[0]._dtInfo.type === Types_1.Types.FunctionalComponent) {
|
|
13
|
-
const wrapperProps = {
|
|
14
|
-
children: jsxFunction(...args),
|
|
15
|
-
};
|
|
13
|
+
const wrapperProps = Object.assign(Object.assign({}, args[1]), { children: jsxFunction(...args) });
|
|
16
14
|
wrapperProps.dtActionName =
|
|
17
15
|
args[1] !== undefined && args[1].dtActionName !== undefined
|
|
18
16
|
? args[1].dtActionName
|
|
@@ -27,9 +25,7 @@ const instrumentJsxCall = (jsxFunction) => (...args) => {
|
|
|
27
25
|
else if (args[0]._dtInfo.type === Types_1.Types.ClassComponent &&
|
|
28
26
|
args[0].prototype !== undefined &&
|
|
29
27
|
args[0].prototype.isReactComponent !== undefined) {
|
|
30
|
-
const wrapperProps = {
|
|
31
|
-
children: jsxFunction(...args),
|
|
32
|
-
};
|
|
28
|
+
const wrapperProps = Object.assign(Object.assign({}, args[1]), { children: jsxFunction(...args) });
|
|
33
29
|
if (args[2] !== undefined) {
|
|
34
30
|
return jsxFunction(ClassComponent_1.DynatraceClassComponent, wrapperProps, args[2] + '_dt');
|
|
35
31
|
}
|
|
@@ -13,20 +13,66 @@ function withOnPressMonitoring(Component, fallbackName) {
|
|
|
13
13
|
const { onPress, onLongPress } = props;
|
|
14
14
|
const touchableName = (0, exports.chooseTouchableName)(props, fallbackName);
|
|
15
15
|
const dynatraceIgnored = (0, ComponentUtil_1.isDynatraceIgnored)(props);
|
|
16
|
+
const isRNButton = 'title' in props && typeof props.title === 'string';
|
|
17
|
+
const isRectButton = fallbackName === 'Button';
|
|
18
|
+
const isButtonLike = isRNButton || isRectButton;
|
|
19
|
+
const buttonLabel = isRNButton ? String(props.title) : null;
|
|
16
20
|
const propsWithoutRef = Object.assign(Object.assign(Object.assign({}, props), (!dynatraceIgnored &&
|
|
17
21
|
onPress && {
|
|
18
|
-
onPress: (0, exports.wrapOnPress)(onPress, touchableName),
|
|
22
|
+
onPress: (0, exports.wrapOnPress)(onPress, touchableName, isButtonLike, buttonLabel),
|
|
19
23
|
})), (!dynatraceIgnored &&
|
|
20
24
|
onLongPress && {
|
|
21
|
-
onLongPress: (0, exports.wrapOnPress)(onLongPress, touchableName),
|
|
25
|
+
onLongPress: (0, exports.wrapOnPress)(onLongPress, touchableName, isButtonLike, buttonLabel),
|
|
22
26
|
}));
|
|
23
27
|
const propsWithRef = Object.assign(Object.assign({}, propsWithoutRef), { ref });
|
|
24
28
|
return React.createElement(Component, Object.assign({}, propsWithRef));
|
|
25
29
|
});
|
|
26
30
|
}
|
|
27
31
|
exports.withOnPressMonitoring = withOnPressMonitoring;
|
|
28
|
-
const
|
|
32
|
+
const dtGetUiBridge = () => {
|
|
33
|
+
const g = globalThis;
|
|
34
|
+
return g && g.__DT_UII_BRIDGE ? g.__DT_UII_BRIDGE : null;
|
|
35
|
+
};
|
|
36
|
+
const dtBuildPressPath = (startPath, touchableName) => {
|
|
37
|
+
const base = (startPath && String(startPath)) || '';
|
|
38
|
+
if (!base)
|
|
39
|
+
return `Touchable(${touchableName})`;
|
|
40
|
+
const cut1 = base.lastIndexOf('/Text');
|
|
41
|
+
const cut2 = base.lastIndexOf('/Text(');
|
|
42
|
+
const cut = Math.max(cut1, cut2);
|
|
43
|
+
const parent = cut > 0 ? base.slice(0, cut) : base;
|
|
44
|
+
return parent + `/Touchable(${touchableName})`;
|
|
45
|
+
};
|
|
46
|
+
const wrapOnPress = (onPress, touchableName, isButtonLike, buttonLabel) => {
|
|
29
47
|
return (...args) => {
|
|
48
|
+
const bridge = dtGetUiBridge();
|
|
49
|
+
if (bridge && typeof bridge.registerPress === 'function') {
|
|
50
|
+
try {
|
|
51
|
+
const e = args && args[0];
|
|
52
|
+
const ne = e && e.nativeEvent;
|
|
53
|
+
const x = Number(ne && ne.pageX);
|
|
54
|
+
const y = Number(ne && ne.pageY);
|
|
55
|
+
const pos = Number.isFinite(x) && Number.isFinite(y)
|
|
56
|
+
? { x, y }
|
|
57
|
+
: undefined;
|
|
58
|
+
const startPath = bridge.getStartPath &&
|
|
59
|
+
typeof bridge.getStartPath === 'function'
|
|
60
|
+
? bridge.getStartPath()
|
|
61
|
+
: null;
|
|
62
|
+
const nameForBridge = isButtonLike
|
|
63
|
+
? buttonLabel || touchableName
|
|
64
|
+
: touchableName;
|
|
65
|
+
bridge.registerPress({
|
|
66
|
+
path: dtBuildPressPath(startPath, nameForBridge),
|
|
67
|
+
elementName: nameForBridge,
|
|
68
|
+
pos,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
const errorMsg = e instanceof Error ? e.stack || e.message : String(e);
|
|
73
|
+
Logger.debug(`registerPress bridge hook failed: ${errorMsg}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
30
76
|
if (!ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) {
|
|
31
77
|
Logger.info('React Native plugin has not been started yet! Touch will not be reported!');
|
|
32
78
|
onPress(...args);
|
package/ios/DynatraceRNBridge.mm
CHANGED
|
@@ -279,6 +279,7 @@ template<typename T = void> std::enable_if_t<(facebook::react::ReactNativeVersio
|
|
|
279
279
|
/**
|
|
280
280
|
* Triggered when starting to emit events
|
|
281
281
|
*/
|
|
282
|
+
|
|
282
283
|
- (void)startObserving
|
|
283
284
|
{
|
|
284
285
|
hasListeners = YES;
|
|
@@ -720,7 +721,7 @@ RCT_EXPORT_METHOD(getUserPrivacyOptions:(NSString *) platform findEventsWithReso
|
|
|
720
721
|
level = DataCollectionOff;
|
|
721
722
|
}
|
|
722
723
|
|
|
723
|
-
NSDictionary *privacyDict = @{@"dataCollectionLevel": level, @"crashReportingOptedIn": [NSNumber numberWithBool: privacyConfig.crashReportingOptedIn]};
|
|
724
|
+
NSDictionary *privacyDict = @{@"dataCollectionLevel": level, @"crashReportingOptedIn": [NSNumber numberWithBool: privacyConfig.crashReportingOptedIn], @"screenRecordOptedIn": [NSNumber numberWithBool: privacyConfig.screenRecordOptedIn]};
|
|
724
725
|
|
|
725
726
|
resolve(privacyDict);
|
|
726
727
|
}
|
|
@@ -750,6 +751,12 @@ RCT_EXPORT_METHOD(applyUserPrivacyOptions:(NSDictionary *) userPrivacyOptions pl
|
|
|
750
751
|
// do nothing and keep current value
|
|
751
752
|
}
|
|
752
753
|
|
|
754
|
+
if ([[userPrivacyOptions valueForKey:@"_screenRecordOptedIn"] isEqual: @(YES)]) {
|
|
755
|
+
privacyConfig.screenRecordOptedIn = @(YES);
|
|
756
|
+
} else if ([[userPrivacyOptions valueForKey:@"_screenRecordOptedIn"] isEqual: @(NO)]) {
|
|
757
|
+
privacyConfig.screenRecordOptedIn = @(NO);
|
|
758
|
+
}
|
|
759
|
+
|
|
753
760
|
[Dynatrace applyUserPrivacyOptions:privacyConfig completion:^(BOOL successful) {
|
|
754
761
|
// do nothing with callback
|
|
755
762
|
}];
|
package/lib/core/Application.js
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ApplicationHandler = void 0;
|
|
4
4
|
const AppStartObserver_1 = require("../next/appstart/AppStartObserver");
|
|
5
|
+
const RuntimeConfigurationObserver_1 = require("../next/configuration/RuntimeConfigurationObserver");
|
|
5
6
|
const ConfigurationBuilder_1 = require("./configuration/ConfigurationBuilder");
|
|
6
7
|
const ConfigurationHandler_1 = require("./configuration/ConfigurationHandler");
|
|
7
8
|
const ConsoleLogger_1 = require("./logging/ConsoleLogger");
|
|
8
9
|
AppStartObserver_1.AppStartObserver.call();
|
|
10
|
+
RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.call();
|
|
9
11
|
const logger = new ConsoleLogger_1.ConsoleLogger('ApplicationHandler');
|
|
10
12
|
exports.ApplicationHandler = {
|
|
11
13
|
startup: (configuration) => {
|
package/lib/core/Dynatrace.js
CHANGED
|
@@ -287,10 +287,11 @@ exports.Dynatrace = {
|
|
|
287
287
|
}
|
|
288
288
|
},
|
|
289
289
|
getUserPrivacyOptions: (platform) => __awaiter(void 0, void 0, void 0, function* () {
|
|
290
|
+
var _a;
|
|
290
291
|
if (ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) {
|
|
291
292
|
logger.debug('getUserPrivacyOptions()');
|
|
292
293
|
const options = yield DynatraceBridge_1.DynatraceNative.getUserPrivacyOptions(platform === null || platform === void 0 ? void 0 : platform.toString());
|
|
293
|
-
const currentOptions = new UserPrivacyOptions_1.UserPrivacyOptions((0, DataCollectionLevel_1.StringToDataCollectionLevel)(options.dataCollectionLevel), options.crashReportingOptedIn);
|
|
294
|
+
const currentOptions = new UserPrivacyOptions_1.UserPrivacyOptions((0, DataCollectionLevel_1.StringToDataCollectionLevel)(options.dataCollectionLevel), options.crashReportingOptedIn, (_a = options.screenRecordOptedIn) !== null && _a !== void 0 ? _a : false);
|
|
294
295
|
return currentOptions;
|
|
295
296
|
}
|
|
296
297
|
else {
|