@dynatrace/react-native-plugin 2.329.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 +102 -8
- 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 +35 -0
- package/lib/next/DynatraceArgValidators.js +10 -0
- 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/lib/next/events/HttpRequestEventData.js +22 -20
- package/lib/next/events/modifier/ModifyEventValidation.js +2 -4
- package/lib/next/events/spec/EventSpecContstants.js +2 -2
- package/package.json +21 -11
- 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 +46 -32
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 {
|
|
@@ -766,7 +770,7 @@ This example shows two *TouchableHighlight*, which will fire the *onPress()* fun
|
|
|
766
770
|
|
|
767
771
|
The New RUM Experience introduces a set of advanced APIs that allow you to send custom events, modify event data, track exceptions, monitor HTTP requests, and manage view contexts in your React Native application. These APIs provide more granular control over the data captured by Dynatrace and are designed for the next generation RUM capabilities.
|
|
768
772
|
|
|
769
|
-
For more detailed information about the New RUM Experience, see the [official Dynatrace documentation](https://docs.dynatrace.com/docs/
|
|
773
|
+
For more detailed information about the New RUM Experience, see the [official Dynatrace documentation](https://docs.dynatrace.com/docs/shortlink/react-native-main).
|
|
770
774
|
|
|
771
775
|
### Send Event
|
|
772
776
|
|
|
@@ -875,6 +879,7 @@ Dynatrace.removeEventModifier(myModifier);
|
|
|
875
879
|
- **Reserved fields**: Certain reserved fields and namespaces cannot be modified. Attempts to modify them will be ignored
|
|
876
880
|
- **Error handling**: If a modifier throws an exception, it will be logged but won't prevent other modifiers from executing
|
|
877
881
|
- **Primitive values**: Event fields can only contain primitive values (String, int, double, bool)
|
|
882
|
+
- **Invalid argument**: In case you pass an invalid argument to `addEventModifier`, we return a no-op placeholder modifier.
|
|
878
883
|
|
|
879
884
|
### Send Exception Event
|
|
880
885
|
|
|
@@ -1011,6 +1016,42 @@ Dynatrace.sendEvent(new EventData()
|
|
|
1011
1016
|
Dynatrace.startView("UserProfileDetailed");
|
|
1012
1017
|
```
|
|
1013
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
|
+
|
|
1014
1055
|
### React Native Symbolication
|
|
1015
1056
|
|
|
1016
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.
|
|
@@ -1228,6 +1269,7 @@ The `react` configuration block contains all settings regarding the react instru
|
|
|
1228
1269
|
|
|
1229
1270
|
```js
|
|
1230
1271
|
react : {
|
|
1272
|
+
|
|
1231
1273
|
input : {
|
|
1232
1274
|
instrument(filename) => {
|
|
1233
1275
|
return true;
|
|
@@ -1268,6 +1310,47 @@ react: {
|
|
|
1268
1310
|
|
|
1269
1311
|
This activates the debug mode. You will get more console output during instrumentation and at runtime.
|
|
1270
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
|
+
|
|
1271
1354
|
#### Error Handler
|
|
1272
1355
|
|
|
1273
1356
|
```js
|
|
@@ -1528,7 +1611,7 @@ ios: {
|
|
|
1528
1611
|
## How does Dynatrace determine the user action name?
|
|
1529
1612
|
* React views
|
|
1530
1613
|
* dtActionName: Use a custom property called dtActionName
|
|
1531
|
-
* displayName: Use the displayName property to check if React views have a display name set
|
|
1614
|
+
* displayName: Use the displayName property to check if React views have a display name set
|
|
1532
1615
|
* instrumentation string: Auto instrumentation or manual instrumentation is passing a string. This will be used if available.
|
|
1533
1616
|
* class name: If the display name is not available, the class name is used by taking the property name from the constructor
|
|
1534
1617
|
* Touchables
|
|
@@ -1824,7 +1907,7 @@ In summary, ensure your build fulfills our Kotlin 2.0.21 requirement while simul
|
|
|
1824
1907
|
|
|
1825
1908
|
## Compose Compatibility Note
|
|
1826
1909
|
|
|
1827
|
-
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:
|
|
1828
1911
|
|
|
1829
1912
|
```
|
|
1830
1913
|
Could not resolve all dependencies for configuration ':app:debugCompileClasspath'.
|
|
@@ -1971,6 +2054,17 @@ If you are struggling with a problem, submit a support ticket to Dynatrace (supp
|
|
|
1971
2054
|
<br/><br/>
|
|
1972
2055
|
## Changelog
|
|
1973
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
|
+
|
|
2065
|
+
2.331.1
|
|
2066
|
+
* Updated Android (8.331.1.1004) & iOS Agent (8.331.1.1008)
|
|
2067
|
+
|
|
1974
2068
|
2.329.1
|
|
1975
2069
|
* Updated Android (8.329.1.1014) & iOS Agent (8.329.1.1017)
|
|
1976
2070
|
* [New RUM experience](#new-rum-experience) Removed Dynatrace.stopView() API
|
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)})),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
|
}];
|