@dynatrace/react-native-plugin 2.333.1 → 2.337.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 +181 -232
- package/android/build.gradle +1 -1
- package/files/plugin-runtime.gradle +27 -13
- package/files/plugin.gradle +1 -1
- package/instrumentation/BabelPluginDynatrace.js +1 -0
- package/instrumentation/DynatraceInstrumentation.js +1 -1
- package/instrumentation/jsx/JsxRuntime.js +4 -4
- package/instrumentation/libs/UserInteraction.js +114 -0
- package/instrumentation/libs/community/Picker.js +1 -1
- package/instrumentation/libs/community/gesture-handler/Touchables.InstrInfo.js +2 -0
- package/instrumentation/libs/community/gesture-handler/Touchables.js +3 -1
- package/instrumentation/libs/community/gesture-handler/index.js +3 -1
- package/instrumentation/libs/react-navigation/ReactNavigation.js +9 -0
- package/instrumentation/libs/withOnPressMonitoring.js +65 -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/dynatrace-reporter.js +0 -14
- package/lib/dynatrace-transformer.js +10 -13
- package/lib/features/ui-interaction/Config.js +8 -2
- package/lib/features/ui-interaction/Plugin.Fragment.Test.js +170 -0
- package/lib/features/ui-interaction/Plugin.js +226 -882
- package/lib/features/ui-interaction/Run.js +11 -7
- package/lib/features/ui-interaction/Runtime.js +258 -913
- package/lib/features/ui-interaction/TouchMetaResolver.js +492 -0
- package/lib/features/ui-interaction/Types.js +1 -62
- 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 +8 -10
- package/react-native-dynatrace.podspec +1 -1
- package/scripts/Android.js +96 -66
- package/scripts/Config.js +11 -1
- package/scripts/Ios.js +288 -71
- package/scripts/PathsConstants.js +34 -20
- package/scripts/core/InstrumentCall.js +8 -3
- package/scripts/core/LineOffsetAnalyzeCall.js +9 -15
- package/scripts/util/SourceMapUtil.js +49 -11
- package/types.d.ts +178 -39
- package/scripts/util/ReactOptions.js +0 -21
package/README.md
CHANGED
|
@@ -10,9 +10,10 @@ 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
|
+
* Tracking navigation via `react.navigation.enabled`
|
|
16
17
|
* UI Interaction feature toggle via `react.userInteraction` (enable/disable user interaction capturing at runtime)
|
|
17
18
|
* Manual instrumentation
|
|
18
19
|
* Typescript bindings to add manual instrumentation
|
|
@@ -32,18 +33,18 @@ If you want to start using this plugin and are not a Dynatrace customer yet, hea
|
|
|
32
33
|
* NodeJS 16.0.0+ since our dependencies require NodeJS 16.0.0
|
|
33
34
|
|
|
34
35
|
## Agent Versions
|
|
35
|
-
|
|
36
|
+
These agent versions are configured in this plugin:
|
|
36
37
|
|
|
37
|
-
* Android Agent: 8.
|
|
38
|
-
* iOS Agent: 8.
|
|
38
|
+
* Android Agent: 8.337.2.1010
|
|
39
|
+
* iOS Agent: 8.337.1.1003
|
|
39
40
|
|
|
40
41
|
## Quick Setup
|
|
41
42
|
|
|
42
43
|
1. [Install plugin](#1-install-the-plugin)
|
|
43
|
-
2. [
|
|
44
|
-
3. [
|
|
45
|
-
4. [
|
|
46
|
-
5. [Build and run your app](#
|
|
44
|
+
2. [Setup configuration](#2-setup-dynatraceconfigjs)
|
|
45
|
+
3. [Register babel plugin](#3-register-our-babel-plugin-in-babelconfigjs)
|
|
46
|
+
4. [Register jsx-runtime](#4-register-our-jsx-runtime-in-babelconfigjs)
|
|
47
|
+
5. [Build and run your app](#5-build-and-run-your-app)
|
|
47
48
|
|
|
48
49
|
## Advanced topics
|
|
49
50
|
* [Manual OneAgent Startup](#manual-oneagent-startup)
|
|
@@ -72,7 +73,6 @@ This agent versions are configured in this plugin:
|
|
|
72
73
|
* [Send Exception Event](#send-exception-event)
|
|
73
74
|
* [Send HTTP Request Event](#send-http-request-event)
|
|
74
75
|
* [View Monitoring](#view-monitoring)
|
|
75
|
-
* [User Interaction](#user-interaction-1)
|
|
76
76
|
* [React Native Symbolication](#react-native-symbolication)
|
|
77
77
|
* [NPX Commands](#npx-commands)
|
|
78
78
|
* [npx instrumentDynatrace](#npx-instrumentdynatrace)
|
|
@@ -92,7 +92,9 @@ This agent versions are configured in this plugin:
|
|
|
92
92
|
* [Bundle Name and Version](#bundle-name-and-version)
|
|
93
93
|
* [Navigation](#navigation)
|
|
94
94
|
* [Source Map](#source-map)
|
|
95
|
-
* [User Interaction](#user-interaction-
|
|
95
|
+
* [User Interaction Configuration](#user-interaction-configuration)
|
|
96
|
+
* [Debugging our auto-instrumentation](#debugging-our-auto-instrumentation)
|
|
97
|
+
* [Using our legacy jscodeshift auto-instrumentation](#using-our-legacy-jscodeshift-auto-instrumentation)
|
|
96
98
|
* [Android block](#android-block)
|
|
97
99
|
* [iOS block](#ios-block)
|
|
98
100
|
* [Lifecycle modes](#lifecycle)
|
|
@@ -125,9 +127,7 @@ This agent versions are configured in this plugin:
|
|
|
125
127
|
> **Note**: If you are upgrading to React Native v0.70 (or newer) or using the @react-native-community/cli 9.x+ version, be aware that our automated script running before every start/run-android/run-ios command is no longer working. When your *dynatrace.config.js* changed be sure to execute `npx instrumentDynatrace` beforehand.
|
|
126
128
|
|
|
127
129
|
## 1. Install the plugin
|
|
128
|
-
1. Install the plugin by calling
|
|
129
|
-
- React Native v0.60 or newer : `npm install @dynatrace/react-native-plugin`
|
|
130
|
-
- React Native v0.59.x : `react-native install @dynatrace/react-native-plugin`.
|
|
130
|
+
1. Install the plugin by calling `npm install @dynatrace/react-native-plugin`
|
|
131
131
|
2. **iOS only :** If you use pods, you need to go into your `ios` directory and execute `pod install` to install the new Dynatrace dependency to your xCode project.
|
|
132
132
|
|
|
133
133
|
### Troubleshooting
|
|
@@ -135,81 +135,36 @@ This agent versions are configured in this plugin:
|
|
|
135
135
|
- Standalone Project: If you are using React Native standalone and embed it in your native project have a look [here](#configuration-of-standalone-react-native-project).
|
|
136
136
|
- If for some reason (e.g. seperate native projects) `react-native link` doesn't work as expected, [manually add the iOS agent to your project](#manually-adding-ios-oneagent-to-a-project).
|
|
137
137
|
|
|
138
|
-
## 2.
|
|
138
|
+
## 2. Setup dynatrace.config.js
|
|
139
139
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
Depending on your React Native version, you will need to use a different way to register the transformer. If you don't know the version, enter `react-native --version` in your terminal.
|
|
143
|
-
|
|
144
|
-
The following configuration must be added. If you already have a babel transformer (babelTransformerPath) in place, you need to [use the upstreamTransformer property in dynatrace.config.js](#using-a-second-transformer-besides-the-dynatrace-transformer) to use a transformer besides our dynatrace transformer.
|
|
145
|
-
|
|
146
|
-
In your project's root directory, create or extend `metro.config.js` so that it contains the following configuration properties `transformer.babelTransformerPath` and `reporter`:
|
|
147
|
-
|
|
148
|
-
#### For React Native v0.72.1 or newer
|
|
149
|
-
|
|
150
|
-
```js
|
|
151
|
-
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
|
|
152
|
-
const defaultConfig = getDefaultConfig(__dirname);
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Metro configuration
|
|
156
|
-
* https://facebook.github.io/metro/docs/configuration
|
|
157
|
-
*
|
|
158
|
-
* @type {import('metro-config').MetroConfig}
|
|
159
|
-
*/
|
|
160
|
-
const config = {
|
|
161
|
-
transformer: {
|
|
162
|
-
babelTransformerPath: require.resolve(
|
|
163
|
-
'@dynatrace/react-native-plugin/lib/dynatrace-transformer',
|
|
164
|
-
),
|
|
165
|
-
},
|
|
166
|
-
reporter: require('@dynatrace/react-native-plugin/lib/dynatrace-reporter'),
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
module.exports = mergeConfig(defaultConfig, config);
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
#### For Expo
|
|
140
|
+
> **Note**: If you are upgrading from a previous version of this plugin, you'll notice that the file format has changed. Your old configuration is still available in `dynatrace.config` and you have to copy your values to the new `dynatrace.config.js`.
|
|
173
141
|
|
|
174
|
-
|
|
175
|
-
const {getDefaultConfig} = require('expo/metro-config');
|
|
176
|
-
const config = getDefaultConfig(__dirname);
|
|
142
|
+
Define a mobile app in Dynatrace and open the Mobile app instrumentation settings. In the settings you will see a `dynatrace.config.js` file which can be downloaded for React Native. Download and copy this file into the root folder of your application. If you are not sure you can always use `npx configDynatrace` to create a default configuration file.
|
|
177
143
|
|
|
178
|
-
|
|
179
|
-
'@dynatrace/react-native-plugin/lib/dynatrace-transformer',
|
|
180
|
-
);
|
|
144
|
+
> **Note**: Define the components that you want to see lifecycle instrumented ([example](#lifecycle)). This is important as you will only see Application startup and Touches out of the box.
|
|
181
145
|
|
|
182
|
-
|
|
146
|
+
For more details about the configuration, see [Advanced topics](#structure-of-the-dynatracejs-file).
|
|
183
147
|
|
|
184
|
-
|
|
185
|
-
```
|
|
148
|
+
## 3. Register our babel plugin in babel.config.js
|
|
186
149
|
|
|
187
|
-
|
|
150
|
+
Add the Dynatrace babel plugin to your `babel.config.js`:
|
|
188
151
|
|
|
189
152
|
```js
|
|
190
153
|
module.exports = {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
'@dynatrace/react-native-plugin/lib/dynatrace-transformer'
|
|
194
|
-
)
|
|
195
|
-
},
|
|
196
|
-
reporter: require('@dynatrace/react-native-plugin/lib/dynatrace-reporter'),
|
|
154
|
+
...
|
|
155
|
+
plugins: [..., '@dynatrace/react-native-plugin/instrumentation/BabelPluginDynatrace'],
|
|
197
156
|
};
|
|
198
157
|
```
|
|
199
158
|
|
|
200
|
-
|
|
159
|
+
This plugin handles the auto-instrumentation of your React Native code at build time.
|
|
201
160
|
|
|
202
|
-
> **Note**:
|
|
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.
|
|
203
162
|
|
|
204
|
-
|
|
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.
|
|
205
164
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
For more details about the configuration, see [Advanced topics](#structure-of-the-dynatracejs-file).
|
|
165
|
+
## 4. Register our jsx-runtime in babel.config.js
|
|
209
166
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
Depending on your version of Metro or Expo (if used), your babel configuration `babel.config.js` will need to be updated.
|
|
167
|
+
Depending on your version of Metro or Expo (if used), you additionally need to add our jsx-runtime to your babel configuration `babel.config.js`.
|
|
213
168
|
|
|
214
169
|
The changes have to be done in the following cases:
|
|
215
170
|
|
|
@@ -303,7 +258,9 @@ configurationBuilder.withCrashReporting(true)
|
|
|
303
258
|
.withLogLevel(LogLevel.Info)
|
|
304
259
|
.withLifecycleUpdate(false)
|
|
305
260
|
.withUserOptIn(false)
|
|
306
|
-
.withActionNamePrivacy(false)
|
|
261
|
+
.withActionNamePrivacy(false)
|
|
262
|
+
.withActionNamePreference('any')
|
|
263
|
+
.withActionNameAlgorithm('depth-first');
|
|
307
264
|
|
|
308
265
|
await Dynatrace.start(configurationBuilder.buildConfiguration());
|
|
309
266
|
```
|
|
@@ -320,7 +277,9 @@ await Dynatrace.start(configurationBuilder.buildConfiguration());
|
|
|
320
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.|
|
|
321
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.|
|
|
322
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`.|
|
|
323
|
-
|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.|
|
|
324
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.
|
|
325
284
|
|
|
326
285
|
**Attention:**
|
|
@@ -699,7 +658,7 @@ myAction.leaveAction();
|
|
|
699
658
|
|
|
700
659
|
With `sendBizEvent`, you can report business events. These events are standalone events, as OneAgent sends them detached from user actions or user sessions.
|
|
701
660
|
|
|
702
|
-
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).
|
|
703
662
|
|
|
704
663
|
```ts
|
|
705
664
|
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
@@ -1020,7 +979,53 @@ Dynatrace.startView("UserProfileDetailed");
|
|
|
1020
979
|
|
|
1021
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.
|
|
1022
981
|
|
|
1023
|
-
|
|
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
|
+
|
|
1024
1029
|
|
|
1025
1030
|
#### Produced data
|
|
1026
1031
|
|
|
@@ -1034,6 +1039,8 @@ Each captured interaction produces an event describing what the user touched and
|
|
|
1034
1039
|
|
|
1035
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.
|
|
1036
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
|
+
|
|
1037
1044
|
#### Example event
|
|
1038
1045
|
|
|
1039
1046
|
```json
|
|
@@ -1071,13 +1078,6 @@ To generate a sourcemap:
|
|
|
1071
1078
|
* Then run `npx react-native run-ios --mode Release`, or
|
|
1072
1079
|
* Build for release in Xcode
|
|
1073
1080
|
|
|
1074
|
-
#### Accounting for Auto-Instrumentation
|
|
1075
|
-
|
|
1076
|
-
Since the plugin auto-instruments your code, sourcemap line numbers may be slightly offset. To ensure accurate symbolication:
|
|
1077
|
-
|
|
1078
|
-
* **Android**: Automatic patching is **enabled by default** and patches sourcemaps automatically at the end of every release build (see [Source Map](#source-map) configuration)
|
|
1079
|
-
* **iOS**: There is currently **no automation** available. You **must** execute [`npx lineOffsetDynatrace`](#npx-lineoffsetdynatrace) to patch your sourcemap files before uploading them to Dynatrace. Without this step, line numbers will be slightly off depending on instrumentation in iOS
|
|
1080
|
-
|
|
1081
1081
|
#### Uploading Sourcemaps
|
|
1082
1082
|
|
|
1083
1083
|
Once generated and patched, upload your sourcemaps to Dynatrace. For detailed instructions, see the [symbol file management documentation](https://docs.dynatrace.com/docs/observe/digital-experience/mobile-applications/analyze-and-use/upload-and-manage-symbol-files).
|
|
@@ -1100,27 +1100,20 @@ npx instrumentDynatrace [optional: config=... gradle=... plist=...]
|
|
|
1100
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.
|
|
1101
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.
|
|
1102
1102
|
|
|
1103
|
-
|
|
1103
|
+
If `plist=...` is not provided, the plugin tries to resolve `Info.plist` automatically in this order:
|
|
1104
1104
|
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
```
|
|
1108
|
-
|
|
1109
|
-
* `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.
|
|
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`.
|
|
1110
1107
|
|
|
1111
|
-
|
|
1108
|
+
For monorepos or multi-target iOS setups, automatic discovery can be ambiguous. In those cases, pass `plist=...` explicitly to select the exact file.
|
|
1112
1109
|
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
The `npx lineOffsetDynatrace` command patches your sourcemap file with offset information, allowing Dynatrace to accurately map instrumented line numbers back to the original source code. The patching process adds Dynatrace-specific metadata alongside the original sourcemap content without modifying any existing fields, ensuring your sourcemap continues to work as expected with all standard tooling.
|
|
1116
|
-
|
|
1117
|
-
**Usage:**
|
|
1110
|
+
### npx configDynatrace
|
|
1118
1111
|
|
|
1119
1112
|
```
|
|
1120
|
-
npx
|
|
1113
|
+
npx configDynatrace [optional: config=...]
|
|
1121
1114
|
```
|
|
1122
1115
|
|
|
1123
|
-
* `
|
|
1116
|
+
* `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.
|
|
1124
1117
|
|
|
1125
1118
|
## Customizing paths for configuration
|
|
1126
1119
|
|
|
@@ -1149,6 +1142,32 @@ npx react-native run-android --port=2000
|
|
|
1149
1142
|
|
|
1150
1143
|
> **Note:** that custom arguments must not be prefixed with -- !
|
|
1151
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
|
+
|
|
1152
1171
|
## Manually adding iOS OneAgent to a project
|
|
1153
1172
|
|
|
1154
1173
|
Adding the iOS agent manually depends on the availability of support for CocoaPods.
|
|
@@ -1180,9 +1199,6 @@ Before installing the plugin, add the following to your `package.json`:
|
|
|
1180
1199
|
|
|
1181
1200
|
```
|
|
1182
1201
|
"overrides": {
|
|
1183
|
-
"@react-native-picker/picker": {
|
|
1184
|
-
"react-native": "<insert-version-here>"
|
|
1185
|
-
},
|
|
1186
1202
|
"@dynatrace/react-native-plugin": {
|
|
1187
1203
|
"react-native": "<insert-version-here>"
|
|
1188
1204
|
}
|
|
@@ -1193,9 +1209,6 @@ If you are using the following `"react-native": "npm:react-native-tvos@0.69.8-2"
|
|
|
1193
1209
|
|
|
1194
1210
|
```
|
|
1195
1211
|
"overrides": {
|
|
1196
|
-
"@react-native-picker/picker": {
|
|
1197
|
-
"react-native": "0.69.8-2"
|
|
1198
|
-
},
|
|
1199
1212
|
"@dynatrace/react-native-plugin": {
|
|
1200
1213
|
"react-native": "0.69.8-2"
|
|
1201
1214
|
}
|
|
@@ -1259,6 +1272,8 @@ Here is a list of all the counterparts for the options that can be used with a m
|
|
|
1259
1272
|
|lifecycleUpdate|false| - | - | lifecycle.includeUpdate |
|
|
1260
1273
|
|userOptIn|false|userOptIn|DTXUserOptIn| - |
|
|
1261
1274
|
|actionNamePrivacy|false|-|-|input.actionNamePrivacy
|
|
1275
|
+
|actionNamePreference|'any'|-|-|input.actionNamePreference
|
|
1276
|
+
|actionNameAlgorithm|'depth-first'|-|-|input.actionNameAlgorithm
|
|
1262
1277
|
|bundleName|undefined|-|-|bundleName
|
|
1263
1278
|
|
|
1264
1279
|
### React block
|
|
@@ -1269,13 +1284,14 @@ The `react` configuration block contains all settings regarding the react instru
|
|
|
1269
1284
|
|
|
1270
1285
|
```js
|
|
1271
1286
|
react : {
|
|
1272
|
-
|
|
1273
1287
|
input : {
|
|
1274
1288
|
instrument(filename) => {
|
|
1275
1289
|
return true;
|
|
1276
1290
|
},
|
|
1277
1291
|
|
|
1278
1292
|
actionNamePrivacy: false,
|
|
1293
|
+
actionNamePreference: 'any',
|
|
1294
|
+
actionNameAlgorithm: 'depth-first',
|
|
1279
1295
|
}
|
|
1280
1296
|
}
|
|
1281
1297
|
```
|
|
@@ -1311,7 +1327,7 @@ react: {
|
|
|
1311
1327
|
This activates the debug mode. You will get more console output during instrumentation and at runtime.
|
|
1312
1328
|
|
|
1313
1329
|
|
|
1314
|
-
|
|
1330
|
+
#### User Interaction Configuration
|
|
1315
1331
|
|
|
1316
1332
|
```js
|
|
1317
1333
|
react: {
|
|
@@ -1319,37 +1335,7 @@ react: {
|
|
|
1319
1335
|
}
|
|
1320
1336
|
```
|
|
1321
1337
|
|
|
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.
|
|
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.
|
|
1353
1339
|
|
|
1354
1340
|
#### Error Handler
|
|
1355
1341
|
|
|
@@ -1420,33 +1406,32 @@ react: {
|
|
|
1420
1406
|
}
|
|
1421
1407
|
```
|
|
1422
1408
|
|
|
1423
|
-
####
|
|
1424
|
-
|
|
1425
|
-
This feature is enabled by default and patches sourcemap files so that any modifications made through Dynatrace will result in correct line numbers. If this feature is not enabled, line numbers of symbolicated stacktraces in Dynatrace might not match with your original source.
|
|
1409
|
+
#### Debugging our auto-instrumentation
|
|
1426
1410
|
|
|
1427
|
-
|
|
1411
|
+
You can see the changes our auto-instrumentation is making to your code with this flag:
|
|
1428
1412
|
|
|
1429
1413
|
```js
|
|
1430
1414
|
react: {
|
|
1431
|
-
|
|
1432
|
-
enabled: true
|
|
1433
|
-
}
|
|
1415
|
+
debugBabelPlugin: true
|
|
1434
1416
|
}
|
|
1435
1417
|
```
|
|
1436
1418
|
|
|
1437
|
-
|
|
1419
|
+
The changes our auto-instrumentation is making now get dumped into the `node_modules/@dynatrace/react-native-plugin/build` folder when building the Javascript bundle. The `*.dtx` files show what your code looks like after only our auto-instrumentation was applied to your code. The `*.dtx.downstream` files show what your code looks like after both our auto-instrumentation and all other babel plugins were applied to your code.
|
|
1420
|
+
|
|
1421
|
+
> **Note:** This feature increases the time it takes to build the Javascript bundle. Only use it for debugging purposes. Deactivate it otherwise, especially when fast build times are important.
|
|
1422
|
+
|
|
1423
|
+
#### Using our legacy jscodeshift auto-instrumentation
|
|
1438
1424
|
|
|
1439
|
-
|
|
1425
|
+
We recently moved our auto-instrumentation to a babel plugin. In case you need to, you can still switch to the old jscodeshift auto-instrumentation with this flag:
|
|
1440
1426
|
|
|
1441
1427
|
```js
|
|
1442
1428
|
react: {
|
|
1443
|
-
|
|
1444
|
-
enabled: true,
|
|
1445
|
-
androidSourcemapLocation: 'sourcemap.map'
|
|
1446
|
-
}
|
|
1429
|
+
useLegacyJscodeshift: true
|
|
1447
1430
|
}
|
|
1448
1431
|
```
|
|
1449
1432
|
|
|
1433
|
+
> **Note:** When we moved our auto-instrumentation to a babel plugin, we removed documentation that was only relevant for the jscodeshift auto-instrumentation. Most notably, we removed documentation concerning registering a custom metro transformer and patching sourcemaps. If you use the `useLegacyJscodeshift` flag, please refer to the [legacy documentation (v2.333.1)](https://www.npmjs.com/package/@dynatrace/react-native-plugin/v/2.333.1) for details on custom metro transformers and sourcemap patching.
|
|
1434
|
+
|
|
1450
1435
|
### Android block
|
|
1451
1436
|
|
|
1452
1437
|
The Android block is a wrapper for the Android configuration you find in the WebUI (in the Mobile Application Settings). Copy the content into the following block:
|
|
@@ -1614,20 +1599,38 @@ ios: {
|
|
|
1614
1599
|
* displayName: Use the displayName property to check if React views have a display name set
|
|
1615
1600
|
* instrumentation string: Auto instrumentation or manual instrumentation is passing a string. This will be used if available.
|
|
1616
1601
|
* class name: If the display name is not available, the class name is used by taking the property name from the constructor
|
|
1617
|
-
* Touchables
|
|
1618
|
-
* dtActionName: Use a custom property called dtActionName
|
|
1619
|
-
* If [actionNamePrivacy](#plugin-startup) is activated anything below will not be detected
|
|
1620
|
-
* accessibilityLabel property
|
|
1621
|
-
* If both are not set, it will search for an inner text
|
|
1622
|
-
* If it is an Image Button, it will search for a source
|
|
1623
|
-
* Buttons
|
|
1602
|
+
* Touchables, Buttons, Pressable
|
|
1624
1603
|
* dtActionName: Use a custom property called dtActionName
|
|
1625
|
-
* If [actionNamePrivacy](#plugin-startup) is activated
|
|
1626
|
-
*
|
|
1604
|
+
* If [actionNamePrivacy](#plugin-startup) is activated anything below will not be detected
|
|
1605
|
+
* title property
|
|
1627
1606
|
* accessibilityLabel property
|
|
1628
|
-
* If
|
|
1629
|
-
*
|
|
1630
|
-
|
|
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
|
|
1631
1634
|
* dtActionName: Use a custom property called dtActionName
|
|
1632
1635
|
* accessibilityLabel property
|
|
1633
1636
|
|
|
@@ -1745,75 +1748,6 @@ module.exports = {
|
|
|
1745
1748
|
};
|
|
1746
1749
|
```
|
|
1747
1750
|
|
|
1748
|
-
## Using a second transformer besides the dynatrace transformer
|
|
1749
|
-
|
|
1750
|
-
If you want to register the Dynatrace transformer in your configuration and you already have a transformer in place, change the upstreaming transformer for the Dynatrace transformer.
|
|
1751
|
-
|
|
1752
|
-
This can be done via a configuration value in the `dynatrace.config.js`. The following example shows how the configuration might look like for the popular `react-native-svg-transformer`. Be aware that the following example is targeting *React Native v0.72.1* or newer. Be aware if you are using a different second transformer, you need to change `react-native-svg-transformer/react-native` accordingly.
|
|
1753
|
-
|
|
1754
|
-
#### dynatrace.config.js
|
|
1755
|
-
|
|
1756
|
-
```js
|
|
1757
|
-
// The `...` only indicates that there are other values as well, but we've omitted them in this example.
|
|
1758
|
-
module.exports = {
|
|
1759
|
-
react : {
|
|
1760
|
-
upstreamTransformer: require.resolve('react-native-svg-transformer/react-native'),
|
|
1761
|
-
// ...
|
|
1762
|
-
},
|
|
1763
|
-
// ...
|
|
1764
|
-
};
|
|
1765
|
-
```
|
|
1766
|
-
|
|
1767
|
-
#### metro.config.js for React Native v0.72.1 or newer
|
|
1768
|
-
```js
|
|
1769
|
-
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
|
|
1770
|
-
const defaultConfig = getDefaultConfig(__dirname);
|
|
1771
|
-
const {assetExts, sourceExts} = defaultConfig.resolver;
|
|
1772
|
-
|
|
1773
|
-
/**
|
|
1774
|
-
* Metro configuration
|
|
1775
|
-
* https://facebook.github.io/metro/docs/configuration
|
|
1776
|
-
*
|
|
1777
|
-
* @type {import('metro-config').MetroConfig}
|
|
1778
|
-
*/
|
|
1779
|
-
const config = {
|
|
1780
|
-
transformer: {
|
|
1781
|
-
babelTransformerPath: require.resolve(
|
|
1782
|
-
'@dynatrace/react-native-plugin/lib/dynatrace-transformer',
|
|
1783
|
-
),
|
|
1784
|
-
},
|
|
1785
|
-
reporter: require('@dynatrace/react-native-plugin/lib/dynatrace-reporter'),
|
|
1786
|
-
resolver: {
|
|
1787
|
-
assetExts: assetExts.filter((ext) => ext !== 'svg'),
|
|
1788
|
-
sourceExts: [...sourceExts, 'cjs', 'svg'],
|
|
1789
|
-
},
|
|
1790
|
-
};
|
|
1791
|
-
|
|
1792
|
-
module.exports = mergeConfig(defaultConfig, config);
|
|
1793
|
-
```
|
|
1794
|
-
|
|
1795
|
-
#### metro.config.js for React Native v0.59 or newer
|
|
1796
|
-
|
|
1797
|
-
```js
|
|
1798
|
-
const { getDefaultConfig } = require("metro-config");
|
|
1799
|
-
|
|
1800
|
-
module.exports = (async () => {
|
|
1801
|
-
const {
|
|
1802
|
-
resolver: { sourceExts, assetExts }
|
|
1803
|
-
} = await getDefaultConfig();
|
|
1804
|
-
return {
|
|
1805
|
-
transformer: {
|
|
1806
|
-
babelTransformerPath: require.resolve('@dynatrace/react-native-plugin/lib/dynatrace-transformer')
|
|
1807
|
-
},
|
|
1808
|
-
reporter: require('@dynatrace/react-native-plugin/lib/dynatrace-reporter'),
|
|
1809
|
-
resolver: {
|
|
1810
|
-
assetExts: assetExts.filter((ext) => ext !== "svg"),
|
|
1811
|
-
sourceExts: [...sourceExts, "cjs", "svg"]
|
|
1812
|
-
}
|
|
1813
|
-
};
|
|
1814
|
-
})();
|
|
1815
|
-
```
|
|
1816
|
-
|
|
1817
1751
|
## Maven Central in top-level gradle file
|
|
1818
1752
|
|
|
1819
1753
|
Because the Dynatrace Android agent now requires the MavenCentral repository, if either `jcenter()` or `mavenCentral()` is not added inside of **ALL** the repositories blocks via the [top-level build.gradle](https://dt-url.net/jm610pso), the build will fail.
|
|
@@ -2054,12 +1988,27 @@ If you are struggling with a problem, submit a support ticket to Dynatrace (supp
|
|
|
2054
1988
|
<br/><br/>
|
|
2055
1989
|
## Changelog
|
|
2056
1990
|
|
|
2057
|
-
|
|
1991
|
+
2.337.1
|
|
1992
|
+
* Updated Android (8.337.2.1010) & iOS Agent (8.337.1.1003)
|
|
1993
|
+
* 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`).
|
|
1994
|
+
* 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.
|
|
1995
|
+
* Added [actionNamePreference](#plugin-startup) and [actionNameAlgorithm](#plugin-startup) configuration flags.
|
|
1996
|
+
|
|
1997
|
+
2.335.1
|
|
1998
|
+
* Updated Android (8.335.1.1001) & iOS Agent (8.335.1.1009)
|
|
1999
|
+
* 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.
|
|
2000
|
+
* Updated Android Gradle plugin configuration for Gradle 9 compatibility in `plugin-runtime.gradle`.
|
|
2001
|
+
* Moved auto-instrumentation from jscodeshift to a Babel plugin, improvements include:
|
|
2002
|
+
* Significantly faster JS bundle builds
|
|
2003
|
+
* Sourcemaps now natively account for our auto-instrumentation - no patching needed
|
|
2004
|
+
* Added instrumentation for `BorderlessButton` and `BaseButton` from `react-native-gesture-handler`.
|
|
2005
|
+
* 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.
|
|
2006
|
+
* 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.
|
|
2058
2007
|
|
|
2059
2008
|
2.333.1
|
|
2060
2009
|
* Jetpack Compose support range extended to 1.4 - 1.10 see [Compose Compatibility Note](#compose-compatibility-note)
|
|
2061
2010
|
* Updated Android (8.333.1.1006) & iOS Agent (8.333.1.1005)
|
|
2062
|
-
* Added
|
|
2011
|
+
* Added configuration flag to enable/disable the [User Interaction feature](#user-interaction-configuration).
|
|
2063
2012
|
* Added [User Interaction feature](#user-interaction) to collect UI interaction data such as touches, providing insights into user behavior
|
|
2064
2013
|
|
|
2065
2014
|
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.2.1010'
|
|
76
76
|
implementation "com.facebook.react:react-native:${safeExtGet('reactNative', '+')}"
|
|
77
77
|
}
|
|
78
78
|
|