@dynatrace/react-native-plugin 2.335.1 → 2.337.2
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 +145 -61
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +1 -1
- package/files/plugin.gradle +1 -1
- package/instrumentation/BabelPluginDynatrace.js +1 -1
- package/instrumentation/DynatraceInstrumentation.js +1 -1
- package/instrumentation/libs/community/Picker.js +1 -1
- package/instrumentation/libs/react-navigation/ReactNavigation.js +9 -0
- package/instrumentation/libs/withOnPressMonitoring.js +59 -14
- package/lib/core/Dynatrace.js +3 -0
- package/lib/core/DynatraceBridge.js +5 -7
- package/lib/core/configuration/ActionNameOptions.js +2 -0
- package/lib/core/configuration/Configuration.js +5 -1
- package/lib/core/configuration/ConfigurationBuilder.js +11 -1
- package/lib/core/configuration/ConfigurationDefaults.js +3 -1
- package/lib/core/configuration/ConfigurationHandler.js +64 -0
- package/lib/core/configuration/ConfigurationPreset.js +6 -0
- package/lib/core/configuration/ManualStartupConfiguration.js +9 -1
- package/lib/features/ui-interaction/Runtime.js +31 -19
- package/lib/next/Dynatrace.js +44 -0
- package/lib/next/configuration/INativeRuntimeConfiguration.js +9 -0
- package/lib/next/configuration/RuntimeConfigurationObserver.js +50 -6
- package/lib/next/events/EventPipeline.js +14 -6
- package/lib/next/events/HttpRequestEventData.js +26 -30
- package/lib/next/provider/TimestampProvider.js +20 -7
- package/lib/next/util/TraceContextUtils.js +108 -0
- package/package.json +4 -3
- package/react-native-dynatrace.podspec +1 -1
- package/scripts/Android.js +27 -10
- package/scripts/Config.js +1 -1
- package/scripts/Ios.js +288 -71
- package/scripts/PathsConstants.js +34 -20
- package/scripts/core/InstrumentCall.js +7 -1
- package/scripts/util/SourceMapUtil.js +49 -11
- package/types.d.ts +178 -39
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ If you want to start using this plugin and are not a Dynatrace customer yet, hea
|
|
|
10
10
|
* Web requests
|
|
11
11
|
* Crashes
|
|
12
12
|
* React-native Auto-instrumentation
|
|
13
|
-
* User actions for onPress and onLongPress (Touchables, Buttons,
|
|
13
|
+
* User actions for onPress and onLongPress (Touchables, Buttons, Pressable, Switch, RefreshControl, Picker)
|
|
14
14
|
* User actions for class and functional components (lifecycle events such as render(), didMount() and didUpdate())
|
|
15
15
|
* Reporting React Native errors
|
|
16
16
|
* Tracking navigation via `react.navigation.enabled`
|
|
@@ -35,8 +35,8 @@ If you want to start using this plugin and are not a Dynatrace customer yet, hea
|
|
|
35
35
|
## Agent Versions
|
|
36
36
|
These agent versions are configured in this plugin:
|
|
37
37
|
|
|
38
|
-
* Android Agent: 8.
|
|
39
|
-
* iOS Agent: 8.
|
|
38
|
+
* Android Agent: 8.337.3.1013
|
|
39
|
+
* iOS Agent: 8.337.1.1003
|
|
40
40
|
|
|
41
41
|
## Quick Setup
|
|
42
42
|
|
|
@@ -73,7 +73,6 @@ These agent versions are configured in this plugin:
|
|
|
73
73
|
* [Send Exception Event](#send-exception-event)
|
|
74
74
|
* [Send HTTP Request Event](#send-http-request-event)
|
|
75
75
|
* [View Monitoring](#view-monitoring)
|
|
76
|
-
* [User Interaction](#user-interaction-1)
|
|
77
76
|
* [React Native Symbolication](#react-native-symbolication)
|
|
78
77
|
* [NPX Commands](#npx-commands)
|
|
79
78
|
* [npx instrumentDynatrace](#npx-instrumentdynatrace)
|
|
@@ -93,7 +92,7 @@ These agent versions are configured in this plugin:
|
|
|
93
92
|
* [Bundle Name and Version](#bundle-name-and-version)
|
|
94
93
|
* [Navigation](#navigation)
|
|
95
94
|
* [Source Map](#source-map)
|
|
96
|
-
* [User Interaction](#user-interaction-
|
|
95
|
+
* [User Interaction Configuration](#user-interaction-configuration)
|
|
97
96
|
* [Debugging our auto-instrumentation](#debugging-our-auto-instrumentation)
|
|
98
97
|
* [Using our legacy jscodeshift auto-instrumentation](#using-our-legacy-jscodeshift-auto-instrumentation)
|
|
99
98
|
* [Android block](#android-block)
|
|
@@ -159,7 +158,9 @@ module.exports = {
|
|
|
159
158
|
|
|
160
159
|
This plugin handles the auto-instrumentation of your React Native code at build time.
|
|
161
160
|
|
|
162
|
-
> **Note**: We recently moved our auto-instrumentation from a custom
|
|
161
|
+
> **Note**: We recently moved our auto-instrumentation from a custom Metro transformer to a babel plugin for much faster bundling, independence of Metro and correct sourcemaps. The code shown above is the new and recommended way to add our auto-instrumentation to your project by adding the babel plugin directly. However, our plugin is backwards compatible in a sense that we keep supporting auto-instrumentation via the Dynatrace Metro transformer and reporter. In short, no configuration change is needed. If you continue using the Dynatrace Metro transformer and reporter, we reroute the instrumentation logic to the babel plugin internally.
|
|
162
|
+
|
|
163
|
+
> **Note**: Bypassing Metro by adding the Babel plugin directly allows for the use of alternative bundlers. However, please be aware that we only regularly test with the default Metro bundler; other bundlers are not explicitly supported or documented.
|
|
163
164
|
|
|
164
165
|
## 4. Register our jsx-runtime in babel.config.js
|
|
165
166
|
|
|
@@ -257,7 +258,9 @@ configurationBuilder.withCrashReporting(true)
|
|
|
257
258
|
.withLogLevel(LogLevel.Info)
|
|
258
259
|
.withLifecycleUpdate(false)
|
|
259
260
|
.withUserOptIn(false)
|
|
260
|
-
.withActionNamePrivacy(false)
|
|
261
|
+
.withActionNamePrivacy(false)
|
|
262
|
+
.withActionNamePreference('any')
|
|
263
|
+
.withActionNameAlgorithm('depth-first');
|
|
261
264
|
|
|
262
265
|
await Dynatrace.start(configurationBuilder.buildConfiguration());
|
|
263
266
|
```
|
|
@@ -274,7 +277,9 @@ await Dynatrace.start(configurationBuilder.buildConfiguration());
|
|
|
274
277
|
|logLevel |LogLevel|LogLevel.Info|Allows you to choose between `LogLevel.Info` and `LogLevel.Debug`. Debug returns more logs. This is especially important when something is not functioning correctly.|
|
|
275
278
|
|lifecycleUpdate |boolean |false |Decide if you want to see update cycles on lifecycle actions as well. This is per default false as it creates a lot more actions.|
|
|
276
279
|
|userOptIn |boolean |false |Activates the privacy mode when set to `true`. User consent must be queried and set. The privacy settings for [data collection](#user-privacy-options) and [crash reporting](#crash-reporting) can be changed via OneAgent SDK for Mobile as described under Data privacy. The default value is `false`.|
|
|
277
|
-
|actionNamePrivacy |boolean |false |Activates a privacy mode especially for
|
|
280
|
+
|actionNamePrivacy |boolean |false |Activates a privacy mode especially for `onPress`. Setting this option to true means that a name for the control will no longer be shown, e.g. "Touch on Button". When setting a dtActionName onto the component this setting will be ignored.
|
|
281
|
+
|actionNamePreference |string |'any' |Controls which type of child element is preferred when searching the component tree for the name of an `onPress` action. `'text'` prefers text and falls back to any match. `'icon'` prefers `ReactNative.Image` and custom Icons and falls back to any match. `'any'` accepts the first match regardless of type (text, image, or custom icon).
|
|
282
|
+
|actionNameAlgorithm |string |'depth-first' |Controls the traversal algorithm used when searching the component tree for the name of an `onPress` action. `'depth-first'` follows the first child branch fully before trying siblings. `'breadth-first'` visits all siblings at a level before going deeper, returning the shallowest match first.|
|
|
278
283
|
|bundleName |string |undefined |Should be used only if you have a multiple bundle setup where you load several .bundle files within your React Native application. Enter the name of your bundle. This should be unique in comparison to your other bundle names. This will ensure that actions coming from different bundles will not interfere with each other.
|
|
279
284
|
|
|
280
285
|
**Attention:**
|
|
@@ -653,7 +658,7 @@ myAction.leaveAction();
|
|
|
653
658
|
|
|
654
659
|
With `sendBizEvent`, you can report business events. These events are standalone events, as OneAgent sends them detached from user actions or user sessions.
|
|
655
660
|
|
|
656
|
-
For more information on business events, see [dynatrace documentation](https://
|
|
661
|
+
For more information on business events, see [dynatrace documentation](https://docs.dynatrace.com/docs/observe/business-observability/explore-business-events).
|
|
657
662
|
|
|
658
663
|
```ts
|
|
659
664
|
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
@@ -974,7 +979,53 @@ Dynatrace.startView("UserProfileDetailed");
|
|
|
974
979
|
|
|
975
980
|
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.
|
|
976
981
|
|
|
977
|
-
|
|
982
|
+
The following is an example of how this feature can be configured in your `dynatrace.config.js` file. Note that this feature is disabled by default.
|
|
983
|
+
|
|
984
|
+
```js
|
|
985
|
+
react: {
|
|
986
|
+
userInteraction: true
|
|
987
|
+
}
|
|
988
|
+
```
|
|
989
|
+
|
|
990
|
+
When enabled, UI Interaction can be controlled by two layers:
|
|
991
|
+
|
|
992
|
+
1. **Build/config layer (`dynatrace.config.js`)**
|
|
993
|
+
- `react.userInteraction: true|false` controls whether the UI Interaction instrumentation feature is applied.
|
|
994
|
+
|
|
995
|
+
2. **Runtime remote layer (`RuntimeConfigurationObserver`)**
|
|
996
|
+
- Runtime emission checks the remote flag `touch_interaction_enabled`.
|
|
997
|
+
- If remote flag is present, it is used as the source of truth.
|
|
998
|
+
- If remote flag is temporarily unavailable, the plugin falls back to the last known good remote value.
|
|
999
|
+
- If no remote value was received yet, runtime defaults to enabled behavior.
|
|
1000
|
+
|
|
1001
|
+
#### Masking sensitive UI labels
|
|
1002
|
+
|
|
1003
|
+
UI Interaction also supports masking sensitive labels before events are sent.
|
|
1004
|
+
|
|
1005
|
+
Masking is applied when:
|
|
1006
|
+
|
|
1007
|
+
* the touched element or one of its parents is marked with `dtMask`
|
|
1008
|
+
* the runtime masking rules classify the detected text as sensitive
|
|
1009
|
+
* the runtime masking rules classify the element `testID` as sensitive
|
|
1010
|
+
|
|
1011
|
+
When masking is active:
|
|
1012
|
+
|
|
1013
|
+
* the interaction path and component information are still reported
|
|
1014
|
+
* the detected UI label is replaced with the configured replacement string (default: `***`)
|
|
1015
|
+
* `ui_element.name_origin` is reported as `masked`
|
|
1016
|
+
|
|
1017
|
+
Example using `dtMask`:
|
|
1018
|
+
|
|
1019
|
+
```tsx
|
|
1020
|
+
<View dtMask>
|
|
1021
|
+
<Pressable onPress={onPress}>
|
|
1022
|
+
<Text>john.doe@example.com</Text>
|
|
1023
|
+
</Pressable>
|
|
1024
|
+
</View>
|
|
1025
|
+
```
|
|
1026
|
+
|
|
1027
|
+
This allows you to preserve interaction analytics while avoiding exposure of sensitive text in the emitted UI Interaction event.
|
|
1028
|
+
|
|
978
1029
|
|
|
979
1030
|
#### Produced data
|
|
980
1031
|
|
|
@@ -988,6 +1039,8 @@ Each captured interaction produces an event describing what the user touched and
|
|
|
988
1039
|
|
|
989
1040
|
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.
|
|
990
1041
|
|
|
1042
|
+
If masking is active for an interaction, the event still contains the same structural information, but the detected name is replaced and the name origin changes to `masked`.
|
|
1043
|
+
|
|
991
1044
|
#### Example event
|
|
992
1045
|
|
|
993
1046
|
```json
|
|
@@ -1047,6 +1100,13 @@ npx instrumentDynatrace [optional: config=... gradle=... plist=...]
|
|
|
1047
1100
|
* `plist=C:\MyReactIOSProject\projectName\info.plist`: Tell the script where your info.plist file is. The plist file is used for updating the configuration for the agent.
|
|
1048
1101
|
* `config=C:\SpecialFolderForDynatrace\dynatrace.config.js`: If you have not got your config file in the root folder of the React Native project but somewhere else.
|
|
1049
1102
|
|
|
1103
|
+
If `plist=...` is not provided, the plugin tries to resolve `Info.plist` automatically in this order:
|
|
1104
|
+
|
|
1105
|
+
1. Resolve app name from Expo config files in the app root (`app.json`, `app.config.js`, `app.config.ts`) and check common iOS plist locations.
|
|
1106
|
+
2. Fallback to scanning the `ios/` folder for `Info.plist`.
|
|
1107
|
+
|
|
1108
|
+
For monorepos or multi-target iOS setups, automatic discovery can be ambiguous. In those cases, pass `plist=...` explicitly to select the exact file.
|
|
1109
|
+
|
|
1050
1110
|
### npx configDynatrace
|
|
1051
1111
|
|
|
1052
1112
|
```
|
|
@@ -1082,6 +1142,32 @@ npx react-native run-android --port=2000
|
|
|
1082
1142
|
|
|
1083
1143
|
> **Note:** that custom arguments must not be prefixed with -- !
|
|
1084
1144
|
|
|
1145
|
+
### pnpm Monorepo Setup
|
|
1146
|
+
|
|
1147
|
+
In a pnpm monorepo where React Native apps share a single native project (e.g. `packages/shared/android` and `packages/shared/ios`), the native platform folders are not located inside each app directory. To use shared native projects, you must provide the paths explicitly via `config=`, `gradle=`, and `plist=` arguments.
|
|
1148
|
+
|
|
1149
|
+
Add a dedicated `instrument` script for each app in the **root** `package.json` of your monorepo:
|
|
1150
|
+
|
|
1151
|
+
```json
|
|
1152
|
+
"scripts": {
|
|
1153
|
+
"instrument:my-app": "pnpm --filter my-app exec instrumentDynatrace config=$PWD/apps/my-app/dynatrace.config.js gradle=$PWD/packages/shared/android/build.gradle plist=$PWD/packages/shared/ios/MyApp/Info.plist",
|
|
1154
|
+
"instrument:another-app": "pnpm --filter another-app exec instrumentDynatrace config=$PWD/apps/another-app/dynatrace.config.js gradle=$PWD/packages/shared/android/build.gradle plist=$PWD/packages/shared/ios/AnotherApp/Info.plist"
|
|
1155
|
+
}
|
|
1156
|
+
```
|
|
1157
|
+
|
|
1158
|
+
Then run the instrumentation for each app from the monorepo root:
|
|
1159
|
+
|
|
1160
|
+
```
|
|
1161
|
+
pnpm instrument:my-app
|
|
1162
|
+
pnpm instrument:another-app
|
|
1163
|
+
```
|
|
1164
|
+
|
|
1165
|
+
**Key points:**
|
|
1166
|
+
* `$PWD` expands to the monorepo root at the time the script runs, so all paths are absolute and unambiguous regardless of the calling directory.
|
|
1167
|
+
* `--filter <app-name>` scopes `pnpm exec` to the correct app workspace so `instrumentDynatrace` is resolved from that app's `node_modules`.
|
|
1168
|
+
* The `gradle=` argument accepts either a `build.gradle` / `build.gradle.kts` file path or a folder path. When a file is given, the plugin derives the `app/build.gradle(.kts)` path from the same directory automatically.
|
|
1169
|
+
* If your project uses Kotlin DSL, point `gradle=` to `build.gradle.kts` instead.
|
|
1170
|
+
|
|
1085
1171
|
## Manually adding iOS OneAgent to a project
|
|
1086
1172
|
|
|
1087
1173
|
Adding the iOS agent manually depends on the availability of support for CocoaPods.
|
|
@@ -1113,9 +1199,6 @@ Before installing the plugin, add the following to your `package.json`:
|
|
|
1113
1199
|
|
|
1114
1200
|
```
|
|
1115
1201
|
"overrides": {
|
|
1116
|
-
"@react-native-picker/picker": {
|
|
1117
|
-
"react-native": "<insert-version-here>"
|
|
1118
|
-
},
|
|
1119
1202
|
"@dynatrace/react-native-plugin": {
|
|
1120
1203
|
"react-native": "<insert-version-here>"
|
|
1121
1204
|
}
|
|
@@ -1126,9 +1209,6 @@ If you are using the following `"react-native": "npm:react-native-tvos@0.69.8-2"
|
|
|
1126
1209
|
|
|
1127
1210
|
```
|
|
1128
1211
|
"overrides": {
|
|
1129
|
-
"@react-native-picker/picker": {
|
|
1130
|
-
"react-native": "0.69.8-2"
|
|
1131
|
-
},
|
|
1132
1212
|
"@dynatrace/react-native-plugin": {
|
|
1133
1213
|
"react-native": "0.69.8-2"
|
|
1134
1214
|
}
|
|
@@ -1192,6 +1272,8 @@ Here is a list of all the counterparts for the options that can be used with a m
|
|
|
1192
1272
|
|lifecycleUpdate|false| - | - | lifecycle.includeUpdate |
|
|
1193
1273
|
|userOptIn|false|userOptIn|DTXUserOptIn| - |
|
|
1194
1274
|
|actionNamePrivacy|false|-|-|input.actionNamePrivacy
|
|
1275
|
+
|actionNamePreference|'any'|-|-|input.actionNamePreference
|
|
1276
|
+
|actionNameAlgorithm|'depth-first'|-|-|input.actionNameAlgorithm
|
|
1195
1277
|
|bundleName|undefined|-|-|bundleName
|
|
1196
1278
|
|
|
1197
1279
|
### React block
|
|
@@ -1208,6 +1290,8 @@ react : {
|
|
|
1208
1290
|
},
|
|
1209
1291
|
|
|
1210
1292
|
actionNamePrivacy: false,
|
|
1293
|
+
actionNamePreference: 'any',
|
|
1294
|
+
actionNameAlgorithm: 'depth-first',
|
|
1211
1295
|
}
|
|
1212
1296
|
}
|
|
1213
1297
|
```
|
|
@@ -1243,7 +1327,7 @@ react: {
|
|
|
1243
1327
|
This activates the debug mode. You will get more console output during instrumentation and at runtime.
|
|
1244
1328
|
|
|
1245
1329
|
|
|
1246
|
-
#### User Interaction
|
|
1330
|
+
#### User Interaction Configuration
|
|
1247
1331
|
|
|
1248
1332
|
```js
|
|
1249
1333
|
react: {
|
|
@@ -1251,37 +1335,7 @@ react: {
|
|
|
1251
1335
|
}
|
|
1252
1336
|
```
|
|
1253
1337
|
|
|
1254
|
-
Enables or disables the UI interaction (user interaction) feature.
|
|
1255
|
-
Set to false to disable capturing of user interactions (e.g., touch/click actions) produced by the React Native UI interaction instrumentation.
|
|
1256
|
-
|
|
1257
|
-
##### What customers will observe after enabling UI Interaction
|
|
1258
|
-
|
|
1259
|
-
After setting `react.userInteraction: true` and rebuilding with instrumentation, the expected flow is:
|
|
1260
|
-
|
|
1261
|
-
1. Build-time instrumentation wraps supported UI elements and app root entrypoints.
|
|
1262
|
-
2. At runtime, touch/press interactions are captured and converted into UI interaction events.
|
|
1263
|
-
3. Events are processed by the plugin event pipeline and sent to Dynatrace.
|
|
1264
|
-
4. In Dynatrace, customers can analyze captured user interactions (for example, touch-driven behavior and related UI element context).
|
|
1265
|
-
|
|
1266
|
-
Notes:
|
|
1267
|
-
|
|
1268
|
-
- No extra UI needs to be added in customer screens for standard automatic capture.
|
|
1269
|
-
- If `react.debug` is enabled, additional debug output can appear during instrumentation/runtime.
|
|
1270
|
-
|
|
1271
|
-
##### Runtime switching (config + remote configuration observer)
|
|
1272
|
-
|
|
1273
|
-
UI Interaction can be controlled by two layers:
|
|
1274
|
-
|
|
1275
|
-
1. **Build/config layer (`dynatrace.config.js`)**
|
|
1276
|
-
- `react.userInteraction: true|false` controls whether the UI Interaction instrumentation feature is applied.
|
|
1277
|
-
|
|
1278
|
-
2. **Runtime remote layer (`RuntimeConfigurationObserver`)**
|
|
1279
|
-
- Runtime emission checks the remote flag `touch_interaction_enabled`.
|
|
1280
|
-
- If remote flag is present, it is used as the source of truth.
|
|
1281
|
-
- If remote flag is temporarily unavailable, the plugin falls back to the last known good remote value.
|
|
1282
|
-
- If no remote value was received yet, runtime defaults to enabled behavior.
|
|
1283
|
-
|
|
1284
|
-
In short: local config enables the feature path, while remote configuration can dynamically allow/deny event emission at runtime.
|
|
1338
|
+
Enables or disables the UI interaction (user interaction) feature. Set to `false` to disable capturing of user interactions (for example, touch/click actions) produced by the React Native UI interaction instrumentation. See the [User Interaction](#user-interaction) section for behavior, produced data, and runtime control details.
|
|
1285
1339
|
|
|
1286
1340
|
#### Error Handler
|
|
1287
1341
|
|
|
@@ -1545,20 +1599,38 @@ ios: {
|
|
|
1545
1599
|
* displayName: Use the displayName property to check if React views have a display name set
|
|
1546
1600
|
* instrumentation string: Auto instrumentation or manual instrumentation is passing a string. This will be used if available.
|
|
1547
1601
|
* class name: If the display name is not available, the class name is used by taking the property name from the constructor
|
|
1548
|
-
* Touchables
|
|
1549
|
-
* dtActionName: Use a custom property called dtActionName
|
|
1550
|
-
* If [actionNamePrivacy](#plugin-startup) is activated anything below will not be detected
|
|
1551
|
-
* accessibilityLabel property
|
|
1552
|
-
* If both are not set, it will search for an inner text
|
|
1553
|
-
* If it is an Image Button, it will search for a source
|
|
1554
|
-
* Buttons
|
|
1602
|
+
* Touchables, Buttons, Pressable
|
|
1555
1603
|
* dtActionName: Use a custom property called dtActionName
|
|
1556
|
-
* If [actionNamePrivacy](#plugin-startup) is activated
|
|
1557
|
-
*
|
|
1604
|
+
* If [actionNamePrivacy](#plugin-startup) is activated anything below will not be detected
|
|
1605
|
+
* title property
|
|
1558
1606
|
* accessibilityLabel property
|
|
1559
|
-
* If
|
|
1560
|
-
*
|
|
1561
|
-
|
|
1607
|
+
* If none of the above exist, we recursively traverse `children` to find a name. We consider text, the source property of any `ReactNative.Image` and the name property of any functional component called `Icon`.
|
|
1608
|
+
* You can use `actionNamePreference` to specify which of these 3 you prefer. Consider the following example:
|
|
1609
|
+
```tsx
|
|
1610
|
+
<TouchableOpacity onPress={onPress}>
|
|
1611
|
+
<View>
|
|
1612
|
+
<Image source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }} />
|
|
1613
|
+
<Text>Some Text</Text>
|
|
1614
|
+
</View>
|
|
1615
|
+
</TouchableOpacity>
|
|
1616
|
+
```
|
|
1617
|
+
- `'text'`: Resulting name: `Some Text`. Prefers text and falls back to any match.
|
|
1618
|
+
- `'icon'`: Resulting name: `Image Button: https://reactnative.dev/img/tiny_logo.png`. Prefers `ReactNative.Image` and custom Icons and falls back to any match.
|
|
1619
|
+
- `'any'`: Resulting name: `Image Button: https://reactnative.dev/img/tiny_logo.png`. Accepts the first match regardless of type (text, image, or custom icon).
|
|
1620
|
+
* You can use `actionNameAlgorithm` to specify with what algorithm `children` are traversed recursively, which in turn decides which name will be found first and used. Consider the following example:
|
|
1621
|
+
```tsx
|
|
1622
|
+
<TouchableOpacity onPress={onPress}>
|
|
1623
|
+
<View>
|
|
1624
|
+
<View>
|
|
1625
|
+
<Text>Deep Text</Text>
|
|
1626
|
+
</View>
|
|
1627
|
+
<Text>Shallow Text</Text>
|
|
1628
|
+
</View>
|
|
1629
|
+
</TouchableOpacity>
|
|
1630
|
+
```
|
|
1631
|
+
- `'depth-first'`: Resulting name: `Deep Text`. Follows the first child branch fully before trying siblings.
|
|
1632
|
+
- `'breadth-first'`: Resulting name: `Shallow Text`. Visits all siblings at a level before going deeper, returning the shallowest match first.
|
|
1633
|
+
* Switch, RefreshControl, Picker
|
|
1562
1634
|
* dtActionName: Use a custom property called dtActionName
|
|
1563
1635
|
* accessibilityLabel property
|
|
1564
1636
|
|
|
@@ -1916,6 +1988,16 @@ If you are struggling with a problem, submit a support ticket to Dynatrace (supp
|
|
|
1916
1988
|
<br/><br/>
|
|
1917
1989
|
## Changelog
|
|
1918
1990
|
|
|
1991
|
+
2.337.2
|
|
1992
|
+
* Updated Android Agent (8.337.3.1013)
|
|
1993
|
+
* Fixed crash in `Dynatrace.getUserPrivacyOptions()` on Android
|
|
1994
|
+
|
|
1995
|
+
2.337.1
|
|
1996
|
+
* Updated Android (8.337.2.1010) & iOS Agent (8.337.1.1003)
|
|
1997
|
+
* Fixed gradle path derivation for custom `--gradle` arguments: the plugin now correctly probes the filesystem to auto-detect `app/build.gradle(.kts)` with proper Kotlin DSL support, and validates that only `build.gradle` or `build.gradle.kts` files are accepted (not `settings.gradle`).
|
|
1998
|
+
* Enables [pnpm monorepo instrumentation](#pnpm-monorexpo-setup) by allowing explicit `config=`, `gradle=`, and `plist=` arguments in root `package.json` scripts, supporting shared native project layouts where `android/` and `ios/` are not co-located with each app.
|
|
1999
|
+
* Added [actionNamePreference](#plugin-startup) and [actionNameAlgorithm](#plugin-startup) configuration flags.
|
|
2000
|
+
|
|
1919
2001
|
2.335.1
|
|
1920
2002
|
* Updated Android (8.335.1.1001) & iOS Agent (8.335.1.1009)
|
|
1921
2003
|
* Dynatrace Android configuration (`dynatrace.gradle`) is now written directly next to the `build.gradle` file instead of inside `node_modules`. Existing projects with the old path are migrated automatically.
|
|
@@ -1924,11 +2006,13 @@ If you are struggling with a problem, submit a support ticket to Dynatrace (supp
|
|
|
1924
2006
|
* Significantly faster JS bundle builds
|
|
1925
2007
|
* Sourcemaps now natively account for our auto-instrumentation - no patching needed
|
|
1926
2008
|
* Added instrumentation for `BorderlessButton` and `BaseButton` from `react-native-gesture-handler`.
|
|
2009
|
+
* Improved iOS `Info.plist` auto-discovery for `npx instrumentDynatrace` by resolving names from `app.json`, `app.config.js`, and `app.config.ts`, plus `INFOPLIST_FILE` values from Xcode project settings.
|
|
2010
|
+
* Added safer fallback scanning for `Info.plist` in `ios/`, with explicit ambiguity errors for multi-target/monorepo layouts and guidance to pass `plist=...` when needed.
|
|
1927
2011
|
|
|
1928
2012
|
2.333.1
|
|
1929
2013
|
* Jetpack Compose support range extended to 1.4 - 1.10 see [Compose Compatibility Note](#compose-compatibility-note)
|
|
1930
2014
|
* Updated Android (8.333.1.1006) & iOS Agent (8.333.1.1005)
|
|
1931
|
-
* Added
|
|
2015
|
+
* Added configuration flag to enable/disable the [User Interaction feature](#user-interaction-configuration).
|
|
1932
2016
|
* Added [User Interaction feature](#user-interaction) to collect UI interaction data such as touches, providing insights into user behavior
|
|
1933
2017
|
|
|
1934
2018
|
2.331.1
|
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.337.3.1013'
|
|
76
76
|
implementation "com.facebook.react:react-native:${safeExtGet('reactNative', '+')}"
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -400,7 +400,7 @@ class DynatraceRNBridgeImpl(
|
|
|
400
400
|
val privacyMap = Arguments.createMap()
|
|
401
401
|
privacyMap.putString("dataCollectionLevel", options.dataCollectionLevel.name)
|
|
402
402
|
privacyMap.putBoolean("crashReportingOptedIn", options.isCrashReportingOptedIn)
|
|
403
|
-
privacyMap.putBoolean("screenRecordOptedIn", options.isScreenRecordOptedIn)
|
|
403
|
+
privacyMap.putBoolean("screenRecordOptedIn", options.isScreenRecordOptedIn ?: false)
|
|
404
404
|
promise.resolve(privacyMap)
|
|
405
405
|
}
|
|
406
406
|
}
|
package/files/plugin.gradle
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var _templateObject,_templateObject2,_templateObject3,_templateObject4,_templateObject5,_templateObject6,_interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault"),_taggedTemplateLiteral2=_interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));function _createForOfIteratorHelper(e,t){var n,r,a,i,o="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(o)return a=!(r=!0),{s:function(){o=o.call(e)},n:function(){var e=o.next();return r=e.done,e},e:function(e){a=!0,n=e},f:function(){try{r||null==o.return||o.return()}finally{if(a)throw n}}};if(Array.isArray(e)||(o=_unsupportedIterableToArray(e))||t&&e&&"number"==typeof e.length)return o&&(e=o),i=0,{s:t=function(){},n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:t};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 _unsupportedIterableToArray(e,t){var n;if(e)return"string"==typeof e?_arrayLikeToArray(e,t):"Map"===(n="Object"===(n={}.toString.call(e).slice(8,-1))&&e.constructor?e.constructor.name:n)||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(e,t):void 0}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}Object.defineProperty(exports,"__esModule",{value:!0});var reactOptions,fspath=require("path"),fs=require("fs"),core_1=require("@babel/core"),generator_1=require("@babel/generator"),PathsConstants_1=require("../scripts/PathsConstants"),Config_1=require("../scripts/Config"),GetValuesFromPackage_1=require("../lib/core/util/GetValuesFromPackage"),Types_1=require("./model/Types"),INSTRUMENTATION_LIBS="@dynatrace/react-native-plugin/instrumentation/libs",hasJSX=function(e){var t=!1;return e.traverse({"JSXElement|JSXFragment":function(){t=!0}}),t},instrumentUserInteraction=function(e){e.traverse({"FunctionDeclaration|ObjectMethod":function(e){var e=e.node,t=core_1.types.isFunctionDeclaration(e)?e.id:e.key;core_1.types.isIdentifier(t,{name:"registerComponent"})&&(t="".concat(INSTRUMENTATION_LIBS,"/UserInteraction"),e.body.body.unshift(core_1.template.statement('componentProvider = require("'.concat(t,'").wrapProvider(componentProvider);'))()))}})},instrumentAppRegistry=function(e){e.traverse({"FunctionDeclaration|ObjectMethod":function(e){var e=e.node,t=core_1.types.isFunctionDeclaration(e)?e.id:e.key;core_1.types.isIdentifier(t,{name:"runApplication"})&&e.body.body.unshift(core_1.template.statement(_templateObject=_templateObject||(0,_taggedTemplateLiteral2.default)(['require("@dynatrace/react-native-plugin").ApplicationHandler.startup();']))())}})},instrumentExceptionsManager=function(e){var t,n=null!=(t=null==(t=null==reactOptions?void 0:reactOptions.errorHandler)?void 0:t.reportFatalErrorAsCrash)&&t,r=(null==reactOptions?void 0:reactOptions.autoStart)&&(null==(t=null==reactOptions?void 0:reactOptions.errorHandler)?void 0:t.enabled);e.traverse({FunctionDeclaration:function(e){var t;core_1.types.isIdentifier(e.node.id,{name:"handleException"})&&(t=core_1.template.statement(_templateObject2=_templateObject2||(0,_taggedTemplateLiteral2.default)(['\n setTimeout(() => BODY, require("@dynatrace/react-native-plugin/lib/core/ErrorHandler")\n .reportErrorToDynatrace(e, isFatal, CRASH, AUTO));\n ']))({BODY:core_1.types.cloneNode(e.node.body),CRASH:core_1.types.booleanLiteral(n),AUTO:core_1.types.booleanLiteral(!!r)}),e.node.body.body=[t])}})},instrumentCssInterop=function(e){e.traverse({CallExpression:function(e){core_1.types.isIdentifier(e.node.callee,{name:"require"})&&(e=e.node.arguments[0],core_1.types.isStringLiteral(e))&&("react/jsx-runtime"===e.value?e.value="@dynatrace/react-native-plugin/jsx-runtime":"react/jsx-dev-runtime"===e.value&&(e.value="@dynatrace/react-native-plugin/jsx-dev-runtime"))}})},instrumentNavigation=function(e){e.traverse({VariableDeclarator:function(e){var t;core_1.types.isIdentifier(e.node.id,{name:"getRootState"})&&(t=core_1.template.statement(_templateObject3=_templateObject3||(0,_taggedTemplateLiteral2.default)(["\n require(PATH).monitorNavigation(getRootState);\n "]))({PATH:core_1.types.stringLiteral("".concat(INSTRUMENTATION_LIBS,"/react-navigation/ReactNavigation"))}),e.parentPath.insertAfter(t))}})},instrumentReactCreateElement=function(e){var t=core_1.template.statement(_templateObject4=_templateObject4||(0,_taggedTemplateLiteral2.default)(["\n require(PATH).instrumentCreateElement(module.exports);\n "]))({PATH:core_1.types.stringLiteral("@dynatrace/react-native-plugin/instrumentation/jsx/ElementHelper")});e.pushContainer("body",t)},instrumentComponents=function(e,n){e.traverse({FunctionDeclaration:function(e){var t;hasJSX(e)&&(t=e.node,core_1.types.isIdentifier(t.id))&&null!=(e=e.getStatementParent())&&e.insertAfter(n(t.id.name,Types_1.Types.FunctionalComponent))},ClassDeclaration:function(e){var t;hasJSX(e)&&(t=e.node,core_1.types.isIdentifier(t.id))&&null!=(e=e.getStatementParent())&&e.insertAfter(n(t.id.name,Types_1.Types.ClassComponent))},"FunctionExpression|ArrowFunctionExpression":function(e){var t;hasJSX(e)&&(t=e.parent,void 0!==(t=core_1.types.isVariableDeclarator(t)&&core_1.types.isIdentifier(t.id)?t.id.name:core_1.types.isAssignmentExpression(t)&&core_1.types.isIdentifier(t.left)?t.left.name:void 0))&&null!=(e=e.getStatementParent())&&e.insertAfter(n(t,Types_1.Types.FunctionalComponent))}})},instrumentLifecycle=function(e){instrumentComponents(e,function(e,t){return core_1.template.statement(_templateObject5=_templateObject5||(0,_taggedTemplateLiteral2.default)(["NAME._dtInfo = { type: TYPE, name: 'NAME_STR' }"]))({NAME:core_1.types.identifier(e),TYPE:core_1.types.numericLiteral(t),NAME_STR:core_1.types.stringLiteral(e)})})},instrumentComponentNames=function(e){instrumentComponents(e,function(e){return core_1.template.statement(_templateObject6=_templateObject6||(0,_taggedTemplateLiteral2.default)(["NAME.dtName = 'NAME_STR'"]))({NAME:core_1.types.identifier(e),NAME_STR:core_1.types.stringLiteral(e)})})},instrumentInput=function(e){var l=new Map([["react-native",{proxy:"".concat(INSTRUMENTATION_LIBS,"/react-native/"),components:new Set(["TouchableHighlight","TouchableNativeFeedback","TouchableOpacity","TouchableWithoutFeedback","Button","RefreshControl","Text","Pressable","Switch"])}],["react-native-gesture-handler",{proxy:"".concat(INSTRUMENTATION_LIBS,"/community/gesture-handler/"),components:new Set(["TouchableHighlight","TouchableNativeFeedback","TouchableOpacity","TouchableWithoutFeedback","RectButton","BorderlessButton","BaseButton"])}],["@react-native-picker/picker",{proxy:"".concat(INSTRUMENTATION_LIBS,"/community/Picker"),components:new Set(["Picker","PickerIOS"])}]]);e.traverse({ImportDeclaration:function(e){if(void 0===e.node.processed){var t=e.node.source;if(l.has(t.value)){var r=l.get(t.value),n=e.node.specifiers,a=[],i=[];if(n.forEach(function(e,t){var n;core_1.types.isImportSpecifier(e)&&(n=core_1.types.isIdentifier(e.imported)?e.imported.name:e.imported.value,r.components.has(n)||(a.push(e),i.push(t)))}),a.length!==n.length){var o,s=_createForOfIteratorHelper(i.reverse());try{for(s.s();!(o=s.n()).done;){var c=o.value;n.splice(c,1)}}catch(e){s.e(e)}finally{s.f()}0<a.length&&((t=core_1.types.importDeclaration(a,core_1.types.stringLiteral(t.value))).processed=!0,e.insertBefore(t)),e.node.source=core_1.types.stringLiteral(r.proxy),e.scope.crawl()}}}},CallExpression:function(e){core_1.types.isIdentifier(e.node.callee,{name:"require"})&&(e=e.node.arguments[0],core_1.types.isStringLiteral(e))&&l.has(e.value)&&(e.value=l.get(e.value).proxy)}})},instrumentJsxNames=function(e){e.traverse({JSXOpeningElement:function(e){var t=e.node.name,t=core_1.types.isJSXIdentifier(t)?t.name:core_1.types.isJSXMemberExpression(t)?(0,generator_1.default)(t).code:void 0;t&&e.node.attributes.push(core_1.types.jsxAttribute(core_1.types.jsxIdentifier("dtName"),core_1.types.stringLiteral(t)))}})},instrumentConfigurationPreset=function(e){var t,n=(0,GetValuesFromPackage_1.getHostAppBundleInfo)(PathsConstants_1.default.getPackageJsonFile()),r={getLifecycleUpdate:reactOptions.lifecycle.includeUpdate,getLogLevel:reactOptions.debug?0:1,getBundleName:null!=(t=reactOptions.bundleName)?t:null==n?void 0:n.name,getBundleVersion:null!=(t=reactOptions.bundleVersion)?t:null==n?void 0:n.version,getActionNamePrivacy:reactOptions.input.actionNamePrivacy,isErrorHandlerEnabled:reactOptions.errorHandler.enabled,isReportFatalErrorAsCrash:reactOptions.errorHandler.reportFatalErrorAsCrash,isAutoStartupEnabled:reactOptions.autoStart};e.traverse({ClassMethod:function(e){var t;core_1.types.isIdentifier(e.node.key)&&void 0!==(t=r[e.node.key.name])&&(e=e.node.body.body[0],core_1.types.isReturnStatement(e))&&(e.argument=core_1.types.valueToNode(t))}})};exports.default=function(){return{visitor:{Program:function(e,t){reactOptions=(0,Config_1.readConfigDefault)().react;var n,r,a,i,o,s,c=t.filename;void 0!==c&&(a=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.some(function(e){return c.includes(fspath.join("node_modules",e)+fspath.sep)})},s=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.some(function(e){return c.endsWith(e)})},!(i="")===reactOptions.debugBabelPlugin&&(i=(0,generator_1.default)(e.node).code),a("@dynatrace")&&s("ConfigurationPreset.js")&&instrumentConfigurationPreset(e),a("react-native")&&s("AppRegistry.js","AppRegistryImpl.js")&&(reactOptions.autoStart&&instrumentAppRegistry(e),reactOptions.userInteraction)&&instrumentUserInteraction(e),a("react-native")&&s("ExceptionsManager.js")&&instrumentExceptionsManager(e),a("react-native-css-interop")&&s("jsx-runtime.js","jsx-dev-runtime.js")&&instrumentCssInterop(e),reactOptions.navigation.enabled&&a("@react-navigation")&&s("BaseNavigationContainer.js","BaseNavigationContainer.tsx")&&instrumentNavigation(e),a("react")&&s("index.js")&&instrumentReactCreateElement(e),null!=(n=null==(r=reactOptions.lifecycle)?void 0:r.instrument)&&n.call(r,c)&&(!c.includes("node_modules")||a("react-native")&&s("renderApplication.js"))&&hasJSX(e)&&instrumentLifecycle(e),null==(r=null==(n=reactOptions.input)?void 0:n.instrument)||!r.call(n,c)||c.includes("node_modules")&&!a("@react-navigation","react-native-drawer-layout")||instrumentInput(e),reactOptions.userInteraction&&!c.includes("node_modules")&&(instrumentJsxNames(e),instrumentComponentNames(e)),!0===reactOptions.debugBabelPlugin)&&(o=(0,generator_1.default)(e.node).code)!==i&&(s=fspath.join(PathsConstants_1.default.getBuildPath(),fspath.relative(PathsConstants_1.default.getApplicationPath(),c)+".dtx"),fs.mkdirSync(fspath.dirname(s),{recursive:!0}),fs.writeFileSync(s,o),t.set("fileDidChange",!0))}},post:function(e){var t;!0===reactOptions.debugBabelPlugin&&!0===this.get("fileDidChange")&&(t=(0,generator_1.default)(e.ast).code,e=fspath.join(PathsConstants_1.default.getBuildPath(),fspath.relative(PathsConstants_1.default.getApplicationPath(),e.opts.filename)+".dtx.downstream"),fs.mkdirSync(fspath.dirname(e),{recursive:!0}),fs.writeFileSync(e,t))}}};
|
|
1
|
+
var _templateObject,_templateObject2,_templateObject3,_templateObject4,_templateObject5,_templateObject6,_interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault"),_taggedTemplateLiteral2=_interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));function _createForOfIteratorHelper(e,t){var n,r,a,i,o="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(o)return a=!(r=!0),{s:function(){o=o.call(e)},n:function(){var e=o.next();return r=e.done,e},e:function(e){a=!0,n=e},f:function(){try{r||null==o.return||o.return()}finally{if(a)throw n}}};if(Array.isArray(e)||(o=_unsupportedIterableToArray(e))||t&&e&&"number"==typeof e.length)return o&&(e=o),i=0,{s:t=function(){},n:function(){return i>=e.length?{done:!0}:{done:!1,value:e[i++]}},e:function(e){throw e},f:t};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 _unsupportedIterableToArray(e,t){var n;if(e)return"string"==typeof e?_arrayLikeToArray(e,t):"Map"===(n="Object"===(n={}.toString.call(e).slice(8,-1))&&e.constructor?e.constructor.name:n)||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(e,t):void 0}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}Object.defineProperty(exports,"__esModule",{value:!0});var reactOptions,fspath=require("path"),fs=require("fs"),core_1=require("@babel/core"),generator_1=require("@babel/generator"),PathsConstants_1=require("../scripts/PathsConstants"),Config_1=require("../scripts/Config"),GetValuesFromPackage_1=require("../lib/core/util/GetValuesFromPackage"),Types_1=require("./model/Types"),INSTRUMENTATION_LIBS="@dynatrace/react-native-plugin/instrumentation/libs",hasJSX=function(e){var t=!1;return e.traverse({"JSXElement|JSXFragment":function(){t=!0}}),t},instrumentUserInteraction=function(e){e.traverse({"FunctionDeclaration|ObjectMethod":function(e){var e=e.node,t=core_1.types.isFunctionDeclaration(e)?e.id:e.key;core_1.types.isIdentifier(t,{name:"registerComponent"})&&(t="".concat(INSTRUMENTATION_LIBS,"/UserInteraction"),e.body.body.unshift(core_1.template.statement('componentProvider = require("'.concat(t,'").wrapProvider(componentProvider);'))()))}})},instrumentAppRegistry=function(e){e.traverse({"FunctionDeclaration|ObjectMethod":function(e){var e=e.node,t=core_1.types.isFunctionDeclaration(e)?e.id:e.key;core_1.types.isIdentifier(t,{name:"runApplication"})&&e.body.body.unshift(core_1.template.statement(_templateObject=_templateObject||(0,_taggedTemplateLiteral2.default)(['require("@dynatrace/react-native-plugin").ApplicationHandler.startup();']))())}})},instrumentExceptionsManager=function(e){var t,n=null!=(t=null==(t=null==reactOptions?void 0:reactOptions.errorHandler)?void 0:t.reportFatalErrorAsCrash)&&t,r=(null==reactOptions?void 0:reactOptions.autoStart)&&(null==(t=null==reactOptions?void 0:reactOptions.errorHandler)?void 0:t.enabled);e.traverse({FunctionDeclaration:function(e){var t;core_1.types.isIdentifier(e.node.id,{name:"handleException"})&&(t=core_1.template.statement(_templateObject2=_templateObject2||(0,_taggedTemplateLiteral2.default)(['\n setTimeout(() => BODY, require("@dynatrace/react-native-plugin/lib/core/ErrorHandler")\n .reportErrorToDynatrace(e, isFatal, CRASH, AUTO));\n ']))({BODY:core_1.types.cloneNode(e.node.body),CRASH:core_1.types.booleanLiteral(n),AUTO:core_1.types.booleanLiteral(!!r)}),e.node.body.body=[t])}})},instrumentCssInterop=function(e){e.traverse({CallExpression:function(e){core_1.types.isIdentifier(e.node.callee,{name:"require"})&&(e=e.node.arguments[0],core_1.types.isStringLiteral(e))&&("react/jsx-runtime"===e.value?e.value="@dynatrace/react-native-plugin/jsx-runtime":"react/jsx-dev-runtime"===e.value&&(e.value="@dynatrace/react-native-plugin/jsx-dev-runtime"))}})},instrumentNavigation=function(e){e.traverse({VariableDeclarator:function(e){var t;core_1.types.isIdentifier(e.node.id,{name:"getRootState"})&&(t=core_1.template.statement(_templateObject3=_templateObject3||(0,_taggedTemplateLiteral2.default)(["\n require(PATH).monitorNavigation(getRootState);\n "]))({PATH:core_1.types.stringLiteral("".concat(INSTRUMENTATION_LIBS,"/react-navigation/ReactNavigation"))}),e.parentPath.insertAfter(t))}})},instrumentReactCreateElement=function(e){var t=core_1.template.statement(_templateObject4=_templateObject4||(0,_taggedTemplateLiteral2.default)(["\n require(PATH).instrumentCreateElement(module.exports);\n "]))({PATH:core_1.types.stringLiteral("@dynatrace/react-native-plugin/instrumentation/jsx/ElementHelper")});e.pushContainer("body",t)},instrumentComponents=function(e,n){e.traverse({FunctionDeclaration:function(e){var t;hasJSX(e)&&(t=e.node,core_1.types.isIdentifier(t.id))&&null!=(e=e.getStatementParent())&&e.insertAfter(n(t.id.name,Types_1.Types.FunctionalComponent))},ClassDeclaration:function(e){var t;hasJSX(e)&&(t=e.node,core_1.types.isIdentifier(t.id))&&null!=(e=e.getStatementParent())&&e.insertAfter(n(t.id.name,Types_1.Types.ClassComponent))},"FunctionExpression|ArrowFunctionExpression":function(e){var t;hasJSX(e)&&(t=e.parent,void 0!==(t=core_1.types.isVariableDeclarator(t)&&core_1.types.isIdentifier(t.id)?t.id.name:core_1.types.isAssignmentExpression(t)&&core_1.types.isIdentifier(t.left)?t.left.name:void 0))&&null!=(e=e.getStatementParent())&&e.insertAfter(n(t,Types_1.Types.FunctionalComponent))}})},instrumentLifecycle=function(e){instrumentComponents(e,function(e,t){return core_1.template.statement(_templateObject5=_templateObject5||(0,_taggedTemplateLiteral2.default)(["NAME._dtInfo = { type: TYPE, name: 'NAME_STR' }"]))({NAME:core_1.types.identifier(e),TYPE:core_1.types.numericLiteral(t),NAME_STR:core_1.types.stringLiteral(e)})})},instrumentComponentNames=function(e){instrumentComponents(e,function(e){return core_1.template.statement(_templateObject6=_templateObject6||(0,_taggedTemplateLiteral2.default)(["NAME.dtName = 'NAME_STR'"]))({NAME:core_1.types.identifier(e),NAME_STR:core_1.types.stringLiteral(e)})})},instrumentInput=function(e){var l=new Map([["react-native",{proxy:"".concat(INSTRUMENTATION_LIBS,"/react-native/"),components:new Set(["TouchableHighlight","TouchableNativeFeedback","TouchableOpacity","TouchableWithoutFeedback","Button","RefreshControl","Text","Pressable","Switch"])}],["react-native-gesture-handler",{proxy:"".concat(INSTRUMENTATION_LIBS,"/community/gesture-handler/"),components:new Set(["TouchableHighlight","TouchableNativeFeedback","TouchableOpacity","TouchableWithoutFeedback","RectButton","BorderlessButton","BaseButton"])}],["@react-native-picker/picker",{proxy:"".concat(INSTRUMENTATION_LIBS,"/community/Picker"),components:new Set(["Picker","PickerIOS"])}]]);e.traverse({ImportDeclaration:function(e){if(void 0===e.node.processed){var t=e.node.source;if(l.has(t.value)){var r=l.get(t.value),n=e.node.specifiers,a=[],i=[];if(n.forEach(function(e,t){var n;core_1.types.isImportSpecifier(e)&&(n=core_1.types.isIdentifier(e.imported)?e.imported.name:e.imported.value,r.components.has(n)||(a.push(e),i.push(t)))}),a.length!==n.length){var o,s=_createForOfIteratorHelper(i.reverse());try{for(s.s();!(o=s.n()).done;){var c=o.value;n.splice(c,1)}}catch(e){s.e(e)}finally{s.f()}0<a.length&&((t=core_1.types.importDeclaration(a,core_1.types.stringLiteral(t.value))).processed=!0,e.insertBefore(t)),e.node.source=core_1.types.stringLiteral(r.proxy),e.scope.crawl()}}}},CallExpression:function(e){core_1.types.isIdentifier(e.node.callee,{name:"require"})&&(e=e.node.arguments[0],core_1.types.isStringLiteral(e))&&l.has(e.value)&&(e.value=l.get(e.value).proxy)}})},instrumentJsxNames=function(e){e.traverse({JSXOpeningElement:function(e){var t=e.node.name,t=core_1.types.isJSXIdentifier(t)?t.name:core_1.types.isJSXMemberExpression(t)?(0,generator_1.default)(t).code:void 0;t&&e.node.attributes.push(core_1.types.jsxAttribute(core_1.types.jsxIdentifier("dtName"),core_1.types.stringLiteral(t)))}})},instrumentConfigurationPreset=function(e){var t,n=(0,GetValuesFromPackage_1.getHostAppBundleInfo)(PathsConstants_1.default.getPackageJsonFile()),r={getLifecycleUpdate:reactOptions.lifecycle.includeUpdate,getLogLevel:reactOptions.debug?0:1,getBundleName:null!=(t=reactOptions.bundleName)?t:null==n?void 0:n.name,getBundleVersion:null!=(t=reactOptions.bundleVersion)?t:null==n?void 0:n.version,getActionNamePrivacy:reactOptions.input.actionNamePrivacy,getActionNamePreference:reactOptions.input.actionNamePreference,getActionNameAlgorithm:reactOptions.input.actionNameAlgorithm,isErrorHandlerEnabled:reactOptions.errorHandler.enabled,isReportFatalErrorAsCrash:reactOptions.errorHandler.reportFatalErrorAsCrash,isAutoStartupEnabled:reactOptions.autoStart};e.traverse({ClassMethod:function(e){var t;core_1.types.isIdentifier(e.node.key)&&void 0!==(t=r[e.node.key.name])&&(e=e.node.body.body[0],core_1.types.isReturnStatement(e))&&(e.argument=core_1.types.valueToNode(t))}})};exports.default=function(){return{visitor:{Program:function(e,t){reactOptions=(0,Config_1.readConfigDefault)().react;var n,r,a,i,o,s,c=t.filename;void 0!==c&&(a=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.some(function(e){return c.includes(fspath.join("node_modules",e)+fspath.sep)})},s=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return t.some(function(e){return c.endsWith(e)})},!(i="")===reactOptions.debugBabelPlugin&&(i=(0,generator_1.default)(e.node).code),a("@dynatrace")&&s("ConfigurationPreset.js")&&instrumentConfigurationPreset(e),a("react-native")&&s("AppRegistry.js","AppRegistryImpl.js")&&(reactOptions.autoStart&&instrumentAppRegistry(e),reactOptions.userInteraction)&&instrumentUserInteraction(e),a("react-native")&&s("ExceptionsManager.js")&&instrumentExceptionsManager(e),a("react-native-css-interop")&&s("jsx-runtime.js","jsx-dev-runtime.js")&&instrumentCssInterop(e),reactOptions.navigation.enabled&&a("@react-navigation")&&s("BaseNavigationContainer.js","BaseNavigationContainer.tsx")&&instrumentNavigation(e),a("react")&&s("index.js")&&instrumentReactCreateElement(e),null!=(n=null==(r=reactOptions.lifecycle)?void 0:r.instrument)&&n.call(r,c)&&(!c.includes("node_modules")||a("react-native")&&s("renderApplication.js"))&&hasJSX(e)&&instrumentLifecycle(e),null==(r=null==(n=reactOptions.input)?void 0:n.instrument)||!r.call(n,c)||c.includes("node_modules")&&!a("@react-navigation","react-native-drawer-layout")||instrumentInput(e),reactOptions.userInteraction&&!c.includes("node_modules")&&(instrumentJsxNames(e),instrumentComponentNames(e)),!0===reactOptions.debugBabelPlugin)&&(o=(0,generator_1.default)(e.node).code)!==i&&(s=fspath.join(PathsConstants_1.default.getBuildPath(),fspath.relative(PathsConstants_1.default.getApplicationPath(),c)+".dtx"),fs.mkdirSync(fspath.dirname(s),{recursive:!0}),fs.writeFileSync(s,o),t.set("fileDidChange",!0))}},post:function(e){var t;!0===reactOptions.debugBabelPlugin&&!0===this.get("fileDidChange")&&(t=(0,generator_1.default)(e.ast).code,e=fspath.join(PathsConstants_1.default.getBuildPath(),fspath.relative(PathsConstants_1.default.getApplicationPath(),e.opts.filename)+".dtx.downstream"),fs.mkdirSync(fspath.dirname(e),{recursive:!0}),fs.writeFileSync(e,t))}}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault"),_toConsumableArray2=_interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));function _createForOfIteratorHelper(e,t){var n,r,i,o,a="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(a)return i=!(r=!0),{s:function(){a=a.call(e)},n:function(){var e=a.next();return r=e.done,e},e:function(e){i=!0,n=e},f:function(){try{r||null==a.return||a.return()}finally{if(i)throw n}}};if(Array.isArray(e)||(a=_unsupportedIterableToArray(e))||t&&e&&"number"==typeof e.length)return a&&(e=a),o=0,{s:t=function(){},n:function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:t};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 _unsupportedIterableToArray(e,t){var n;if(e)return"string"==typeof e?_arrayLikeToArray(e,t):"Map"===(n="Object"===(n={}.toString.call(e).slice(8,-1))&&e.constructor?e.constructor.name:n)||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(e,t):void 0}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}Object.defineProperty(exports,"__esModule",{value:!0}),exports.instrument=void 0;var FileType,nodePath=require("path"),jscodeshift=require("jscodeshift"),Collection_1=require("jscodeshift/src/Collection"),FileOperationHelper_1=require("../scripts/FileOperationHelper"),PathsConstants_1=require("../scripts/PathsConstants"),GetValuesFromPackage_1=require("../lib/core/util/GetValuesFromPackage"),InstrumentUtil_1=require("../scripts/util/InstrumentUtil"),Run_1=require("../lib/features/ui-interaction/Run"),Touchables_InstrInfo_1=require("./libs/react-native/Touchables.InstrInfo"),RefreshControl_InstrInfo_1=require("./libs/react-native/RefreshControl.InstrInfo"),Switch_InstrInfo_1=require("./libs/react-native/Switch.InstrInfo"),Touchables_InstrInfo_2=require("./libs/community/gesture-handler/Touchables.InstrInfo"),Picker_InstrInfo_1=require("./libs/community/Picker.InstrInfo"),Types_1=require("./model/Types"),ParserUtil_1=require("./parser/ParserUtil"),referenceListInput=((e=>{e[e.Filtered=-1]="Filtered",e[e.Normal=0]="Normal",e[e.ReactNative=1]="ReactNative",e[e.React=2]="React",e[e.ReactNativeCssInterop=3]="ReactNativeCssInterop"})(FileType=FileType||{}),[]),whiteList=(referenceListInput.push.apply(referenceListInput,(0,_toConsumableArray2.default)(Touchables_InstrInfo_1.instrumentationInfo)),referenceListInput.push.apply(referenceListInput,(0,_toConsumableArray2.default)(RefreshControl_InstrInfo_1.instrumentationInfo)),referenceListInput.push.apply(referenceListInput,(0,_toConsumableArray2.default)(Switch_InstrInfo_1.instrumentationInfo)),referenceListInput.push.apply(referenceListInput,(0,_toConsumableArray2.default)(Touchables_InstrInfo_2.instrumentationInfo)),referenceListInput.push.apply(referenceListInput,(0,_toConsumableArray2.default)(Picker_InstrInfo_1.instrumentationInfo)),new Set(["AppRegistry","AppRegistryImpl","renderApplication","ExceptionsManager"])),instrumentationLibraryFolder="@dynatrace/react-native-plugin/instrumentation/libs",instrument=function(e,t,n){t=correctFilename(t);var r=shouldInstrumentFile(t);if(r!==FileType.Filtered){var i=!1,o=parseSource(t,e);if(r===FileType.React)addCreateElementInstrumentation(o),i=!0;else if(r===FileType.ReactNative)t.endsWith("AppRegistryImpl.js")?null!=n&&n.autoStart&&addStartupCallRegistryImpl(o)&&(i=!0):t.endsWith("AppRegistry.js")?null!=n&&n.autoStart&&addStartupCallRegistry(o)&&(i=!0):t.endsWith("renderApplication.js")?(addInfoToComponent(o),i=!0):t.endsWith("ExceptionsManager.js")&&(a=void 0!==n&&n.autoStart&&n.errorHandler.enabled,addReportErrorToDynatraceCall(o,n.errorHandler.reportFatalErrorAsCrash,a),i=!0);else if(r===FileType.ReactNativeCssInterop)i=replaceReactWithDynatraceJsxRuntime(o)||i;else{var a=getInstrumentationList(t,n),r=[{isEnabled:function(e,t){return!0===(null==t?void 0:t.userInteraction)},run:function(e,t,n){return(0,Run_1.runDTUserInteraction)(e,t,n)}}].filter(function(e){return e.isEnabled(t,n)});if(n.navigation.enabled&&instrumentReactNavigation(t,o))i=!0;else{if(!a.input&&!a.lifecycle&&0===r.length)return null!=n&&n.debug&&console.log("Dynatrace - Filtered All: ".concat(t)),deleteTransformation(t),e;a.lifecycle&&addInfoToComponent(o)&&(i=!0),a.input&&referenceListInput.forEach(function(e){e=swapReferences(o,e);o=e.root,i=i||e.modified})}var s,l=_createForOfIteratorHelper(r);try{for(l.s();!(s=l.n()).done;){var c=s.value;try{var u=c.run(o,t,n),o=u.root;u.modified&&(i=!0)}catch(e){var f=e instanceof Error?e.stack||e.message:String(e);null!=n&&n.debug&&console.log("[DynatraceInstrumentationRaw]: Feature instrumentation failed for ".concat(t,": ").concat(f))}}}catch(e){l.e(e)}finally{l.f()}}var a=i?o.toSource({quote:"single"}):e;i?writeTransformation(e=a,t):deleteTransformation(t),null!=n&&n.debug&&i&&console.log("Dynatrace - Modified Filename: "+t)}else t.includes(nodePath.join("@dynatrace","react-native-plugin"))&&t.endsWith(nodePath.join("lib","core","configuration","ConfigurationPreset.js"))&&void 0!==n&&(r=(0,GetValuesFromPackage_1.getHostAppBundleInfo)(PathsConstants_1.default.getPackageJsonFile()),a=parseSource(t,e),void 0!==n.lifecycle&&changeConfigurationValue(a,"getLifecycleUpdate",n.lifecycle.includeUpdate),void 0!==n.debug&&changeConfigurationValue(a,"getLogLevel",n.debug?0:1),void 0!==n.bundleName?changeConfigurationValue(a,"getBundleName",n.bundleName):null!==r&&changeConfigurationValue(a,"getBundleName",null==r?void 0:r.name),void 0!==n.bundleVersion?changeConfigurationValue(a,"getBundleVersion",n.bundleVersion):null!==r&&changeConfigurationValue(a,"getBundleVersion",null==r?void 0:r.version),void 0!==n.input&&void 0!==n.input.actionNamePrivacy&&changeConfigurationValue(a,"getActionNamePrivacy",n.input.actionNamePrivacy),void 0!==n.errorHandler&&(changeConfigurationValue(a,"isErrorHandlerEnabled",n.errorHandler.enabled),changeConfigurationValue(a,"isReportFatalErrorAsCrash",n.errorHandler.reportFatalErrorAsCrash)),n.autoStart&&changeConfigurationValue(a,"isAutoStartupEnabled",n.autoStart),e=a.toSource({quote:"single"}),writeTransformation(e,t));return e},instrumentReactNavigation=(exports.instrument=instrument,function(e,t){return!!instrumentReactBaseNavigationContainer(e,t)&&(e="import { monitorNavigation } from '".concat(instrumentationLibraryFolder,"/react-navigation/ReactNavigation';"),t.find(jscodeshift.ImportDeclaration).at(0).insertBefore(e),!0)}),instrumentReactBaseNavigationContainer=function(e,t){var n=!1;return e.includes("@react-navigation")&&e.includes("core")&&(e.includes("BaseNavigationContainer.js")||e.includes("BaseNavigationContainer.tsx"))&&t.find(jscodeshift.VariableDeclarator,{id:{name:"getRootState"}}).forEach(function(e){n=!0,e.parent.insertAfter("monitorNavigation(getRootState);")}),n},addInfoToComponent=function(e){var t=e.findJSXElements(),r=!1;return 0<t.length&&(e.find(jscodeshift.FunctionDeclaration).forEach(function(e){var t,n=(0,Collection_1.fromPaths)([e]);0<n.findJSXElements().length&&null!=e&&null!=e.value&&null!=e.value.id&&e.value.id.name.toString()&&(t=n.find(jscodeshift.ClassDeclaration),n=n.find(jscodeshift.ClassExpression),0===t.length)&&0===n.length&&(insertExpressionIntoNextBody(e,Types_1.Types.FunctionalComponent,e.value.id.name.toString()),r=!0)}),e.find(jscodeshift.ClassDeclaration).forEach(function(e){0<(0,Collection_1.fromPaths)([e]).findJSXElements().length&&null!=e&&null!=e.value&&e.value.id&&e.value.id.name.toString()&&(insertExpressionIntoNextBody(e,Types_1.Types.ClassComponent,e.value.id.name.toString()),r=!0)}),e.find(jscodeshift.ArrowFunctionExpression).forEach(function(e){0<(0,Collection_1.fromPaths)([e]).findJSXElements().length&&null!=e.parent&&null!=e.parent.value&&null!=e.parent.value.id&&null!=e.parent.value.id.name&&(insertExpressionIntoNextBody(e,Types_1.Types.FunctionalComponent,e.parent.value.id.name),r=!0)}),e.find(jscodeshift.FunctionExpression).forEach(function(e){0<(0,Collection_1.fromPaths)([e]).findJSXElements().length&&null!=e.parent&&null!=e.parent.value&&null!=e.parent.value.id&&null!=e.parent.value.id.name&&(insertExpressionIntoNextBody(e,Types_1.Types.FunctionalComponent,e.parent.value.id.name),r=!0)})),r},insertExpressionIntoNextBody=function(e,t,n){for(t=jscodeshift.expressionStatement(jscodeshift.assignmentExpression("=",jscodeshift.memberExpression(jscodeshift.identifier(n),jscodeshift.identifier("_dtInfo")),createComponentInfo(t,n)));"body"!==(null==e?void 0:e.parentPath.name);)e=e.parentPath;void 0!==e.parentPath&&e.insertAfter(t)},createComponentInfo=function(e,t){return jscodeshift.objectExpression([jscodeshift.objectProperty(jscodeshift.identifier("type"),jscodeshift.numericLiteral(e)),jscodeshift.objectProperty(jscodeshift.identifier("name"),jscodeshift.stringLiteral(t))])},changeConfigurationValue=function(e,t,n){var e=e.find(jscodeshift.Identifier).filter(function(e){return e.node.name===t});1===e.length&&"ReturnStatement"===(e=e.paths()[0].parent.value.body.body[0]).type&&("boolean"==typeof n&&(e.argument=jscodeshift.booleanLiteral(n)),"string"==typeof n&&(e.argument=jscodeshift.stringLiteral(n)),"number"==typeof n)&&(e.argument=jscodeshift.numericLiteral(n))},parseSource=function(e,t){return jscodeshift.withParser((0,ParserUtil_1.chooseParser)(e,t))(t)},correctFilename=function(e){return nodePath.isAbsolute(e)?e.replace(PathsConstants_1.default.getApplicationPath()+nodePath.sep,""):e},deleteTransformation=function(e){try{var t=nodePath.join(PathsConstants_1.default.getBuildPath(),e+InstrumentUtil_1.INSTRUMENTED_FILE_EXTENSION);FileOperationHelper_1.default.checkIfFileExistsSync(t),FileOperationHelper_1.default.deleteFileSync(t)}catch(e){}},writeTransformation=function(e,t){t=nodePath.join(PathsConstants_1.default.getBuildPath(),t);try{FileOperationHelper_1.default.checkIfFileExistsSync(nodePath.dirname(t))}catch(e){FileOperationHelper_1.default.createDirectorySync(nodePath.dirname(t))}FileOperationHelper_1.default.writeTextToFileSync(t+InstrumentUtil_1.INSTRUMENTED_FILE_EXTENSION,e)},getInstrumentationList=function(e,t){var n={input:!1,lifecycle:!1};return void 0!==t&&(void 0!==t.lifecycle&&void 0!==t.lifecycle.instrument&&t.lifecycle.instrument(e)&&(n.lifecycle=!0),void 0!==t.input)&&void 0!==t.input.instrument&&t.input.instrument(e)&&(n.input=!0),n},addCreateElementInstrumentation=function(e){var t,e=e.find(jscodeshift.Program);1===e.length&&(t=jscodeshift.expressionStatement(jscodeshift.callExpression(jscodeshift.memberExpression(jscodeshift.callExpression(jscodeshift.identifier("require"),[jscodeshift.stringLiteral("@dynatrace/react-native-plugin/instrumentation/jsx/ElementHelper")]),jscodeshift.identifier("instrumentCreateElement")),[jscodeshift.memberExpression(jscodeshift.identifier("module"),jscodeshift.identifier("exports"))])),e.paths()[0].node.body.push(t))},addStartupCallRegistryImpl=function(e){var t=e.find(jscodeshift.FunctionDeclaration,{id:{name:"runApplication"}});return 1===t.length&&(addRequire(e,{customName:"_DynatraceApplicationHandler",module:"@dynatrace/react-native-plugin",reference:"ApplicationHandler"}),insertInArray(t.get().value.body.body,0,expressionStatement("_DynatraceApplicationHandler","startup",[])),!0)},addStartupCallRegistry=function(e){var t=e.find(jscodeshift.ObjectMethod,{key:{name:"runApplication"}});return 1===t.length&&(addRequire(e,{customName:"_DynatraceApplicationHandler",module:"@dynatrace/react-native-plugin",reference:"ApplicationHandler"}),insertInArray(t.get().value.body.body,0,expressionStatement("_DynatraceApplicationHandler","startup",[])),!0)},addReportErrorToDynatraceCall=function(e,n,r){var i=jscodeshift;e.find(i.FunctionDeclaration,{id:{name:"handleException"}}).forEach(function(e){var t=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(n),i.literal(r)]),t=i.expressionStatement(i.callExpression(i.identifier("setTimeout"),[i.arrowFunctionExpression([],i.blockStatement(e.node.body.body)),t]));e.node.body.body=[t]})},replaceReactWithDynatraceJsxRuntime=function(e){var t=!1,e=e.find(jscodeshift.CallExpression,{callee:{name:"require"}});return e.find(jscodeshift.Literal,{value:"react/jsx-runtime"}).replaceWith(function(e){e=e.node;return e.value="@dynatrace/react-native-plugin/jsx-runtime",t=!0,e}),e.find(jscodeshift.Literal,{value:"react/jsx-dev-runtime"}).replaceWith(function(e){e=e.node;return e.value="@dynatrace/react-native-plugin/jsx-dev-runtime",t=!0,e}),t},insertInArray=function(e,t){for(var n=arguments.length,r=new Array(2<n?n-2:0),i=2;i<n;i++)r[i-2]=arguments[i];return e.splice.apply(e,[t,0].concat(r))},shouldInstrumentFile=function(e){if(e.includes("@dynatrace"))return FileType.Filtered;var t=nodePath.extname(e);if(".js"!==t&&".ts"!==t&&".tsx"!==t&&".jsx"!==t)return FileType.Filtered;for(var n=nodePath.parse(e),r=n.dir.split(nodePath.sep),i=0;i<r.length;i++)if("node_modules"===r[i]){if("react-native"===r[i+1]||"create-react-class"===r[i+1]||"react-clone-referenced-element"===r[i+1])return whiteList.has(n.name)?FileType.ReactNative:FileType.Filtered;if("react"===r[i+1]&&"index"===n.name)return FileType.React;if("react-native-css-interop"===r[i+1]&&("jsx-runtime"===n.name||"jsx-dev-runtime"===n.name))return FileType.ReactNativeCssInterop}return FileType.Normal},handleImports=function(e,t,n){var r=handleDestructuredImport(e,t,n);return handleDefaultImport(e,t,n)||r},handleDestructuredImport=function(e,t,n){var r=findImportSpecifier(e,t);return 0<r.length&&(void 0!==(r=removeImportSpecifier(r,t.reference,!1))&&(n.customName=r.localName),addReference(e,n),!0)},handleDefaultImport=function(e,t,n){var r=findImportDeclaration(e,t.module);if(1===r.length){r=removeImportSpecifier(r,t.reference,!0);if(void 0!==r)return addDefaultImport(e,n.defaultImport,r.localName,"ImportNamespaceSpecifier"===r.type),!0}return!1},swapReferences=function(e,t){var n=JSON.parse(JSON.stringify(t.new));return{root:e,modified:handleImports(e,t.old,n)||modifyRequireModule(e,t.old,t.new.defaultImport)}},findImportSpecifier=function(e,t){return e.find(jscodeshift.ImportDeclaration).filter(function(e){return e.node.source.value===t.module&&null!=e.node.specifiers&&e.node.specifiers.some(function(e){return isImportSpecifier(e)&&e.imported.name===t.reference||e.local&&e.local.name===t.reference})})},isImportSpecifier=function(e){return void 0!==e.imported},modifyRequireModule=function(e,t,n){var r=!1;return e.find(jscodeshift.CallExpression).filter(function(e){return isRequire(e.node.callee)&&isArgumentALiteral(e.node.arguments[0])&&e.node.arguments[0].value===t.module&&void 0!==e.parent}).forEach(function(e){(void 0===e.parent.value.property||void 0!==e.parent.value.property&&void 0!==e.parent.value.property.name&&e.parent.value.property.name===t.reference)&&(e.node.arguments[0].value=n,r=r||!0)}),r},isRequire=function(e){return"require"===e.name},isArgumentALiteral=function(e){return"StringLiteral"===e.type||"Literal"===e.type},findImportDeclaration=function(e,t){return e.find(jscodeshift.ImportDeclaration).filter(function(e){return e.node.source.value===t})},removeImportSpecifier=function(e,n,r){var i;return e.forEach(function(e){void 0!==e.node.specifiers&&(e.node.specifiers=e.node.specifiers.filter(function(e){var t;return isImportSpecifier(e)&&!r?((t=e.imported.name!==n)||null==e.local||e.imported.name===e.local.name||(i={localName:e.local.name.toString(),type:e.type}),t):!(!isImportSpecifier(e)&&r&&(null!=e.local&&(i={localName:e.local.name.toString(),type:e.type}),1))}),0===e.node.specifiers.length)&&e.prune()}),i},insertImportSpecifier=function(e,t){e.find(jscodeshift.ImportDeclaration).filter(function(e){return e.node.source.value===t.module}).forEach(function(e){null!=e.node.specifiers&&e.node.specifiers.push(importSpecifier(t))})},insertImportDefaultSpecifier=function(e,t,n){e.find(jscodeshift.ImportDeclaration).filter(function(e){return e.node.source.value===t}).forEach(function(e){null!=e.node.specifiers&&e.node.specifiers.push(n)})},insertImportDeclaration=function(e,t,n){var r=e.find(jscodeshift.ImportDeclaration);0<r.length?jscodeshift(r.paths()[0]).insertAfter(importDeclaration(t,n)):1===(r=e.find(jscodeshift.Program)).length&&r.paths()[0].node.body.unshift(importDeclaration(t,n))},addReference=function(e,t){0<findImportDeclaration(e,t.module).length?insertImportSpecifier(e,t):insertImportDeclaration(e,t.module,[importSpecifier(t)])},addDefaultImport=function(e,t,n,r){var i=findImportDeclaration(e,t),r=(r?importNamespaceSpecifier:importDefaultSpecifier)(n);0<i.length?insertImportDefaultSpecifier(e,t,r):insertImportDeclaration(e,t,[r])},addRequire=function(e,t){e=e.find(jscodeshift.VariableDeclaration);0<e.length&&jscodeshift(e.paths()[0]).insertAfter(requireDeclaration(t))},expressionStatement=function(e,t,n){return jscodeshift.expressionStatement(callExpression(e,t,n))},callExpression=function(e,t,n){return jscodeshift.callExpression(memberExpression(e,t),n)},requireDeclaration=function(e){return jscodeshift.variableDeclaration("var",[requireDeclarator(e)])},requireDeclarator=function(e){return jscodeshift.variableDeclarator(void 0!==e.customName?jscodeshift.identifier(e.customName):jscodeshift.identifier(e.reference),(0<e.reference.length?memberExpressionRequire:requireExpression)(e))},memberExpressionRequire=function(e){return jscodeshift.memberExpression(requireExpression(e),jscodeshift.identifier(e.reference))},memberExpression=function(e,t){return jscodeshift.memberExpression(jscodeshift.identifier(e),jscodeshift.identifier(t))},requireExpression=function(e){return jscodeshift.callExpression(jscodeshift.identifier("require"),[jscodeshift.literal(e.module)])},importDeclaration=function(e,t){return jscodeshift.importDeclaration(t,jscodeshift.literal(e))},importSpecifier=function(e){return void 0!==e.customName?jscodeshift.importSpecifier(jscodeshift.identifier(e.reference),jscodeshift.identifier(e.customName)):jscodeshift.importSpecifier(jscodeshift.identifier(e.reference))},importDefaultSpecifier=function(e){return jscodeshift.importDefaultSpecifier(jscodeshift.identifier(e))},importNamespaceSpecifier=function(e){return jscodeshift.importNamespaceSpecifier(jscodeshift.identifier(e))};
|
|
1
|
+
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault"),_toConsumableArray2=_interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));function _createForOfIteratorHelper(e,t){var n,r,i,o,a="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(a)return i=!(r=!0),{s:function(){a=a.call(e)},n:function(){var e=a.next();return r=e.done,e},e:function(e){i=!0,n=e},f:function(){try{r||null==a.return||a.return()}finally{if(i)throw n}}};if(Array.isArray(e)||(a=_unsupportedIterableToArray(e))||t&&e&&"number"==typeof e.length)return a&&(e=a),o=0,{s:t=function(){},n:function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:t};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 _unsupportedIterableToArray(e,t){var n;if(e)return"string"==typeof e?_arrayLikeToArray(e,t):"Map"===(n="Object"===(n={}.toString.call(e).slice(8,-1))&&e.constructor?e.constructor.name:n)||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(e,t):void 0}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}Object.defineProperty(exports,"__esModule",{value:!0}),exports.instrument=void 0;var FileType,nodePath=require("path"),jscodeshift=require("jscodeshift"),Collection_1=require("jscodeshift/src/Collection"),FileOperationHelper_1=require("../scripts/FileOperationHelper"),PathsConstants_1=require("../scripts/PathsConstants"),GetValuesFromPackage_1=require("../lib/core/util/GetValuesFromPackage"),InstrumentUtil_1=require("../scripts/util/InstrumentUtil"),Run_1=require("../lib/features/ui-interaction/Run"),Touchables_InstrInfo_1=require("./libs/react-native/Touchables.InstrInfo"),RefreshControl_InstrInfo_1=require("./libs/react-native/RefreshControl.InstrInfo"),Switch_InstrInfo_1=require("./libs/react-native/Switch.InstrInfo"),Touchables_InstrInfo_2=require("./libs/community/gesture-handler/Touchables.InstrInfo"),Picker_InstrInfo_1=require("./libs/community/Picker.InstrInfo"),Types_1=require("./model/Types"),ParserUtil_1=require("./parser/ParserUtil"),referenceListInput=((e=>{e[e.Filtered=-1]="Filtered",e[e.Normal=0]="Normal",e[e.ReactNative=1]="ReactNative",e[e.React=2]="React",e[e.ReactNativeCssInterop=3]="ReactNativeCssInterop"})(FileType=FileType||{}),[]),whiteList=(referenceListInput.push.apply(referenceListInput,(0,_toConsumableArray2.default)(Touchables_InstrInfo_1.instrumentationInfo)),referenceListInput.push.apply(referenceListInput,(0,_toConsumableArray2.default)(RefreshControl_InstrInfo_1.instrumentationInfo)),referenceListInput.push.apply(referenceListInput,(0,_toConsumableArray2.default)(Switch_InstrInfo_1.instrumentationInfo)),referenceListInput.push.apply(referenceListInput,(0,_toConsumableArray2.default)(Touchables_InstrInfo_2.instrumentationInfo)),referenceListInput.push.apply(referenceListInput,(0,_toConsumableArray2.default)(Picker_InstrInfo_1.instrumentationInfo)),new Set(["AppRegistry","AppRegistryImpl","renderApplication","ExceptionsManager"])),instrumentationLibraryFolder="@dynatrace/react-native-plugin/instrumentation/libs",instrument=function(e,t,n){t=correctFilename(t);var r=shouldInstrumentFile(t);if(r!==FileType.Filtered){var i=!1,o=parseSource(t,e);if(r===FileType.React)addCreateElementInstrumentation(o),i=!0;else if(r===FileType.ReactNative)t.endsWith("AppRegistryImpl.js")?null!=n&&n.autoStart&&addStartupCallRegistryImpl(o)&&(i=!0):t.endsWith("AppRegistry.js")?null!=n&&n.autoStart&&addStartupCallRegistry(o)&&(i=!0):t.endsWith("renderApplication.js")?(addInfoToComponent(o),i=!0):t.endsWith("ExceptionsManager.js")&&(a=void 0!==n&&n.autoStart&&n.errorHandler.enabled,addReportErrorToDynatraceCall(o,n.errorHandler.reportFatalErrorAsCrash,a),i=!0);else if(r===FileType.ReactNativeCssInterop)i=replaceReactWithDynatraceJsxRuntime(o)||i;else{var a=getInstrumentationList(t,n),r=[{isEnabled:function(e,t){return!0===(null==t?void 0:t.userInteraction)},run:function(e,t,n){return(0,Run_1.runDTUserInteraction)(e,t,n)}}].filter(function(e){return e.isEnabled(t,n)});if(n.navigation.enabled&&instrumentReactNavigation(t,o))i=!0;else{if(!a.input&&!a.lifecycle&&0===r.length)return null!=n&&n.debug&&console.log("Dynatrace - Filtered All: ".concat(t)),deleteTransformation(t),e;a.lifecycle&&addInfoToComponent(o)&&(i=!0),a.input&&referenceListInput.forEach(function(e){e=swapReferences(o,e);o=e.root,i=i||e.modified})}var s,l=_createForOfIteratorHelper(r);try{for(l.s();!(s=l.n()).done;){var c=s.value;try{var u=c.run(o,t,n),o=u.root;u.modified&&(i=!0)}catch(e){var f=e instanceof Error?e.stack||e.message:String(e);null!=n&&n.debug&&console.log("[DynatraceInstrumentationRaw]: Feature instrumentation failed for ".concat(t,": ").concat(f))}}}catch(e){l.e(e)}finally{l.f()}}var a=i?o.toSource({quote:"single"}):e;i?writeTransformation(e=a,t):deleteTransformation(t),null!=n&&n.debug&&i&&console.log("Dynatrace - Modified Filename: "+t)}else t.includes(nodePath.join("@dynatrace","react-native-plugin"))&&t.endsWith(nodePath.join("lib","core","configuration","ConfigurationPreset.js"))&&void 0!==n&&(r=(0,GetValuesFromPackage_1.getHostAppBundleInfo)(PathsConstants_1.default.getPackageJsonFile()),a=parseSource(t,e),void 0!==n.lifecycle&&changeConfigurationValue(a,"getLifecycleUpdate",n.lifecycle.includeUpdate),void 0!==n.debug&&changeConfigurationValue(a,"getLogLevel",n.debug?0:1),void 0!==n.bundleName?changeConfigurationValue(a,"getBundleName",n.bundleName):null!==r&&changeConfigurationValue(a,"getBundleName",null==r?void 0:r.name),void 0!==n.bundleVersion?changeConfigurationValue(a,"getBundleVersion",n.bundleVersion):null!==r&&changeConfigurationValue(a,"getBundleVersion",null==r?void 0:r.version),void 0!==(null==(r=n.input)?void 0:r.actionNamePrivacy)&&changeConfigurationValue(a,"getActionNamePrivacy",n.input.actionNamePrivacy),void 0!==(null==(r=n.input)?void 0:r.actionNamePreference)&&changeConfigurationValue(a,"getActionNamePreference",n.input.actionNamePreference),void 0!==(null==(r=n.input)?void 0:r.actionNameAlgorithm)&&changeConfigurationValue(a,"getActionNameAlgorithm",n.input.actionNameAlgorithm),void 0!==n.errorHandler&&(changeConfigurationValue(a,"isErrorHandlerEnabled",n.errorHandler.enabled),changeConfigurationValue(a,"isReportFatalErrorAsCrash",n.errorHandler.reportFatalErrorAsCrash)),n.autoStart&&changeConfigurationValue(a,"isAutoStartupEnabled",n.autoStart),e=a.toSource({quote:"single"}),writeTransformation(e,t));return e},instrumentReactNavigation=(exports.instrument=instrument,function(e,t){return!!instrumentReactBaseNavigationContainer(e,t)&&(e="import { monitorNavigation } from '".concat(instrumentationLibraryFolder,"/react-navigation/ReactNavigation';"),t.find(jscodeshift.ImportDeclaration).at(0).insertBefore(e),!0)}),instrumentReactBaseNavigationContainer=function(e,t){var n=!1;return e.includes("@react-navigation")&&e.includes("core")&&(e.includes("BaseNavigationContainer.js")||e.includes("BaseNavigationContainer.tsx"))&&t.find(jscodeshift.VariableDeclarator,{id:{name:"getRootState"}}).forEach(function(e){n=!0,e.parent.insertAfter("monitorNavigation(getRootState);")}),n},addInfoToComponent=function(e){var t=e.findJSXElements(),r=!1;return 0<t.length&&(e.find(jscodeshift.FunctionDeclaration).forEach(function(e){var t,n=(0,Collection_1.fromPaths)([e]);0<n.findJSXElements().length&&null!=e&&null!=e.value&&null!=e.value.id&&e.value.id.name.toString()&&(t=n.find(jscodeshift.ClassDeclaration),n=n.find(jscodeshift.ClassExpression),0===t.length)&&0===n.length&&(insertExpressionIntoNextBody(e,Types_1.Types.FunctionalComponent,e.value.id.name.toString()),r=!0)}),e.find(jscodeshift.ClassDeclaration).forEach(function(e){0<(0,Collection_1.fromPaths)([e]).findJSXElements().length&&null!=e&&null!=e.value&&e.value.id&&e.value.id.name.toString()&&(insertExpressionIntoNextBody(e,Types_1.Types.ClassComponent,e.value.id.name.toString()),r=!0)}),e.find(jscodeshift.ArrowFunctionExpression).forEach(function(e){0<(0,Collection_1.fromPaths)([e]).findJSXElements().length&&null!=e.parent&&null!=e.parent.value&&null!=e.parent.value.id&&null!=e.parent.value.id.name&&(insertExpressionIntoNextBody(e,Types_1.Types.FunctionalComponent,e.parent.value.id.name),r=!0)}),e.find(jscodeshift.FunctionExpression).forEach(function(e){0<(0,Collection_1.fromPaths)([e]).findJSXElements().length&&null!=e.parent&&null!=e.parent.value&&null!=e.parent.value.id&&null!=e.parent.value.id.name&&(insertExpressionIntoNextBody(e,Types_1.Types.FunctionalComponent,e.parent.value.id.name),r=!0)})),r},insertExpressionIntoNextBody=function(e,t,n){for(t=jscodeshift.expressionStatement(jscodeshift.assignmentExpression("=",jscodeshift.memberExpression(jscodeshift.identifier(n),jscodeshift.identifier("_dtInfo")),createComponentInfo(t,n)));"body"!==(null==e?void 0:e.parentPath.name);)e=e.parentPath;void 0!==e.parentPath&&e.insertAfter(t)},createComponentInfo=function(e,t){return jscodeshift.objectExpression([jscodeshift.objectProperty(jscodeshift.identifier("type"),jscodeshift.numericLiteral(e)),jscodeshift.objectProperty(jscodeshift.identifier("name"),jscodeshift.stringLiteral(t))])},changeConfigurationValue=function(e,t,n){var e=e.find(jscodeshift.Identifier).filter(function(e){return e.node.name===t});1===e.length&&"ReturnStatement"===(e=e.paths()[0].parent.value.body.body[0]).type&&("boolean"==typeof n&&(e.argument=jscodeshift.booleanLiteral(n)),"string"==typeof n&&(e.argument=jscodeshift.stringLiteral(n)),"number"==typeof n)&&(e.argument=jscodeshift.numericLiteral(n))},parseSource=function(e,t){return jscodeshift.withParser((0,ParserUtil_1.chooseParser)(e,t))(t)},correctFilename=function(e){return nodePath.isAbsolute(e)?e.replace(PathsConstants_1.default.getApplicationPath()+nodePath.sep,""):e},deleteTransformation=function(e){try{var t=nodePath.join(PathsConstants_1.default.getBuildPath(),e+InstrumentUtil_1.INSTRUMENTED_FILE_EXTENSION);FileOperationHelper_1.default.checkIfFileExistsSync(t),FileOperationHelper_1.default.deleteFileSync(t)}catch(e){}},writeTransformation=function(e,t){t=nodePath.join(PathsConstants_1.default.getBuildPath(),t);try{FileOperationHelper_1.default.checkIfFileExistsSync(nodePath.dirname(t))}catch(e){FileOperationHelper_1.default.createDirectorySync(nodePath.dirname(t))}FileOperationHelper_1.default.writeTextToFileSync(t+InstrumentUtil_1.INSTRUMENTED_FILE_EXTENSION,e)},getInstrumentationList=function(e,t){var n={input:!1,lifecycle:!1};return void 0!==t&&(void 0!==t.lifecycle&&void 0!==t.lifecycle.instrument&&t.lifecycle.instrument(e)&&(n.lifecycle=!0),void 0!==t.input)&&void 0!==t.input.instrument&&t.input.instrument(e)&&(n.input=!0),n},addCreateElementInstrumentation=function(e){var t,e=e.find(jscodeshift.Program);1===e.length&&(t=jscodeshift.expressionStatement(jscodeshift.callExpression(jscodeshift.memberExpression(jscodeshift.callExpression(jscodeshift.identifier("require"),[jscodeshift.stringLiteral("@dynatrace/react-native-plugin/instrumentation/jsx/ElementHelper")]),jscodeshift.identifier("instrumentCreateElement")),[jscodeshift.memberExpression(jscodeshift.identifier("module"),jscodeshift.identifier("exports"))])),e.paths()[0].node.body.push(t))},addStartupCallRegistryImpl=function(e){var t=e.find(jscodeshift.FunctionDeclaration,{id:{name:"runApplication"}});return 1===t.length&&(addRequire(e,{customName:"_DynatraceApplicationHandler",module:"@dynatrace/react-native-plugin",reference:"ApplicationHandler"}),insertInArray(t.get().value.body.body,0,expressionStatement("_DynatraceApplicationHandler","startup",[])),!0)},addStartupCallRegistry=function(e){var t=e.find(jscodeshift.ObjectMethod,{key:{name:"runApplication"}});return 1===t.length&&(addRequire(e,{customName:"_DynatraceApplicationHandler",module:"@dynatrace/react-native-plugin",reference:"ApplicationHandler"}),insertInArray(t.get().value.body.body,0,expressionStatement("_DynatraceApplicationHandler","startup",[])),!0)},addReportErrorToDynatraceCall=function(e,n,r){var i=jscodeshift;e.find(i.FunctionDeclaration,{id:{name:"handleException"}}).forEach(function(e){var t=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(n),i.literal(r)]),t=i.expressionStatement(i.callExpression(i.identifier("setTimeout"),[i.arrowFunctionExpression([],i.blockStatement(e.node.body.body)),t]));e.node.body.body=[t]})},replaceReactWithDynatraceJsxRuntime=function(e){var t=!1,e=e.find(jscodeshift.CallExpression,{callee:{name:"require"}});return e.find(jscodeshift.Literal,{value:"react/jsx-runtime"}).replaceWith(function(e){e=e.node;return e.value="@dynatrace/react-native-plugin/jsx-runtime",t=!0,e}),e.find(jscodeshift.Literal,{value:"react/jsx-dev-runtime"}).replaceWith(function(e){e=e.node;return e.value="@dynatrace/react-native-plugin/jsx-dev-runtime",t=!0,e}),t},insertInArray=function(e,t){for(var n=arguments.length,r=new Array(2<n?n-2:0),i=2;i<n;i++)r[i-2]=arguments[i];return e.splice.apply(e,[t,0].concat(r))},shouldInstrumentFile=function(e){if(e.includes("@dynatrace"))return FileType.Filtered;var t=nodePath.extname(e);if(".js"!==t&&".ts"!==t&&".tsx"!==t&&".jsx"!==t)return FileType.Filtered;for(var n=nodePath.parse(e),r=n.dir.split(nodePath.sep),i=0;i<r.length;i++)if("node_modules"===r[i]){if("react-native"===r[i+1]||"create-react-class"===r[i+1]||"react-clone-referenced-element"===r[i+1])return whiteList.has(n.name)?FileType.ReactNative:FileType.Filtered;if("react"===r[i+1]&&"index"===n.name)return FileType.React;if("react-native-css-interop"===r[i+1]&&("jsx-runtime"===n.name||"jsx-dev-runtime"===n.name))return FileType.ReactNativeCssInterop}return FileType.Normal},handleImports=function(e,t,n){var r=handleDestructuredImport(e,t,n);return handleDefaultImport(e,t,n)||r},handleDestructuredImport=function(e,t,n){var r=findImportSpecifier(e,t);return 0<r.length&&(void 0!==(r=removeImportSpecifier(r,t.reference,!1))&&(n.customName=r.localName),addReference(e,n),!0)},handleDefaultImport=function(e,t,n){var r=findImportDeclaration(e,t.module);if(1===r.length){r=removeImportSpecifier(r,t.reference,!0);if(void 0!==r)return addDefaultImport(e,n.defaultImport,r.localName,"ImportNamespaceSpecifier"===r.type),!0}return!1},swapReferences=function(e,t){var n=JSON.parse(JSON.stringify(t.new));return{root:e,modified:handleImports(e,t.old,n)||modifyRequireModule(e,t.old,t.new.defaultImport)}},findImportSpecifier=function(e,t){return e.find(jscodeshift.ImportDeclaration).filter(function(e){return e.node.source.value===t.module&&null!=e.node.specifiers&&e.node.specifiers.some(function(e){return isImportSpecifier(e)&&e.imported.name===t.reference||e.local&&e.local.name===t.reference})})},isImportSpecifier=function(e){return void 0!==e.imported},modifyRequireModule=function(e,t,n){var r=!1;return e.find(jscodeshift.CallExpression).filter(function(e){return isRequire(e.node.callee)&&isArgumentALiteral(e.node.arguments[0])&&e.node.arguments[0].value===t.module&&void 0!==e.parent}).forEach(function(e){(void 0===e.parent.value.property||void 0!==e.parent.value.property&&void 0!==e.parent.value.property.name&&e.parent.value.property.name===t.reference)&&(e.node.arguments[0].value=n,r=r||!0)}),r},isRequire=function(e){return"require"===e.name},isArgumentALiteral=function(e){return"StringLiteral"===e.type||"Literal"===e.type},findImportDeclaration=function(e,t){return e.find(jscodeshift.ImportDeclaration).filter(function(e){return e.node.source.value===t})},removeImportSpecifier=function(e,n,r){var i;return e.forEach(function(e){void 0!==e.node.specifiers&&(e.node.specifiers=e.node.specifiers.filter(function(e){var t;return isImportSpecifier(e)&&!r?((t=e.imported.name!==n)||null==e.local||e.imported.name===e.local.name||(i={localName:e.local.name.toString(),type:e.type}),t):!(!isImportSpecifier(e)&&r&&(null!=e.local&&(i={localName:e.local.name.toString(),type:e.type}),1))}),0===e.node.specifiers.length)&&e.prune()}),i},insertImportSpecifier=function(e,t){e.find(jscodeshift.ImportDeclaration).filter(function(e){return e.node.source.value===t.module}).forEach(function(e){null!=e.node.specifiers&&e.node.specifiers.push(importSpecifier(t))})},insertImportDefaultSpecifier=function(e,t,n){e.find(jscodeshift.ImportDeclaration).filter(function(e){return e.node.source.value===t}).forEach(function(e){null!=e.node.specifiers&&e.node.specifiers.push(n)})},insertImportDeclaration=function(e,t,n){var r=e.find(jscodeshift.ImportDeclaration);0<r.length?jscodeshift(r.paths()[0]).insertAfter(importDeclaration(t,n)):1===(r=e.find(jscodeshift.Program)).length&&r.paths()[0].node.body.unshift(importDeclaration(t,n))},addReference=function(e,t){0<findImportDeclaration(e,t.module).length?insertImportSpecifier(e,t):insertImportDeclaration(e,t.module,[importSpecifier(t)])},addDefaultImport=function(e,t,n,r){var i=findImportDeclaration(e,t),r=(r?importNamespaceSpecifier:importDefaultSpecifier)(n);0<i.length?insertImportDefaultSpecifier(e,t,r):insertImportDeclaration(e,t,[r])},addRequire=function(e,t){e=e.find(jscodeshift.VariableDeclaration);0<e.length&&jscodeshift(e.paths()[0]).insertAfter(requireDeclaration(t))},expressionStatement=function(e,t,n){return jscodeshift.expressionStatement(callExpression(e,t,n))},callExpression=function(e,t,n){return jscodeshift.callExpression(memberExpression(e,t),n)},requireDeclaration=function(e){return jscodeshift.variableDeclaration("var",[requireDeclarator(e)])},requireDeclarator=function(e){return jscodeshift.variableDeclarator(void 0!==e.customName?jscodeshift.identifier(e.customName):jscodeshift.identifier(e.reference),(0<e.reference.length?memberExpressionRequire:requireExpression)(e))},memberExpressionRequire=function(e){return jscodeshift.memberExpression(requireExpression(e),jscodeshift.identifier(e.reference))},memberExpression=function(e,t){return jscodeshift.memberExpression(jscodeshift.identifier(e),jscodeshift.identifier(t))},requireExpression=function(e){return jscodeshift.callExpression(jscodeshift.identifier("require"),[jscodeshift.literal(e.module)])},importDeclaration=function(e,t){return jscodeshift.importDeclaration(t,jscodeshift.literal(e))},importSpecifier=function(e){return void 0!==e.customName?jscodeshift.importSpecifier(jscodeshift.identifier(e.reference),jscodeshift.identifier(e.customName)):jscodeshift.importSpecifier(jscodeshift.identifier(e.reference))},importDefaultSpecifier=function(e){return jscodeshift.importDefaultSpecifier(jscodeshift.identifier(e))},importNamespaceSpecifier=function(e){return jscodeshift.importNamespaceSpecifier(jscodeshift.identifier(e))};
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
var _a, _b;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
require("proxy-polyfill");
|
|
5
|
+
const PickerRN = require("@react-native-picker/picker");
|
|
5
6
|
const Types_1 = require("../../model/Types");
|
|
6
|
-
const PickerRN = require('@react-native-picker/picker');
|
|
7
7
|
const dynatraceProxy = new Proxy(PickerRN, {
|
|
8
8
|
get: (target, property) => {
|
|
9
9
|
if (dynatraceInstrument[property] !== undefined) {
|
|
@@ -6,6 +6,7 @@ const react_native_1 = require("react-native");
|
|
|
6
6
|
const ConsoleLogger_1 = require("../../../lib/core/logging/ConsoleLogger");
|
|
7
7
|
const DynatraceBridge_1 = require("../../../lib/core/DynatraceBridge");
|
|
8
8
|
const BaseDataEventModifier_1 = require("../../../lib/next/events/modifier/BaseDataEventModifier");
|
|
9
|
+
const ConfigurationHandler_1 = require("../../../lib/core/configuration/ConfigurationHandler");
|
|
9
10
|
const logger = new ConsoleLogger_1.ConsoleLogger('ReactNavigation');
|
|
10
11
|
let activePath = '';
|
|
11
12
|
let appState = react_native_1.AppState.currentState;
|
|
@@ -44,6 +45,10 @@ const monitorNavigation = (getRootState) => {
|
|
|
44
45
|
};
|
|
45
46
|
exports.monitorNavigation = monitorNavigation;
|
|
46
47
|
const startView = (newPath) => {
|
|
48
|
+
if (!ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) {
|
|
49
|
+
logger.info('React Native plugin has not been started yet! Navigation will not be reported!');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
47
52
|
const startViewInternalEvent = new BaseDataEventModifier_1.BaseDataEventModifier().modifyEvent(Object.assign({ 'view.detected_name': newPath }, (activePath && {
|
|
48
53
|
'view.source.detected_name': activePath,
|
|
49
54
|
})));
|
|
@@ -54,6 +59,10 @@ const startView = (newPath) => {
|
|
|
54
59
|
logger.debug(`startViewinternal(${JSON.stringify(startViewInternalEvent)})`);
|
|
55
60
|
};
|
|
56
61
|
const stopView = () => {
|
|
62
|
+
if (!ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) {
|
|
63
|
+
logger.info('React Native plugin has not been started yet! Navigation will not be reported!');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
57
66
|
const fn = DynatraceBridge_1.DynatraceNative === null || DynatraceBridge_1.DynatraceNative === void 0 ? void 0 : DynatraceBridge_1.DynatraceNative.stopViewInternal;
|
|
58
67
|
if (typeof fn === 'function') {
|
|
59
68
|
fn();
|