@dynatrace/react-native-plugin 2.341.1 → 2.345.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 +674 -668
- package/android/build.gradle +16 -3
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceAppStartModule.kt +9 -31
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceConfigurationModule.kt +1 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +41 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.kt +1 -0
- package/android/src/main/java/com/dynatrace/android/agent/ScreenshotSelfMonitor.kt +175 -0
- package/android/src/main/java/com/dynatrace/android/agent/UIChangeScreenshotListener.kt +124 -0
- package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +33 -0
- package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +40 -0
- package/files/plugin-runtime.gradle +17 -33
- package/files/plugin.gradle +1 -1
- package/instrumentation/BabelPluginDynatrace.js +1 -1
- package/instrumentation/libs/UserInteraction.js +21 -7
- package/instrumentation/libs/react-navigation/ReactNavigation.js +14 -58
- package/instrumentation/libs/withOnPressMonitoring.js +3 -54
- package/internal.d.ts +1 -0
- package/internal.js +3 -1
- package/ios/DTXScreenshotSelfMonitor.h +29 -0
- package/ios/DTXScreenshotSelfMonitor.mm +213 -0
- package/ios/DTXScreenshotSelfMonitorSwizzler.h +15 -0
- package/ios/DTXScreenshotSelfMonitorSwizzler.mm +68 -0
- package/ios/DynatraceRNBridge.h +6 -0
- package/ios/DynatraceRNBridge.mm +62 -0
- package/lib/core/Dynatrace.js +2 -0
- package/lib/core/configuration/ConfigurationHandler.js +0 -21
- package/lib/core/logging/LogMessages.js +42 -0
- package/lib/dynatrace-reporter.js +1 -30
- package/lib/dynatrace-transformer.js +6 -34
- package/lib/next/Dynatrace.js +26 -1
- package/lib/next/configuration/INativeRuntimeConfiguration.js +0 -1
- package/lib/next/configuration/RuntimeConfigurationObserver.js +1 -6
- package/lib/next/events/EventPipeline.js +48 -31
- package/lib/next/events/HttpRequestEventData.js +1 -1
- package/lib/next/events/spec/EventSpecContstants.js +1 -1
- package/lib/next/navigation/NavigationTracker.js +93 -0
- package/lib/next/navigation/useNavigationTracking.js +54 -0
- package/lib/next/userAction/NullUserAction.js +15 -0
- package/lib/next/userAction/UserActionConfiguration.js +10 -0
- package/lib/next/userAction/UserActionImpl.js +70 -0
- package/lib/next/util/TraceContextUtils.js +8 -14
- package/lib/next/util/Utils.js +13 -0
- package/package.json +10 -18
- package/public.js +5 -1
- package/react-native-dynatrace.podspec +10 -3
- package/scripts/Android.js +1 -20
- package/scripts/Config.js +17 -7
- package/scripts/Deprecations.js +18 -0
- package/scripts/Install.js +13 -0
- package/scripts/PathsConstants.js +0 -4
- package/scripts/Uninstall.js +0 -15
- package/scripts/core/InstrumentCall.js +14 -7
- package/scripts/util/DeprecationReport.js +24 -0
- package/src/lib/core/interface/NativeDynatraceBridge.ts +34 -1
- package/types.d.ts +236 -7
- package/instrumentation/DynatraceInstrumentation.js +0 -1
- package/instrumentation/libs/community/Picker.InstrInfo.js +0 -20
- package/instrumentation/libs/community/gesture-handler/Touchables.InstrInfo.js +0 -25
- package/instrumentation/libs/react-native/RefreshControl.InstrInfo.js +0 -12
- package/instrumentation/libs/react-native/Switch.InstrInfo.js +0 -12
- package/instrumentation/libs/react-native/Touchables.InstrInfo.js +0 -25
- package/instrumentation/parser/Babel.js +0 -60
- package/instrumentation/parser/ParserUtil.js +0 -11
- package/lib/features/ui-interaction/Config.js +0 -42
- package/lib/features/ui-interaction/IUserInteractionEvent.js +0 -16
- package/lib/features/ui-interaction/Plugin.Fragment.Test.js +0 -170
- package/lib/features/ui-interaction/Plugin.js +0 -289
- package/lib/features/ui-interaction/RootDetection.js +0 -51
- package/lib/features/ui-interaction/RootWrapper.js +0 -236
- package/lib/features/ui-interaction/Run.js +0 -38
- package/lib/features/ui-interaction/Runtime.js +0 -843
- package/lib/features/ui-interaction/TouchMetaResolver.js +0 -493
- package/lib/features/ui-interaction/Types.js +0 -14
- package/lib/metro/getSourceMapInfo.js +0 -26
- package/scripts/LineOffsetAnalyze.js +0 -25
- package/scripts/core/LineOffsetAnalyzeCall.js +0 -165
- package/scripts/util/SourceMapUtil.js +0 -68
- /package/{instrumentation/model/Reference.js → lib/next/userAction/UserAction.js} +0 -0
package/README.md
CHANGED
|
@@ -23,20 +23,20 @@ If you want to start using this plugin and are not a Dynatrace customer yet, hea
|
|
|
23
23
|
* React v16.8 or newer
|
|
24
24
|
* React Native v0.60 or newer
|
|
25
25
|
* For Android users:
|
|
26
|
-
* SDK version
|
|
27
|
-
* Gradle version
|
|
26
|
+
* SDK version 23+
|
|
27
|
+
* Gradle version 8.1.1+ ([How to update?](#updating-to-gradle-7))
|
|
28
28
|
* Android Gradle plugin version 7.0+
|
|
29
|
-
* Java
|
|
29
|
+
* Java 17
|
|
30
30
|
* Kotlin 2.0.21 - see [Kotlin Compatibility Note](#kotlin-compatibility-note)
|
|
31
31
|
* Jetpack Compose 1.4 - 1.10 - see [Compose Compatibility Note](#compose-compatibility-note)
|
|
32
|
-
* For iOS users: Minimum iOS
|
|
32
|
+
* For iOS users: Minimum iOS 15
|
|
33
33
|
* NodeJS 16.0.0+ since our dependencies require NodeJS 16.0.0
|
|
34
34
|
|
|
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.345.1.1003
|
|
39
|
+
* iOS Agent: 8.345.1.1003
|
|
40
40
|
|
|
41
41
|
## Quick Setup
|
|
42
42
|
|
|
@@ -48,36 +48,35 @@ These agent versions are configured in this plugin:
|
|
|
48
48
|
|
|
49
49
|
## Advanced topics
|
|
50
50
|
* [Manual OneAgent Startup](#manual-oneagent-startup)
|
|
51
|
-
* [
|
|
52
|
-
* [
|
|
51
|
+
* [Real User Monitoring (RUM)](#real-user-monitoring-rum)
|
|
52
|
+
* [User Interaction](#user-interaction)
|
|
53
|
+
* [Send Event](#send-event)
|
|
54
|
+
* [Send Session Property Event](#send-session-property-event)
|
|
55
|
+
* [Event Modifier](#event-modifier)
|
|
56
|
+
* [Send Exception Event](#send-exception-event)
|
|
57
|
+
* [Send HTTP Request Event](#send-http-request-event)
|
|
58
|
+
* [View Monitoring](#view-monitoring)
|
|
59
|
+
* [React Native Symbolication](#react-native-symbolication)
|
|
60
|
+
* [RUM Classic](#rum-classic)
|
|
53
61
|
* [Monitor a Component](#monitor-a-component)
|
|
54
62
|
* [Create Custom Action](#create-custom-actions)
|
|
55
63
|
* [Cancel Actions](#cancel-actions)
|
|
56
64
|
* [Manual Web Request Tagging](#manual-web-request-tagging)
|
|
57
65
|
* [Report Values](#report-values)
|
|
58
66
|
* [Report Stacktrace](#report-an-error-stacktrace)
|
|
59
|
-
* [Identify User](#identify-a-user)
|
|
60
|
-
* [End Session](#end-the-current-user-session)
|
|
61
67
|
* [Crash Reporting](#manually-report-a-crash)
|
|
62
|
-
* [User Privacy Options](#user-privacy-options)
|
|
63
68
|
* [Report GPS Position](#report-gps-location)
|
|
64
69
|
* [Business event capturing](#business-event-capturing)
|
|
65
70
|
* [Platform independent reporting](#platform-independent-reporting)
|
|
66
71
|
* [Set beacon headers](#setting-beacon-headers)
|
|
67
72
|
* [Exclude Individual JSX Elements](#exclude-individual-jsx-elements)
|
|
68
|
-
* [
|
|
69
|
-
* [User
|
|
70
|
-
* [
|
|
71
|
-
* [
|
|
72
|
-
* [Event Modifier](#event-modifier)
|
|
73
|
-
* [Send Exception Event](#send-exception-event)
|
|
74
|
-
* [Send HTTP Request Event](#send-http-request-event)
|
|
75
|
-
* [View Monitoring](#view-monitoring)
|
|
76
|
-
* [React Native Symbolication](#react-native-symbolication)
|
|
73
|
+
* [Extended topics](#extended-topics)
|
|
74
|
+
* [Identify User](#identify-a-user)
|
|
75
|
+
* [End Session](#end-the-current-user-session)
|
|
76
|
+
* [User Privacy Options](#user-privacy-options)
|
|
77
77
|
* [NPX Commands](#npx-commands)
|
|
78
78
|
* [npx instrumentDynatrace](#npx-instrumentdynatrace)
|
|
79
79
|
* [npx configDynatrace](#npx-configdynatrace)
|
|
80
|
-
* [npx lineOffsetDynatrace](#npx-lineoffsetdynatrace)
|
|
81
80
|
* [Customizing paths for configuration](#customizing-paths-for-configuration)
|
|
82
81
|
* [Manual adding iOS Agent to project](#manually-adding-ios-oneagent-to-a-project)
|
|
83
82
|
* [Setup for tvOS](#setup-for-tvos)
|
|
@@ -91,10 +90,8 @@ These agent versions are configured in this plugin:
|
|
|
91
90
|
* [Autostart](#autostart)
|
|
92
91
|
* [Bundle Name and Version](#bundle-name-and-version)
|
|
93
92
|
* [Navigation](#navigation)
|
|
94
|
-
* [Source Map](#source-map)
|
|
95
93
|
* [User Interaction Configuration](#user-interaction-configuration)
|
|
96
94
|
* [Debugging our auto-instrumentation](#debugging-our-auto-instrumentation)
|
|
97
|
-
* [Using our legacy jscodeshift auto-instrumentation](#using-our-legacy-jscodeshift-auto-instrumentation)
|
|
98
95
|
* [Android block](#android-block)
|
|
99
96
|
* [iOS block](#ios-block)
|
|
100
97
|
* [Lifecycle modes](#lifecycle)
|
|
@@ -221,31 +218,7 @@ module.exports = {
|
|
|
221
218
|
};
|
|
222
219
|
```
|
|
223
220
|
|
|
224
|
-
2.
|
|
225
|
-
|
|
226
|
-
Example of a startup call:
|
|
227
|
-
|
|
228
|
-
```ts
|
|
229
|
-
import { Dynatrace, ConfigurationBuilder } from '@dynatrace/react-native-plugin';
|
|
230
|
-
|
|
231
|
-
await Dynatrace.start(new ConfigurationBuilder("beaconUrl", "applicationId").buildConfiguration());
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
For more details see the section about [startup API](#plugin-startup).
|
|
235
|
-
|
|
236
|
-
**Note**: If you don't deactivate the automated startup with the `dynatrace.config.js` file, the `beaconUrl` and `applicationId` values have no impact and are thrown away.
|
|
237
|
-
|
|
238
|
-
## Manual instrumentation
|
|
239
|
-
|
|
240
|
-
To use the API of the React Native plugin, import the API:
|
|
241
|
-
|
|
242
|
-
```ts
|
|
243
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
### Plugin startup
|
|
247
|
-
|
|
248
|
-
The manual startup of the plugin is triggered via the `start(configuration: IConfiguration)` method. If you configured `dynatrace.config.js` for manual startup then the plugin doesn't send any data when not calling this function. Besides the application id and the beacon URL, there are several optional configuration parameters, which are shown in the table below.
|
|
221
|
+
2. Call `Dynatrace.start()` with your configuration. The startup call is triggered via the `start(configuration: IConfiguration)` method — if you configured `dynatrace.config.js` for manual startup, the plugin doesn't send any data until this function is called. At minimum you need `beaconUrl` and `applicationId`, but there are several optional configuration parameters as well:
|
|
249
222
|
|
|
250
223
|
```ts
|
|
251
224
|
import { Dynatrace, ConfigurationBuilder, LogLevel } from '@dynatrace/react-native-plugin';
|
|
@@ -265,6 +238,8 @@ configurationBuilder.withCrashReporting(true)
|
|
|
265
238
|
await Dynatrace.start(configurationBuilder.buildConfiguration());
|
|
266
239
|
```
|
|
267
240
|
|
|
241
|
+
**Note**: If you don't deactivate the automated startup with the `dynatrace.config.js` file, the `beaconUrl` and `applicationId` values have no impact and are thrown away.
|
|
242
|
+
|
|
268
243
|
**Info**: The value used in the function calls for the parameters is also their default value.
|
|
269
244
|
|
|
270
245
|
| Property name | Type | Default | Description |
|
|
@@ -282,866 +257,867 @@ await Dynatrace.start(configurationBuilder.buildConfiguration());
|
|
|
282
257
|
|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.|
|
|
283
258
|
|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.
|
|
284
259
|
|
|
285
|
-
**Attention:**
|
|
260
|
+
**Attention:**
|
|
286
261
|
* Keep in mind that configuration within the `dynatrace.config.js` file is the basis, even for manual startup. When we look at the lifecycleUpdate property: Per default if not used, it is false. If enabled (set to true) in `dynatrace.config.js` file, this will be also true if manual startup is used. You can still override this behavior by calling `ConfigurationBuilder.withLifecycleUpdate(false)`.
|
|
287
262
|
* Please use those parameters only when doing a manual startup. If you want to do an automated startup, please configure the properties via the [auto startup configuration](#manual-startup-counterparts). You will find a list which explains all the counterparts for the available options here.
|
|
288
263
|
|
|
289
|
-
|
|
264
|
+
## Real User Monitoring (RUM)
|
|
290
265
|
|
|
291
|
-
|
|
266
|
+
Real User Monitoring introduces a set of advanced APIs that allow you to send custom events, modify event data, track exceptions, monitor HTTP requests, and manage view contexts in your React Native application. These APIs provide more granular control over the data captured by Dynatrace and are designed for the next generation RUM capabilities.
|
|
292
267
|
|
|
293
|
-
|
|
268
|
+
For more detailed information about Real User Monitoring, see the [official Dynatrace documentation](https://docs.dynatrace.com/docs/shortlink/react-native-main).
|
|
294
269
|
|
|
295
|
-
|
|
296
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
297
|
-
import { FunctionComponent } from 'react';
|
|
270
|
+
### Send Event
|
|
298
271
|
|
|
299
|
-
|
|
300
|
-
return null;
|
|
301
|
-
}
|
|
272
|
+
The `sendEvent()` method allows you to send custom events with arbitrary properties using the EventData class. This is useful for tracking specific user interactions or application state changes.
|
|
302
273
|
|
|
303
|
-
|
|
274
|
+
```ts
|
|
275
|
+
import { Dynatrace, EventData } from '@dynatrace/react-native-plugin';
|
|
276
|
+
|
|
277
|
+
// Send a custom event with properties
|
|
278
|
+
Dynatrace.sendEvent(new EventData()
|
|
279
|
+
.addEventProperty("event_properties.button_clicked", "login_button")
|
|
280
|
+
.addEventProperty("event_properties.user_type", "premium")
|
|
281
|
+
.addEventProperty("event_properties.attempt_count", 3)
|
|
282
|
+
.withDuration(250)
|
|
283
|
+
);
|
|
304
284
|
```
|
|
305
|
-

|
|
306
285
|
|
|
307
|
-
|
|
286
|
+
**Property Requirements:**
|
|
287
|
+
* Only properties prefixed with `event_properties.*` are allowed
|
|
288
|
+
* Additionally, the `duration` property is allowed
|
|
289
|
+
* Maximum of 50 custom properties per event
|
|
290
|
+
* If the limit is exceeded, properties are sorted alphabetically by key and excess properties are dropped deterministically
|
|
291
|
+
* String properties are limited to 5000 characters (exceeding characters are truncated)
|
|
292
|
+
* Field names must contain only alphabetic characters, numbers, underscores, and dots
|
|
293
|
+
* Each dot must be followed by an alphabetic character
|
|
294
|
+
* Each underscore must be followed by an alphabetic character or number
|
|
295
|
+
* Values must be primitive types (string, number, boolean)
|
|
296
|
+
* Cannot contain functions, undefined, Infinity, or NaN as values (they will be replaced with null)
|
|
308
297
|
|
|
309
|
-
|
|
298
|
+
### Send Session Property Event
|
|
310
299
|
|
|
311
|
-
|
|
300
|
+
Session properties apply to all events within the current session. Use `sendSessionPropertyEvent()` to set properties that should be available across the entire user session.
|
|
312
301
|
|
|
313
|
-
|
|
302
|
+
```ts
|
|
303
|
+
import { Dynatrace, SessionPropertyEventData } from '@dynatrace/react-native-plugin';
|
|
314
304
|
|
|
315
|
-
|
|
305
|
+
// Set session-wide properties
|
|
306
|
+
Dynatrace.sendSessionPropertyEvent(new SessionPropertyEventData()
|
|
307
|
+
.addSessionProperty("session_properties.user_tier", "premium")
|
|
308
|
+
.addSessionProperty("session_properties.app_version", "2.1.0")
|
|
309
|
+
.addSessionProperty("session_properties.feature_flag_enabled", true)
|
|
310
|
+
);
|
|
311
|
+
```
|
|
316
312
|
|
|
317
|
-
|
|
313
|
+
**Important Notes:**
|
|
314
|
+
* Session properties persist throughout the entire session
|
|
315
|
+
* If you send the same property multiple times, only one value will be kept (first or last)
|
|
316
|
+
* Use session properties for data that applies to the entire user session
|
|
317
|
+
* Field naming follows the same rules as events, but with `session_properties.` prefix
|
|
318
|
+
* Maximum of 50 custom properties per event
|
|
319
|
+
* If the limit is exceeded, properties are sorted alphabetically by key and excess properties are dropped deterministically
|
|
318
320
|
|
|
319
|
-
|
|
320
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
321
|
+
### Event Modifier
|
|
321
322
|
|
|
322
|
-
|
|
323
|
-
//Perform the action and whatever else is needed.
|
|
324
|
-
myAction.leaveAction();
|
|
325
|
-
```
|
|
326
|
-

|
|
323
|
+
Event modifiers allow you to intercept and modify events before they are sent to Dynatrace. This is useful for adding common properties, filtering sensitive data, or enriching events with additional context. Event modifiers apply to all event types, including custom events, session properties, exceptions, and HTTP events.
|
|
327
324
|
|
|
328
|
-
|
|
325
|
+
If multiple event modifiers are added, they are executed in the order they were added.
|
|
329
326
|
|
|
330
|
-
|
|
331
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
327
|
+
Most fields and namespaces can't be modified in any way (added, removed or overridden), while others are open for modification.
|
|
332
328
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
```
|
|
329
|
+
**Open for modification and can be added:**
|
|
330
|
+
- `event_properties.*`
|
|
331
|
+
- `session_properties.*`
|
|
337
332
|
|
|
338
|
-
|
|
333
|
+
`session_properties.*` are only allowed to be on a session property event.
|
|
334
|
+
|
|
335
|
+
**Open for modification only:**
|
|
336
|
+
- `url.full`
|
|
337
|
+
- `exception.stack_trace`
|
|
338
|
+
|
|
339
|
+
#### Example
|
|
339
340
|
|
|
340
341
|
```ts
|
|
341
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
342
|
+
import { Dynatrace, IEventModifier } from '@dynatrace/react-native-plugin';
|
|
342
343
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
344
|
+
// Create an event modifier
|
|
345
|
+
const myModifier: IEventModifier = {
|
|
346
|
+
modifyEvent(event) {
|
|
347
|
+
// Add common properties to all events
|
|
348
|
+
event["event_properties.app_build"] = "1.2.3";
|
|
349
|
+
event["event_properties.environment"] = "production";
|
|
350
|
+
|
|
351
|
+
// Return null to discard the event entirely
|
|
352
|
+
if (event["event_properties.ignore"] === true) {
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return event;
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
// Add the modifier
|
|
361
|
+
Dynatrace.addEventModifier(myModifier);
|
|
362
|
+
|
|
363
|
+
// Remove the modifier when no longer needed
|
|
364
|
+
Dynatrace.removeEventModifier(myModifier);
|
|
346
365
|
```
|
|
347
366
|
|
|
348
|
-
|
|
367
|
+
#### Important Considerations
|
|
349
368
|
|
|
350
|
-
|
|
369
|
+
- **Execution order**: If multiple event modifiers are added, they are executed in the order they were added
|
|
370
|
+
- **Returning null**: Returning `null` discards the event and prevents future modifier functions from being executed
|
|
371
|
+
- **Performance**: Event modifiers should be efficient as they are called for every event
|
|
372
|
+
- **Field naming**: Custom properties must follow the `event_properties.*` or `session_properties.*` prefix naming convention
|
|
373
|
+
- **Reserved fields**: Certain reserved fields and namespaces cannot be modified. Attempts to modify them will be ignored
|
|
374
|
+
- **Error handling**: If a modifier throws an exception, it will be logged but won't prevent other modifiers from executing
|
|
375
|
+
- **Primitive values**: Event fields can only contain primitive values (String, int, double, bool)
|
|
376
|
+
- **Invalid argument**: In case you pass an invalid argument to `addEventModifier`, we return a no-op placeholder modifier.
|
|
351
377
|
|
|
352
|
-
|
|
378
|
+
### Send Exception Event
|
|
379
|
+
|
|
380
|
+
The `sendExceptionEvent()` method provides a structured way to report exceptions with additional context and custom properties using the ExceptionEventData class.
|
|
353
381
|
|
|
354
382
|
```ts
|
|
355
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
383
|
+
import { Dynatrace, ExceptionEventData } from '@dynatrace/react-native-plugin';
|
|
356
384
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
385
|
+
try {
|
|
386
|
+
// Code that may throw an error
|
|
387
|
+
throw new Error('Something went wrong');
|
|
388
|
+
} catch (error) {
|
|
389
|
+
if (error instanceof Error) {
|
|
390
|
+
Dynatrace.sendExceptionEvent(new ExceptionEventData(error)
|
|
391
|
+
.addEventProperty('event_properties.custom_key', 'custom_value')
|
|
392
|
+
.addEventProperty('event_properties.error_context', 'user_action')
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
362
396
|
```
|
|
363
|
-

|
|
364
397
|
|
|
365
|
-
|
|
398
|
+
**Parameters:**
|
|
399
|
+
* `error`: The Error object containing exception information (required)
|
|
366
400
|
|
|
367
|
-
|
|
401
|
+
### Send HTTP Request Event
|
|
402
|
+
|
|
403
|
+
The `sendHttpRequestEvent()` method allows you to manually report HTTP request events with detailed information about the request and response.
|
|
368
404
|
|
|
369
405
|
```ts
|
|
370
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
406
|
+
import { Dynatrace, HttpRequestEventData } from '@dynatrace/react-native-plugin';
|
|
371
407
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
408
|
+
// Basic HTTP request event
|
|
409
|
+
const requestEventData = new HttpRequestEventData('https://api.example.com/users', 'GET');
|
|
410
|
+
Dynatrace.sendHttpRequestEvent(requestEventData);
|
|
375
411
|
|
|
376
|
-
//
|
|
377
|
-
|
|
412
|
+
// HTTP request with additional details
|
|
413
|
+
const detailedRequestEventData = new HttpRequestEventData('https://api.example.com/data', 'POST')
|
|
414
|
+
.withStatusCode(200)
|
|
415
|
+
.addEventProperty('event_properties.headers.content_type', 'application/json');
|
|
416
|
+
Dynatrace.sendHttpRequestEvent(detailedRequestEventData);
|
|
378
417
|
```
|
|
379
418
|
|
|
380
|
-
|
|
419
|
+
**Parameters:**
|
|
420
|
+
* `url`: The URL of the HTTP request (required)
|
|
421
|
+
* `method`: The HTTP method (e.g., 'GET', 'POST', 'PUT', 'DELETE') (required)
|
|
381
422
|
|
|
382
|
-
|
|
423
|
+
### View Monitoring
|
|
383
424
|
|
|
384
|
-
|
|
385
|
-
Using this API will force the request to be added to the action that is manually created.
|
|
425
|
+
The view monitoring APIs allow you to track different screens or views in your application, providing context for all events happening within those views.
|
|
386
426
|
|
|
387
|
-
|
|
388
|
-
|
|
427
|
+
There are two ways to monitor views:
|
|
428
|
+
1. **Automatic view monitoring** - Enable navigation tracking in your configuration to automatically capture view changes through supported navigation libraries (enabled by default)
|
|
429
|
+
2. **Manual view monitoring** - Use the `startView()` API to manually control when view contexts are created and updated
|
|
389
430
|
|
|
390
|
-
|
|
391
|
-
const url = 'https://api.example.com/data';
|
|
392
|
-
const tag = await action.getRequestTag(url);
|
|
393
|
-
const timing = new DynatraceWebRequestTiming(tag, url);
|
|
431
|
+
> **Important:** These approaches should not be mixed, as the outcome is unpredictable. Choose either automatic or manual view monitoring for your application.
|
|
394
432
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
timing.stopWebRequestTiming(-1, error.message);
|
|
406
|
-
} else {
|
|
407
|
-
timing.stopWebRequestTiming(-1, (error as any).toString());
|
|
433
|
+
#### Automatic Navigation tracking
|
|
434
|
+
|
|
435
|
+
> **Note:** This feature only works with `@react-navigation` versions 5.x through 7.x.
|
|
436
|
+
|
|
437
|
+
The following is an example of how this feature can be configured in your `dynatrace.config.js` file. Note that this feature is enabled by default.
|
|
438
|
+
|
|
439
|
+
```js
|
|
440
|
+
react: {
|
|
441
|
+
navigation: {
|
|
442
|
+
enabled: true
|
|
408
443
|
}
|
|
409
|
-
} finally {
|
|
410
|
-
action.leaveAction();
|
|
411
444
|
}
|
|
412
445
|
```
|
|
413
|
-

|
|
414
446
|
|
|
415
|
-
|
|
447
|
+
When this feature is enabled, the view context will represent the current state of the `@react-navigation` `NavigationContainer`. The state gets represented as a URL-style route. All subsequent events get associated with the view context and thus with the current route.
|
|
416
448
|
|
|
417
|
-
|
|
418
|
-
|
|
449
|
+
For instance, assume the following setup:
|
|
450
|
+
```js
|
|
451
|
+
const Drawer = createDrawerNavigator();
|
|
419
452
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
453
|
+
function App() {
|
|
454
|
+
return (
|
|
455
|
+
<NavigationContainer>
|
|
456
|
+
<Drawer.Navigator initialRouteName="Home">
|
|
457
|
+
<Drawer.Screen name="Home" component={HomeScreen} />
|
|
458
|
+
<Drawer.Screen name="Feature" component={FeatureScreen}/>
|
|
459
|
+
</Drawer.Navigator>
|
|
460
|
+
</NavigationContainer>
|
|
461
|
+
);
|
|
462
|
+
}
|
|
425
463
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
body: requestData
|
|
435
|
-
});
|
|
436
|
-
const responseData = await response.text();
|
|
437
|
-
timing.stopWebRequestTimingWithSize(
|
|
438
|
-
response.status,
|
|
439
|
-
response.statusText,
|
|
440
|
-
requestData.length,
|
|
441
|
-
responseData.length
|
|
464
|
+
const Stack = createStackNavigator();
|
|
465
|
+
|
|
466
|
+
function FeatureScreen() {
|
|
467
|
+
return (
|
|
468
|
+
<Stack.Navigator initialRouteName="ScreenOne">
|
|
469
|
+
<Stack.Screen name="ScreenOne" component={NestedScreenOne} />
|
|
470
|
+
<Stack.Screen name="ScreenTwo" component={NestedScreenTwo} />
|
|
471
|
+
</Stack.Navigator>
|
|
442
472
|
);
|
|
443
|
-
} catch (error) {
|
|
444
|
-
if (error instanceof Error) {
|
|
445
|
-
timing.stopWebRequestTiming(-1, error.message);
|
|
446
|
-
} else {
|
|
447
|
-
timing.stopWebRequestTiming(-1, (error as any).toString());
|
|
448
|
-
}
|
|
449
|
-
} finally {
|
|
450
|
-
action.leaveAction();
|
|
451
473
|
}
|
|
452
474
|
```
|
|
453
|
-

|
|
454
475
|
|
|
455
|
-
|
|
476
|
+
When navigating to `Home`, the view context will be set to `/Home`. When navigating to `Feature` and being redirected to the nested `ScreenOne`, the view context will be set to `/Home/ScreenOne`. When navigating to `ScreenTwo` within `Feature`, the view context will be set to `/Feature/ScreenTwo`.
|
|
456
477
|
|
|
457
|
-
|
|
478
|
+
#### Start View
|
|
479
|
+
|
|
480
|
+
Use `startView()` to begin monitoring a specific view or screen. When a view is started, all subsequent events will be associated with that view context.
|
|
458
481
|
|
|
459
482
|
```ts
|
|
460
|
-
import {
|
|
483
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
461
484
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
reportError(errorName: string, errorCode: number, platform?: Platform): void;
|
|
465
|
-
reportEvent(eventName: string, platform?: Platform): void;
|
|
466
|
-
reportIntValue(valueName: string, value: number, platform?: Platform): void;
|
|
467
|
-
reportStringValue(valueName: string, value: string, platform?: Platform): void;
|
|
468
|
-
}
|
|
485
|
+
// Start monitoring a view
|
|
486
|
+
Dynatrace.startView("HomeScreen");
|
|
469
487
|
```
|
|
470
488
|
|
|
471
|
-
**Important:**
|
|
489
|
+
**Important Considerations:**
|
|
490
|
+
* Only one view can be active at a time
|
|
491
|
+
* Starting a new view will automatically stop the previous one
|
|
492
|
+
* View names should be meaningful and consistent across your application
|
|
493
|
+
* All events captured after starting a view will include the view context
|
|
472
494
|
|
|
473
|
-
|
|
495
|
+
**Complete Example:**
|
|
474
496
|
|
|
475
497
|
```ts
|
|
476
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
498
|
+
import { Dynatrace, EventData } from '@dynatrace/react-native-plugin';
|
|
477
499
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
myAction.leaveAction();
|
|
481
|
-
```
|
|
482
|
-

|
|
500
|
+
// User navigates to profile screen
|
|
501
|
+
Dynatrace.startView("UserProfile");
|
|
483
502
|
|
|
484
|
-
|
|
503
|
+
// Send custom event within the view
|
|
504
|
+
Dynatrace.sendEvent(new EventData()
|
|
505
|
+
.addEventProperty("event_properties.profile_action", "edit_profile")
|
|
506
|
+
.addEventProperty("event_properties.changes_made", true)
|
|
507
|
+
);
|
|
485
508
|
|
|
509
|
+
// User navigates away
|
|
510
|
+
Dynatrace.startView("UserProfileDetailed");
|
|
511
|
+
```
|
|
486
512
|
|
|
487
|
-
###
|
|
513
|
+
### User Interaction
|
|
488
514
|
|
|
489
|
-
|
|
515
|
+
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.
|
|
490
516
|
|
|
491
|
-
|
|
492
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
517
|
+
The following is an example of how this feature can be configured in your `dynatrace.config.js` file. Note that this feature is enabled by default.
|
|
493
518
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
if (error instanceof Error) {
|
|
498
|
-
Dynatrace.reportErrorStacktrace(
|
|
499
|
-
'DatabaseError',
|
|
500
|
-
error.message,
|
|
501
|
-
'Failed to connect to remote database',
|
|
502
|
-
error.stack || 'No stack trace available'
|
|
503
|
-
);
|
|
504
|
-
}
|
|
519
|
+
```js
|
|
520
|
+
react: {
|
|
521
|
+
userInteraction: true
|
|
505
522
|
}
|
|
506
523
|
```
|
|
507
|
-

|
|
508
|
-
|
|
509
|
-
**Note:**
|
|
510
|
-
The previous API without *errorValue* is deprecated and will be removed in the future. Please use the new API with errorValue if possible.
|
|
511
524
|
|
|
512
|
-
|
|
525
|
+
When enabled, UI Interaction can be controlled by two layers:
|
|
513
526
|
|
|
514
|
-
|
|
527
|
+
1. **Build/config layer (`dynatrace.config.js`)**
|
|
528
|
+
- `react.userInteraction: true|false` controls whether the UI Interaction instrumentation feature is applied.
|
|
515
529
|
|
|
516
|
-
**
|
|
530
|
+
2. **Runtime remote layer**
|
|
531
|
+
- CP always forwards User Interaction Actions (UIA) to the native agent unconditionally. The native agent decides whether to record or discard each UIA based on its own remote configuration (e.g. `touch_interaction_enabled`).
|
|
517
532
|
|
|
518
|
-
|
|
519
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
533
|
+
#### Masking sensitive UI labels
|
|
520
534
|
|
|
521
|
-
|
|
522
|
-
```
|
|
523
|
-

|
|
535
|
+
UI Interaction also supports masking sensitive labels before events are sent.
|
|
524
536
|
|
|
525
|
-
|
|
537
|
+
Masking is applied when:
|
|
526
538
|
|
|
527
|
-
|
|
539
|
+
* the touched element or one of its parents is marked with `dtMask`
|
|
540
|
+
* the runtime masking rules classify the detected text as sensitive
|
|
541
|
+
* the runtime masking rules classify the element `testID` as sensitive
|
|
528
542
|
|
|
529
|
-
|
|
530
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
543
|
+
When masking is active:
|
|
531
544
|
|
|
532
|
-
|
|
533
|
-
|
|
545
|
+
* the interaction path and component information are still reported
|
|
546
|
+
* the detected UI label is replaced with the configured replacement string (default: `***`)
|
|
547
|
+
* `ui_element.name_origin` is reported as `masked`
|
|
534
548
|
|
|
535
|
-
|
|
549
|
+
Example using `dtMask`:
|
|
536
550
|
|
|
537
|
-
|
|
551
|
+
```tsx
|
|
552
|
+
<View dtMask>
|
|
553
|
+
<Pressable onPress={onPress}>
|
|
554
|
+
<Text>john.doe@example.com</Text>
|
|
555
|
+
</Pressable>
|
|
556
|
+
</View>
|
|
557
|
+
```
|
|
538
558
|
|
|
539
|
-
|
|
559
|
+
This allows you to preserve interaction analytics while avoiding exposure of sensitive text in the emitted UI Interaction event.
|
|
540
560
|
|
|
541
|
-
```ts
|
|
542
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
543
561
|
|
|
544
|
-
|
|
545
|
-
throw new Error('Fatal memory allocation failure');
|
|
546
|
-
} catch (error) {
|
|
547
|
-
if (error instanceof Error) {
|
|
548
|
-
Dynatrace.reportCrash(
|
|
549
|
-
'MemoryError',
|
|
550
|
-
error.message,
|
|
551
|
-
error.stack || 'No stack trace available'
|
|
552
|
-
);
|
|
562
|
+
#### Produced data
|
|
553
563
|
|
|
554
|
-
|
|
555
|
-
Dynatrace.reportCrashWithException('MemoryError', error);
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
```
|
|
559
|
-

|
|
564
|
+
Each captured interaction produces an event describing what the user touched and where. The event includes:
|
|
560
565
|
|
|
561
|
-
|
|
566
|
+
- **Detected name** — the resolved label of the touched element, derived from its visible text, accessibility label, component name, or test ID.
|
|
567
|
+
- **Component** — the type of the UI component that was touched (e.g. `Pressable`).
|
|
568
|
+
- **Component Path** — a stable path through the component tree that uniquely identifies the element (e.g. `App/View[1]/Pressable[1]`).
|
|
569
|
+
- **Interaction type** — how the user interacted (e.g. `touch`).
|
|
570
|
+
- **Position** — the screen coordinates where the touch occurred.
|
|
562
571
|
|
|
563
|
-
|
|
572
|
+
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.
|
|
564
573
|
|
|
565
|
-
|
|
574
|
+
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`.
|
|
566
575
|
|
|
567
|
-
|
|
576
|
+
#### Example event
|
|
568
577
|
|
|
569
|
-
```
|
|
570
|
-
|
|
571
|
-
|
|
578
|
+
```json
|
|
579
|
+
{
|
|
580
|
+
"characteristics.has_user_interaction": true,
|
|
581
|
+
"ui_element.detected_name": "LoginButton",
|
|
582
|
+
"ui_element.components": ["Pressable"],
|
|
583
|
+
"ui_element.id": "App/View/Pressable",
|
|
584
|
+
"ui_element.name_origin": "component",
|
|
585
|
+
"interaction.type": "touch",
|
|
586
|
+
"positions": [{ "x": 120, "y": 460 }],
|
|
587
|
+
"ui_element.responder.detected_name": "Pressable",
|
|
588
|
+
"ui_element.responder.components": ["Pressable"],
|
|
589
|
+
"ui_element.responder.id": "App/View[/Pressable",
|
|
590
|
+
"ui_element.responder.name_origin": "component"
|
|
572
591
|
}
|
|
573
592
|
```
|
|
574
593
|
|
|
575
|
-
|
|
576
|
-
2. Performance: Native Agent captures only anonymous performance data. Monitoring data that can be used to identify individual users, such as user tags and custom values, aren't captured.
|
|
577
|
-
3. UserBehavior: Native Agent captures both performance and user data. In this mode, Native Agent recognizes and reports users who re-visit in future sessions.
|
|
594
|
+
#### Custom Names for Components
|
|
578
595
|
|
|
579
|
-
|
|
596
|
+
You can assign custom names to your components. A custom name affects both the **Component** and the **Component Path** described above. There are two ways to do this, depending on how the component is used.
|
|
580
597
|
|
|
581
|
-
|
|
598
|
+
##### 1. As a JSX prop (`dtActionName`)
|
|
582
599
|
|
|
583
|
-
|
|
584
|
-
import { Platform, UserPrivacyOptions } from '@dynatrace/react-native-plugin';
|
|
600
|
+
Use this when you render the component as JSX. Pass `dtActionName` as a prop, and it overrides the auto-detected name for that specific usage:
|
|
585
601
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
602
|
+
```tsx
|
|
603
|
+
<TouchableOpacity dtActionName="Checkout Button" onPress={onCheckout}>
|
|
604
|
+
<Text dtActionName="Checkout Text">Buy now</Text>
|
|
605
|
+
</TouchableOpacity>
|
|
590
606
|
```
|
|
591
607
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
```ts
|
|
595
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
608
|
+
Touching it produces:
|
|
596
609
|
|
|
597
|
-
|
|
610
|
+
```json
|
|
611
|
+
"ui_element.components": ["Checkout Text"],
|
|
612
|
+
"ui_element.id": ".../Checkout Button/Checkout Text"
|
|
598
613
|
```
|
|
599
614
|
|
|
600
|
-
|
|
615
|
+
##### 2. As a static property (`Component.dtActionName`)
|
|
601
616
|
|
|
602
|
-
|
|
603
|
-
import { Dynatrace, DataCollectionLevel, UserPrivacyOptions } from '@dynatrace/react-native-plugin';
|
|
617
|
+
Use this when the component is **not** rendered as JSX, so the prop approach above is not available — for example, a screen component you define once and hand to a navigator by reference. Set `dtActionName` directly on the component. This affects **every** place the component is used at once:
|
|
604
618
|
|
|
605
|
-
|
|
619
|
+
```tsx
|
|
620
|
+
import { NavigationContainer } from '@react-navigation/native';
|
|
621
|
+
import { createDrawerNavigator } from '@react-navigation/drawer';
|
|
606
622
|
|
|
607
|
-
|
|
608
|
-
privacyConfig.crashReportingOptedIn = false;
|
|
609
|
-
privacyConfig.dataCollectionLevel = DataCollectionLevel.Performance;
|
|
623
|
+
const Drawer = createDrawerNavigator();
|
|
610
624
|
|
|
611
|
-
|
|
612
|
-
|
|
625
|
+
function ProfileScreen() {
|
|
626
|
+
return (/* ... */);
|
|
627
|
+
}
|
|
613
628
|
|
|
614
|
-
|
|
615
|
-
|
|
629
|
+
// Applies to all usages of ProfileScreen below
|
|
630
|
+
ProfileScreen.dtActionName = 'User Profile';
|
|
616
631
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
632
|
+
function App() {
|
|
633
|
+
return (
|
|
634
|
+
<NavigationContainer>
|
|
635
|
+
<Drawer.Navigator>
|
|
636
|
+
{/* Both screens reference the same component,
|
|
637
|
+
so both pick up the 'User Profile' name */}
|
|
638
|
+
<Drawer.Screen name="Me" component={ProfileScreen} />
|
|
639
|
+
<Drawer.Screen name="Account" component={ProfileScreen} />
|
|
640
|
+
</Drawer.Navigator>
|
|
641
|
+
</NavigationContainer>
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
```
|
|
620
645
|
|
|
621
|
-
|
|
622
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
646
|
+
Touches inside one of the 2 screens now produce:
|
|
623
647
|
|
|
624
|
-
|
|
648
|
+
```json
|
|
649
|
+
"ui_element.id": ".../User Profile/..."
|
|
625
650
|
```
|
|
626
651
|
|
|
627
|
-
|
|
652
|
+
> **Note:** The static property applies to *all* uses of the component. If you need a different name per usage, render the component as JSX and use the `dtActionName` prop (option 1) instead.
|
|
653
|
+
>
|
|
654
|
+
> **Note:** The static property has no effect when a component is rendered as JSX. In that case the name is taken from either the `dtActionName` prop passed to it (option 1) or the name of the JSX component.
|
|
628
655
|
|
|
629
|
-
|
|
630
|
-
* Passing to **iOS** only:
|
|
631
|
-
```ts
|
|
632
|
-
import { Dynatrace, Platform } from '@dynatrace/react-native-plugin';
|
|
656
|
+
### React Native Symbolication
|
|
633
657
|
|
|
634
|
-
|
|
635
|
-
//Perform the action and whatever else is needed.
|
|
636
|
-
myAction.leaveAction(Platform.Ios);
|
|
637
|
-
```
|
|
638
|
-
|
|
639
|
-
* Passing to **Android** only:
|
|
640
|
-
```ts
|
|
641
|
-
import { Dynatrace, Platform } from '@dynatrace/react-native-plugin';
|
|
658
|
+
Dynatrace can automatically symbolicate JavaScript stack traces captured by the plugin using sourcemaps. This allows you to view human-readable file names, line numbers, and column information in your crash reports.
|
|
642
659
|
|
|
643
|
-
|
|
644
|
-
//Perform the action and whatever else is needed.
|
|
645
|
-
myAction.leaveAction(Platform.Android);
|
|
646
|
-
```
|
|
647
|
-
|
|
648
|
-
* Passing to **both**:
|
|
649
|
-
```ts
|
|
650
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
660
|
+
#### Generating Sourcemaps
|
|
651
661
|
|
|
652
|
-
|
|
653
|
-
//Perform the action and whatever else is needed.
|
|
654
|
-
myAction.leaveAction();
|
|
655
|
-
```
|
|
662
|
+
Sourcemaps are generated during release builds and map bytecode offsets (Hermes) and locations in the minified JavaScript bundle (JavaScriptCore) back to your original source code. We support sourcemaps for both Hermes and JavaScriptCore. For detailed instructions on generating sourcemaps, see the [React Native debugging release builds guide](https://reactnative.dev/docs/debugging-release-builds).
|
|
656
663
|
|
|
657
|
-
|
|
664
|
+
To generate a sourcemap:
|
|
658
665
|
|
|
659
|
-
|
|
666
|
+
**Android:**
|
|
667
|
+
* Run `npx react-native run-android --mode release` in your project root, or
|
|
668
|
+
* Run `gradlew assembleRelease` in the `/android` directory
|
|
660
669
|
|
|
661
|
-
|
|
670
|
+
**iOS:**
|
|
671
|
+
* First, enable sourcemaps according to the [React Native debugging release builds guide](https://reactnative.dev/docs/debugging-release-builds)
|
|
672
|
+
* Then run `npx react-native run-ios --mode Release`, or
|
|
673
|
+
* Build for release in Xcode
|
|
662
674
|
|
|
663
|
-
|
|
664
|
-
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
675
|
+
#### Uploading Sourcemaps
|
|
665
676
|
|
|
666
|
-
Dynatrace.
|
|
667
|
-
"event.name" : "Confirmed Booking",
|
|
668
|
-
"screen": "booking-confirmation",
|
|
669
|
-
"product": "Danube Anna Hotel",
|
|
670
|
-
"amount": 358.35,
|
|
671
|
-
"currency": "USD",
|
|
672
|
-
"reviewScore": 4.8,
|
|
673
|
-
"arrivalDate": "2022-11-05",
|
|
674
|
-
"departureDate": "2022-11-15",
|
|
675
|
-
"journeyDuration": 10,
|
|
676
|
-
"adultTravelers": 2,
|
|
677
|
-
"childrenTravelers": 0
|
|
678
|
-
});
|
|
679
|
-
```
|
|
680
|
-

|
|
677
|
+
Once generated, 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).
|
|
681
678
|
|
|
682
|
-
|
|
679
|
+
## RUM Classic
|
|
683
680
|
|
|
684
|
-
|
|
681
|
+
### Monitor a Component
|
|
685
682
|
|
|
686
|
-
|
|
683
|
+
A component can be either monitored automatically or manually. The auto instrumentation is handled via the dynatrace.config.js file. If you want to manually instrument a component you can use the API call `withMonitoring`.
|
|
684
|
+
|
|
685
|
+
* Example with Functional Component:
|
|
687
686
|
|
|
688
687
|
```ts
|
|
689
688
|
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
689
|
+
import { FunctionComponent } from 'react';
|
|
690
690
|
|
|
691
|
-
const
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
```
|
|
691
|
+
export const MyFunctionalComponent: FunctionComponent<{}> = () => {
|
|
692
|
+
return null;
|
|
693
|
+
}
|
|
695
694
|
|
|
696
|
-
|
|
695
|
+
Dynatrace.withMonitoring(MyFunctionalComponent, "MyFunctionalComponent");
|
|
696
|
+
```
|
|
697
|
+

|
|
697
698
|
|
|
698
|
-
|
|
699
|
+
The String "MyFunctionalComponent" is optional as the name of the component can be retrieved through [different properties](#how-does-dynatrace-determine-the-user-action-name).
|
|
699
700
|
|
|
700
|
-
|
|
701
|
-
import React from 'react';
|
|
702
|
-
import { TouchableHighlight, Text, View } from 'react-native';
|
|
701
|
+
Combining manual and auto instrumentation should not be a problem. As they're running the same execution, the manual instrumentation will only override the content of auto instrumentation happening through the transformer.
|
|
703
702
|
|
|
704
|
-
|
|
705
|
-
return (
|
|
706
|
-
<View>
|
|
707
|
-
<TouchableHighlight onPress={onPress}>
|
|
708
|
-
<Text>TouchableHighlight that will be monitored</Text>
|
|
709
|
-
</TouchableHighlight>
|
|
710
|
-
<TouchableHighlight onPress={onPress} dtActionIgnore="true">
|
|
711
|
-
<Text>TouchableHighlight that will be ignored</Text>
|
|
712
|
-
</TouchableHighlight>
|
|
713
|
-
</View>
|
|
714
|
-
);
|
|
715
|
-
};
|
|
703
|
+
### Create custom actions
|
|
716
704
|
|
|
717
|
-
|
|
718
|
-
console.log("TouchableHighlight Pressed!");
|
|
719
|
-
};
|
|
705
|
+
There are two options to create an action. Either using `enterAutoAction` (the previous `enterAction`) or `enterManualAction`:
|
|
720
706
|
|
|
721
|
-
|
|
722
|
-
```
|
|
707
|
+
**Important:** Action names are limited to 250 characters and will be truncated if they exceed this limit.
|
|
723
708
|
|
|
724
|
-
|
|
709
|
+
* `enterAutoAction` - Creates an Action which will be automatically handled by the plugin (This is the type of action which is internally used by the plugin when monitoring components and touchables). This means that the plugin decides about the hierarchy of this action. If there is no open action, the following action will be a root action. All other actions created by this method, while a root action is open, will be automatically inserted as a child action. Furthermore the plugin will automatically link webrequest (if they are not tagged manually) to the open root action. Be aware that the timeout/wait time for sub actions or web requests cannot be modified on the Android side for React Native Auto actions. The timeout is fixed to a 1000ms.
|
|
725
710
|
|
|
726
|
-
|
|
711
|
+
```ts
|
|
712
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
727
713
|
|
|
728
|
-
|
|
714
|
+
const myAction = Dynatrace.enterAutoAction("MyButton tapped");
|
|
715
|
+
//Perform the action and whatever else is needed.
|
|
716
|
+
myAction.leaveAction();
|
|
717
|
+
```
|
|
718
|
+

|
|
729
719
|
|
|
730
|
-
|
|
720
|
+
* `enterManualAction` - Creates an Action which will NOT be handled by the plugin. This means that you have full control about the hierarchy of your actions. This function will create a root action for you, which has the ability to create child actions via `enterAction`. Be aware, because of the full manual approach the plugin will not link webrequest automatically. Webrequest have to be manually tagged by using the tag provided by the action via `getRequestTag`.
|
|
731
721
|
|
|
732
|
-
|
|
722
|
+
```ts
|
|
723
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
733
724
|
|
|
734
|
-
|
|
725
|
+
const myAction = Dynatrace.enterManualAction("MyButton tapped");
|
|
726
|
+
//Perform the action and whatever else is needed.
|
|
727
|
+
myAction.leaveAction();
|
|
728
|
+
```
|
|
735
729
|
|
|
736
|
-
|
|
730
|
+
To create a custom action named `"MyButton tapped"`, use the following code. The *leaveAction* closes the action again. To report values for this action before closing, see [Report Values](#report-values).
|
|
737
731
|
|
|
738
732
|
```ts
|
|
739
|
-
import { Dynatrace
|
|
733
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
740
734
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
.addEventProperty("event_properties.user_type", "premium")
|
|
745
|
-
.addEventProperty("event_properties.attempt_count", 3)
|
|
746
|
-
.withDuration(250)
|
|
747
|
-
);
|
|
735
|
+
const myAction = Dynatrace.enterAutoAction("MyButton tapped");
|
|
736
|
+
//Perform the action and whatever else is needed.
|
|
737
|
+
myAction.leaveAction();
|
|
748
738
|
```
|
|
749
739
|
|
|
750
|
-
|
|
751
|
-
* Only properties prefixed with `event_properties.*` are allowed
|
|
752
|
-
* Additionally, the `duration` property is allowed
|
|
753
|
-
* Maximum of 50 custom properties per event
|
|
754
|
-
* If the limit is exceeded, properties are sorted alphabetically by key and excess properties are dropped deterministically
|
|
755
|
-
* String properties are limited to 5000 characters (exceeding characters are truncated)
|
|
756
|
-
* Field names must contain only alphabetic characters, numbers, underscores, and dots
|
|
757
|
-
* Each dot must be followed by an alphabetic character
|
|
758
|
-
* Each underscore must be followed by an alphabetic character or number
|
|
759
|
-
* Values must be primitive types (string, number, boolean)
|
|
760
|
-
* Cannot contain functions, undefined, Infinity, or NaN as values (they will be replaced with null)
|
|
740
|
+
### Create custom sub actions
|
|
761
741
|
|
|
762
|
-
|
|
742
|
+
You can create a single custom action as well as sub actions. The `MyButton Sub Action` is automatically put under the `MyButton tapped`. As long as `MyButton tapped` is open, it gathers all the web requests.
|
|
763
743
|
|
|
764
|
-
|
|
744
|
+
**Important:** Action names are limited to 250 characters and will be truncated if they exceed this limit.
|
|
765
745
|
|
|
766
746
|
```ts
|
|
767
|
-
import { Dynatrace
|
|
747
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
768
748
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
);
|
|
749
|
+
const myAction = Dynatrace.enterManualAction("MyButton tapped");
|
|
750
|
+
const mySubAction = myAction.enterAction("MyButton Sub Action");
|
|
751
|
+
//Perform the action and whatever else is needed.
|
|
752
|
+
mySubAction.leaveAction();
|
|
753
|
+
myAction.leaveAction();
|
|
775
754
|
```
|
|
755
|
+

|
|
776
756
|
|
|
777
|
-
|
|
778
|
-
* Session properties persist throughout the entire session
|
|
779
|
-
* If you send the same property multiple times, only one value will be kept (first or last)
|
|
780
|
-
* Use session properties for data that applies to the entire user session
|
|
781
|
-
* Field naming follows the same rules as events, but with `session_properties.` prefix
|
|
782
|
-
* Maximum of 50 custom properties per event
|
|
783
|
-
* If the limit is exceeded, properties are sorted alphabetically by key and excess properties are dropped deterministically
|
|
784
|
-
|
|
785
|
-
### Event Modifier
|
|
757
|
+
### Cancel actions
|
|
786
758
|
|
|
787
|
-
|
|
759
|
+
Actions can be canceled. That means they will not be sent and discarded fully. This also means that any values and sub actions attached to the action will be removed.
|
|
788
760
|
|
|
789
|
-
|
|
761
|
+
```ts
|
|
762
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
790
763
|
|
|
791
|
-
|
|
764
|
+
const myAction = Dynatrace.enterAutoAction("MyButton tapped");
|
|
765
|
+
// Action will be canceled
|
|
766
|
+
myAction.cancel();
|
|
792
767
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
768
|
+
// Has no impact as the action is already canceled
|
|
769
|
+
myAction.leaveAction();
|
|
770
|
+
```
|
|
796
771
|
|
|
797
|
-
|
|
772
|
+
### Manual Web Request Tagging
|
|
798
773
|
|
|
799
|
-
|
|
800
|
-
- `url.full`
|
|
801
|
-
- `exception.stack_trace`
|
|
774
|
+
You can manually tag and time your web requests. With the API shown below, you are able to manually capture the web requests of an http framework/library.
|
|
802
775
|
|
|
803
|
-
|
|
776
|
+
**Note:**
|
|
777
|
+
Using this API will force the request to be added to the action that is manually created.
|
|
804
778
|
|
|
805
779
|
```ts
|
|
806
|
-
import { Dynatrace,
|
|
780
|
+
import { Dynatrace, DynatraceWebRequestTiming } from '@dynatrace/react-native-plugin';
|
|
807
781
|
|
|
808
|
-
|
|
809
|
-
const
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
782
|
+
const action = Dynatrace.enterManualAction('API Data Fetch');
|
|
783
|
+
const url = 'https://api.example.com/data';
|
|
784
|
+
const tag = await action.getRequestTag(url);
|
|
785
|
+
const timing = new DynatraceWebRequestTiming(tag, url);
|
|
786
|
+
|
|
787
|
+
try {
|
|
788
|
+
timing.startWebRequestTiming();
|
|
789
|
+
const response = await fetch(url, {
|
|
790
|
+
headers: {
|
|
791
|
+
[timing.getRequestTagHeader()]: tag
|
|
818
792
|
}
|
|
819
|
-
|
|
820
|
-
|
|
793
|
+
});
|
|
794
|
+
timing.stopWebRequestTiming(response.status, response.statusText);
|
|
795
|
+
} catch (error) {
|
|
796
|
+
if (error instanceof Error) {
|
|
797
|
+
timing.stopWebRequestTiming(-1, error.message);
|
|
798
|
+
} else {
|
|
799
|
+
timing.stopWebRequestTiming(-1, (error as any).toString());
|
|
821
800
|
}
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
Dynatrace.addEventModifier(myModifier);
|
|
826
|
-
|
|
827
|
-
// Remove the modifier when no longer needed
|
|
828
|
-
Dynatrace.removeEventModifier(myModifier);
|
|
801
|
+
} finally {
|
|
802
|
+
action.leaveAction();
|
|
803
|
+
}
|
|
829
804
|
```
|
|
805
|
+

|
|
830
806
|
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
- **Execution order**: If multiple event modifiers are added, they are executed in the order they were added
|
|
834
|
-
- **Returning null**: Returning `null` discards the event and prevents future modifier functions from being executed
|
|
835
|
-
- **Performance**: Event modifiers should be efficient as they are called for every event
|
|
836
|
-
- **Field naming**: Custom properties must follow the `event_properties.*` or `session_properties.*` prefix naming convention
|
|
837
|
-
- **Reserved fields**: Certain reserved fields and namespaces cannot be modified. Attempts to modify them will be ignored
|
|
838
|
-
- **Error handling**: If a modifier throws an exception, it will be logged but won't prevent other modifiers from executing
|
|
839
|
-
- **Primitive values**: Event fields can only contain primitive values (String, int, double, bool)
|
|
840
|
-
- **Invalid argument**: In case you pass an invalid argument to `addEventModifier`, we return a no-op placeholder modifier.
|
|
841
|
-
|
|
842
|
-
### Send Exception Event
|
|
843
|
-
|
|
844
|
-
The `sendExceptionEvent()` method provides a structured way to report exceptions with additional context and custom properties using the ExceptionEventData class.
|
|
807
|
+
There is also the option to report values for request and response size:
|
|
845
808
|
|
|
846
809
|
```ts
|
|
847
|
-
import { Dynatrace,
|
|
810
|
+
import { Dynatrace, DynatraceWebRequestTiming } from '@dynatrace/react-native-plugin';
|
|
811
|
+
|
|
812
|
+
const action = Dynatrace.enterManualAction('API Data Upload');
|
|
813
|
+
const url = 'https://api.example.com/upload';
|
|
814
|
+
const tag = await action.getRequestTag(url);
|
|
815
|
+
const timing = new DynatraceWebRequestTiming(tag, url);
|
|
816
|
+
const requestData = JSON.stringify({ key: 'value' });
|
|
848
817
|
|
|
849
818
|
try {
|
|
850
|
-
|
|
851
|
-
|
|
819
|
+
timing.startWebRequestTiming();
|
|
820
|
+
const response = await fetch(url, {
|
|
821
|
+
method: 'POST',
|
|
822
|
+
headers: {
|
|
823
|
+
[timing.getRequestTagHeader()]: tag,
|
|
824
|
+
'Content-Type': 'application/json'
|
|
825
|
+
},
|
|
826
|
+
body: requestData
|
|
827
|
+
});
|
|
828
|
+
const responseData = await response.text();
|
|
829
|
+
timing.stopWebRequestTimingWithSize(
|
|
830
|
+
response.status,
|
|
831
|
+
response.statusText,
|
|
832
|
+
requestData.length,
|
|
833
|
+
responseData.length
|
|
834
|
+
);
|
|
852
835
|
} catch (error) {
|
|
853
836
|
if (error instanceof Error) {
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
);
|
|
837
|
+
timing.stopWebRequestTiming(-1, error.message);
|
|
838
|
+
} else {
|
|
839
|
+
timing.stopWebRequestTiming(-1, (error as any).toString());
|
|
858
840
|
}
|
|
841
|
+
} finally {
|
|
842
|
+
action.leaveAction();
|
|
859
843
|
}
|
|
860
844
|
```
|
|
845
|
+

|
|
861
846
|
|
|
862
|
-
|
|
863
|
-
* `error`: The Error object containing exception information (required)
|
|
864
|
-
|
|
865
|
-
### Send HTTP Request Event
|
|
847
|
+
### Report values
|
|
866
848
|
|
|
867
|
-
|
|
849
|
+
For any open action you can report certain values. The following API is available for action:
|
|
868
850
|
|
|
869
851
|
```ts
|
|
870
|
-
import {
|
|
871
|
-
|
|
872
|
-
// Basic HTTP request event
|
|
873
|
-
const requestEventData = new HttpRequestEventData('https://api.example.com/users', 'GET');
|
|
874
|
-
Dynatrace.sendHttpRequestEvent(requestEventData);
|
|
852
|
+
import { Platform } from '@dynatrace/react-native-plugin';
|
|
875
853
|
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
854
|
+
interface IDynatraceAction {
|
|
855
|
+
reportDoubleValue(valueName: string, value: number, platform?: Platform): void;
|
|
856
|
+
reportError(errorName: string, errorCode: number, platform?: Platform): void;
|
|
857
|
+
reportEvent(eventName: string, platform?: Platform): void;
|
|
858
|
+
reportIntValue(valueName: string, value: number, platform?: Platform): void;
|
|
859
|
+
reportStringValue(valueName: string, value: string, platform?: Platform): void;
|
|
860
|
+
}
|
|
881
861
|
```
|
|
882
862
|
|
|
883
|
-
**
|
|
884
|
-
* `url`: The URL of the HTTP request (required)
|
|
885
|
-
* `method`: The HTTP method (e.g., 'GET', 'POST', 'PUT', 'DELETE') (required)
|
|
886
|
-
|
|
887
|
-
### View Monitoring
|
|
888
|
-
|
|
889
|
-
The view monitoring APIs allow you to track different screens or views in your application, providing context for all events happening within those views.
|
|
890
|
-
|
|
891
|
-
There are two ways to monitor views:
|
|
892
|
-
1. **Automatic view monitoring** - Enable navigation tracking in your configuration to automatically capture view changes through supported navigation libraries (enabled by default)
|
|
893
|
-
2. **Manual view monitoring** - Use the `startView()` API to manually control when view contexts are created and updated
|
|
894
|
-
|
|
895
|
-
> **Important:** These approaches should not be mixed, as the outcome is unpredictable. Choose either automatic or manual view monitoring for your application.
|
|
896
|
-
|
|
897
|
-
#### Automatic Navigation tracking
|
|
863
|
+
**Important:** All string parameters (errorName, eventName, valueName, value) are limited to 250 characters and will be truncated if they exceed this limit.
|
|
898
864
|
|
|
899
|
-
|
|
865
|
+
To report a string value, use the following:
|
|
900
866
|
|
|
901
|
-
|
|
867
|
+
```ts
|
|
868
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
902
869
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
enabled: true
|
|
907
|
-
}
|
|
908
|
-
}
|
|
870
|
+
const myAction = Dynatrace.enterAutoAction("MyButton tapped");
|
|
871
|
+
myAction.reportStringValue("ValueName", "ImportantValue");
|
|
872
|
+
myAction.leaveAction();
|
|
909
873
|
```
|
|
874
|
+

|
|
910
875
|
|
|
911
|
-
|
|
876
|
+
If you look at the API calls, you will see the optional parameter `platform?: Platform`. This parameter offers the possibility to report values only for a specific platform. to know more, see [Platform independent reporting](#platform-independent-reporting).
|
|
912
877
|
|
|
913
|
-
For instance, assume the following setup:
|
|
914
|
-
```js
|
|
915
|
-
const Drawer = createDrawerNavigator();
|
|
916
878
|
|
|
917
|
-
|
|
918
|
-
return (
|
|
919
|
-
<NavigationContainer>
|
|
920
|
-
<Drawer.Navigator initialRouteName="Home">
|
|
921
|
-
<Drawer.Screen name="Home" component={HomeScreen} />
|
|
922
|
-
<Drawer.Screen name="Feature" component={FeatureScreen}/>
|
|
923
|
-
</Drawer.Navigator>
|
|
924
|
-
</NavigationContainer>
|
|
925
|
-
);
|
|
926
|
-
}
|
|
879
|
+
### Report an error stacktrace
|
|
927
880
|
|
|
928
|
-
|
|
881
|
+
To manually report an error stacktrace, use the following API call:
|
|
929
882
|
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
)
|
|
883
|
+
```ts
|
|
884
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
885
|
+
|
|
886
|
+
try {
|
|
887
|
+
throw new Error('Database connection failed');
|
|
888
|
+
} catch (error) {
|
|
889
|
+
if (error instanceof Error) {
|
|
890
|
+
Dynatrace.reportErrorStacktrace(
|
|
891
|
+
'DatabaseError',
|
|
892
|
+
error.message,
|
|
893
|
+
'Failed to connect to remote database',
|
|
894
|
+
error.stack || 'No stack trace available'
|
|
895
|
+
);
|
|
896
|
+
}
|
|
937
897
|
}
|
|
938
898
|
```
|
|
899
|
+

|
|
939
900
|
|
|
940
|
-
|
|
901
|
+
**Note:**
|
|
902
|
+
The previous API without *errorValue* is deprecated and will be removed in the future. Please use the new API with errorValue if possible.
|
|
941
903
|
|
|
942
|
-
|
|
904
|
+
### Manually report a crash
|
|
943
905
|
|
|
944
|
-
|
|
906
|
+
You can manually report a crash via the following API calls:
|
|
945
907
|
|
|
946
908
|
```ts
|
|
947
909
|
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
948
910
|
|
|
949
|
-
|
|
950
|
-
|
|
911
|
+
try {
|
|
912
|
+
throw new Error('Fatal memory allocation failure');
|
|
913
|
+
} catch (error) {
|
|
914
|
+
if (error instanceof Error) {
|
|
915
|
+
Dynatrace.reportCrash(
|
|
916
|
+
'MemoryError',
|
|
917
|
+
error.message,
|
|
918
|
+
error.stack || 'No stack trace available'
|
|
919
|
+
);
|
|
920
|
+
|
|
921
|
+
// or directly via the full error
|
|
922
|
+
Dynatrace.reportCrashWithException('MemoryError', error);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
951
925
|
```
|
|
926
|
+

|
|
952
927
|
|
|
953
|
-
**
|
|
954
|
-
* Only one view can be active at a time
|
|
955
|
-
* Starting a new view will automatically stop the previous one
|
|
956
|
-
* View names should be meaningful and consistent across your application
|
|
957
|
-
* All events captured after starting a view will include the view context
|
|
928
|
+
> **Note**: If you use this API call to report a crash manually, it will force the session to be completed. Any new actions that are captured afterwards will be added into a new session.
|
|
958
929
|
|
|
959
|
-
|
|
930
|
+
*reportCrashWithException* will use the crashName as name for the crash. It will only report the crash if there is also a stacktrace available.
|
|
960
931
|
|
|
961
|
-
|
|
962
|
-
import { Dynatrace, EventData } from '@dynatrace/react-native-plugin';
|
|
932
|
+
### Report GPS Location
|
|
963
933
|
|
|
964
|
-
|
|
965
|
-
Dynatrace.startView("UserProfile");
|
|
934
|
+
You can report latitude and longitude and specify an optional platform.
|
|
966
935
|
|
|
967
|
-
|
|
968
|
-
Dynatrace
|
|
969
|
-
.addEventProperty("event_properties.profile_action", "edit_profile")
|
|
970
|
-
.addEventProperty("event_properties.changes_made", true)
|
|
971
|
-
);
|
|
936
|
+
```ts
|
|
937
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
972
938
|
|
|
973
|
-
|
|
974
|
-
Dynatrace.startView("UserProfileDetailed");
|
|
939
|
+
Dynatrace.setGPSLocation(48.31518732698596, 14.305245274594471);
|
|
975
940
|
```
|
|
976
941
|
|
|
977
|
-
###
|
|
942
|
+
### Platform independent reporting
|
|
978
943
|
|
|
979
|
-
|
|
944
|
+
You probably noticed that each method has an additional *optional* parameter named `platform` of type `Platform`. You can use this to only trigger manual instrumentation for a specific OS. The available values are: `Platform.Ios` and `Platform.Android`. Default is that it will work on any platform. Otherwise it is passed *only* to the relevant OS. For example:
|
|
945
|
+
* Passing to **iOS** only:
|
|
946
|
+
```ts
|
|
947
|
+
import { Dynatrace, Platform } from '@dynatrace/react-native-plugin';
|
|
980
948
|
|
|
981
|
-
|
|
949
|
+
const myAction = Dynatrace.enterAutoAction("MyButton tapped", Platform.Ios);
|
|
950
|
+
//Perform the action and whatever else is needed.
|
|
951
|
+
myAction.leaveAction(Platform.Ios);
|
|
952
|
+
```
|
|
953
|
+
|
|
954
|
+
* Passing to **Android** only:
|
|
955
|
+
```ts
|
|
956
|
+
import { Dynatrace, Platform } from '@dynatrace/react-native-plugin';
|
|
982
957
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
}
|
|
958
|
+
const myAction = Dynatrace.enterAutoAction("MyButton tapped", Platform.Android);
|
|
959
|
+
//Perform the action and whatever else is needed.
|
|
960
|
+
myAction.leaveAction(Platform.Android);
|
|
987
961
|
```
|
|
962
|
+
|
|
963
|
+
* Passing to **both**:
|
|
964
|
+
```ts
|
|
965
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
988
966
|
|
|
989
|
-
|
|
967
|
+
const myAction = Dynatrace.enterAutoAction("MyButton tapped");
|
|
968
|
+
//Perform the action and whatever else is needed.
|
|
969
|
+
myAction.leaveAction();
|
|
970
|
+
```
|
|
990
971
|
|
|
991
|
-
|
|
992
|
-
- `react.userInteraction: true|false` controls whether the UI Interaction instrumentation feature is applied.
|
|
972
|
+
### Business event capturing
|
|
993
973
|
|
|
994
|
-
|
|
995
|
-
- Runtime emission checks the remote flag `touch_interaction_enabled`.
|
|
996
|
-
- If remote flag is present, it is used as the source of truth.
|
|
997
|
-
- If remote flag is temporarily unavailable, the plugin falls back to the last known good remote value.
|
|
998
|
-
- If no remote value was received yet, runtime defaults to enabled behavior.
|
|
974
|
+
With `sendBizEvent`, you can report business events. These events are standalone events, as OneAgent sends them detached from user actions or user sessions.
|
|
999
975
|
|
|
1000
|
-
|
|
976
|
+
For more information on business events, see [dynatrace documentation](https://docs.dynatrace.com/docs/observe/business-observability/explore-business-events).
|
|
1001
977
|
|
|
1002
|
-
|
|
978
|
+
```ts
|
|
979
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
1003
980
|
|
|
1004
|
-
|
|
981
|
+
Dynatrace.sendBizEvent("com.easytravel.funnel.booking-finished", {
|
|
982
|
+
"event.name" : "Confirmed Booking",
|
|
983
|
+
"screen": "booking-confirmation",
|
|
984
|
+
"product": "Danube Anna Hotel",
|
|
985
|
+
"amount": 358.35,
|
|
986
|
+
"currency": "USD",
|
|
987
|
+
"reviewScore": 4.8,
|
|
988
|
+
"arrivalDate": "2022-11-05",
|
|
989
|
+
"departureDate": "2022-11-15",
|
|
990
|
+
"journeyDuration": 10,
|
|
991
|
+
"adultTravelers": 2,
|
|
992
|
+
"childrenTravelers": 0
|
|
993
|
+
});
|
|
994
|
+
```
|
|
995
|
+

|
|
1005
996
|
|
|
1006
|
-
|
|
1007
|
-
* the runtime masking rules classify the detected text as sensitive
|
|
1008
|
-
* the runtime masking rules classify the element `testID` as sensitive
|
|
997
|
+
### Setting beacon headers
|
|
1009
998
|
|
|
1010
|
-
|
|
999
|
+
This allows you to put a set of http headers on every agent http request (i.e. Authorization header etc.). It will also triggers the agent to reconnect to the beacon endpoint with the new headers.
|
|
1011
1000
|
|
|
1012
|
-
|
|
1013
|
-
* the detected UI label is replaced with the configured replacement string (default: `***`)
|
|
1014
|
-
* `ui_element.name_origin` is reported as `masked`
|
|
1001
|
+
**Note:** To clear the previously set headers, call the method without the headers parameter or with a null value for the headers parameter.
|
|
1015
1002
|
|
|
1016
|
-
|
|
1003
|
+
```ts
|
|
1004
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
1017
1005
|
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
<Text>john.doe@example.com</Text>
|
|
1022
|
-
</Pressable>
|
|
1023
|
-
</View>
|
|
1006
|
+
const beaconHeaders = new Map<string, string>();
|
|
1007
|
+
beaconHeaders.set('headerName', 'headerValue');
|
|
1008
|
+
Dynatrace.setBeaconHeaders(beaconHeaders);
|
|
1024
1009
|
```
|
|
1025
1010
|
|
|
1026
|
-
|
|
1011
|
+
### Exclude Individual JSX Elements
|
|
1027
1012
|
|
|
1013
|
+
If you want to instrument a functional component or class component but want to exclude a certain button or element, you can do this via the `dtActionIgnore` property. Example:
|
|
1028
1014
|
|
|
1029
|
-
|
|
1015
|
+
```tsx
|
|
1016
|
+
import React from 'react';
|
|
1017
|
+
import { TouchableHighlight, Text, View } from 'react-native';
|
|
1030
1018
|
|
|
1031
|
-
|
|
1019
|
+
const TouchableHighlightScreen = () => {
|
|
1020
|
+
return (
|
|
1021
|
+
<View>
|
|
1022
|
+
<TouchableHighlight onPress={onPress}>
|
|
1023
|
+
<Text>TouchableHighlight that will be monitored</Text>
|
|
1024
|
+
</TouchableHighlight>
|
|
1025
|
+
<TouchableHighlight onPress={onPress} dtActionIgnore="true">
|
|
1026
|
+
<Text>TouchableHighlight that will be ignored</Text>
|
|
1027
|
+
</TouchableHighlight>
|
|
1028
|
+
</View>
|
|
1029
|
+
);
|
|
1030
|
+
};
|
|
1032
1031
|
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
- **Interaction type** — how the user interacted (e.g. `touch`).
|
|
1037
|
-
- **Position** — the screen coordinates where the touch occurred.
|
|
1032
|
+
const onPress = () => {
|
|
1033
|
+
console.log("TouchableHighlight Pressed!");
|
|
1034
|
+
};
|
|
1038
1035
|
|
|
1039
|
-
|
|
1036
|
+
export default TouchableHighlightScreen;
|
|
1037
|
+
```
|
|
1040
1038
|
|
|
1041
|
-
|
|
1039
|
+
This example shows two *TouchableHighlight*, which will fire the *onPress()* function when pressed. The property `dtActionIgnore="true"` will prevent the monitoring of one of them. This means that the onPress will still be executed but we will no longer create a user action which is wrapping the button click.
|
|
1042
1040
|
|
|
1043
|
-
|
|
1041
|
+
>*Attention:* If you are using Typescript and want to set this property with type-safety, look [here](#typescript-setup-for-dtactionignore-and-dtactionname).
|
|
1044
1042
|
|
|
1045
|
-
|
|
1046
|
-
{
|
|
1047
|
-
"characteristics.has_user_interaction": true,
|
|
1048
|
-
"ui_element.detected_name": "LoginButton",
|
|
1049
|
-
"ui_element.components": ["Pressable"],
|
|
1050
|
-
"ui_element.id": "App/View/Pressable",
|
|
1051
|
-
"ui_element.name_origin": "component",
|
|
1052
|
-
"interaction.name": "touch",
|
|
1053
|
-
"positions": [{ "x": 120, "y": 460 }],
|
|
1054
|
-
"ui_element.responder.detected_name": "Pressable",
|
|
1055
|
-
"ui_element.responder.components": ["Pressable"],
|
|
1056
|
-
"ui_element.responder.id": "App/View[/Pressable",
|
|
1057
|
-
"ui_element.responder.name_origin": "component"
|
|
1058
|
-
}
|
|
1059
|
-
```
|
|
1043
|
+
## Extended topics
|
|
1060
1044
|
|
|
1061
|
-
|
|
1045
|
+
### Identify a user
|
|
1062
1046
|
|
|
1063
|
-
You can
|
|
1047
|
+
You can identify a user and tag the current session with a name by making the following call:
|
|
1064
1048
|
|
|
1065
|
-
|
|
1049
|
+
**Important:** The user identifier is limited to 250 characters and will be truncated if it exceeds this limit.
|
|
1066
1050
|
|
|
1067
|
-
|
|
1051
|
+
```ts
|
|
1052
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
1068
1053
|
|
|
1069
|
-
|
|
1070
|
-
<TouchableOpacity dtActionName="Checkout Button" onPress={onCheckout}>
|
|
1071
|
-
<Text dtActionName="Checkout Text">Buy now</Text>
|
|
1072
|
-
</TouchableOpacity>
|
|
1054
|
+
Dynatrace.identifyUser("User XY");
|
|
1073
1055
|
```
|
|
1056
|
+

|
|
1074
1057
|
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
```json
|
|
1078
|
-
"ui_element.components": ["Checkout Text"],
|
|
1079
|
-
"ui_element.id": ".../Checkout Button/Checkout Text"
|
|
1080
|
-
```
|
|
1058
|
+
### End the current user session
|
|
1081
1059
|
|
|
1082
|
-
|
|
1060
|
+
To end the current user session, use the following API call:
|
|
1083
1061
|
|
|
1084
|
-
|
|
1062
|
+
```ts
|
|
1063
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
1085
1064
|
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
import { createDrawerNavigator } from '@react-navigation/drawer';
|
|
1065
|
+
Dynatrace.endSession();
|
|
1066
|
+
```
|
|
1089
1067
|
|
|
1090
|
-
|
|
1068
|
+
**Note:** The user tagging will not carry over to the new user session that is started after using this API. If user tagging is desired in the new user session, please ensure that you call the [user tagging](#identify-a-user) API.
|
|
1091
1069
|
|
|
1092
|
-
|
|
1093
|
-
return (/* ... */);
|
|
1094
|
-
}
|
|
1070
|
+
### User Privacy Options
|
|
1095
1071
|
|
|
1096
|
-
|
|
1097
|
-
ProfileScreen.dtActionName = 'User Profile';
|
|
1072
|
+
The privacy API methods allow you to dynamically change the data-collection level based on the individual preferences of your end users. Each end user can select from three data-privacy levels:
|
|
1098
1073
|
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
<Drawer.Navigator>
|
|
1103
|
-
{/* Both screens reference the same component,
|
|
1104
|
-
so both pick up the 'User Profile' name */}
|
|
1105
|
-
<Drawer.Screen name="Me" component={ProfileScreen} />
|
|
1106
|
-
<Drawer.Screen name="Account" component={ProfileScreen} />
|
|
1107
|
-
</Drawer.Navigator>
|
|
1108
|
-
</NavigationContainer>
|
|
1109
|
-
);
|
|
1074
|
+
```ts
|
|
1075
|
+
export enum DataCollectionLevel {
|
|
1076
|
+
Off, Performance, UserBehavior
|
|
1110
1077
|
}
|
|
1111
1078
|
```
|
|
1112
1079
|
|
|
1113
|
-
|
|
1080
|
+
1. Off: Native Agent doesn't capture any monitoring data.
|
|
1081
|
+
2. Performance: Native Agent captures only anonymous performance data. Monitoring data that can be used to identify individual users, such as user tags and custom values, aren't captured.
|
|
1082
|
+
3. UserBehavior: Native Agent captures both performance and user data. In this mode, Native Agent recognizes and reports users who re-visit in future sessions.
|
|
1114
1083
|
|
|
1115
|
-
|
|
1116
|
-
"ui_element.id": ".../User Profile/..."
|
|
1117
|
-
```
|
|
1084
|
+
Crash reporting is enabled by default. The Mobile agent captures all unhandled exceptions/errors and immediately sends the crash report to the server. With this API you can activate or deactivate crash reporting. To change this behaviour via the API, enable/activate [`userOptIn`](#user-opt-in-mode) and set the User Privacy Options.
|
|
1118
1085
|
|
|
1119
|
-
|
|
1120
|
-
>
|
|
1121
|
-
> **Note:** The static property has no effect when a component is rendered as JSX. In that case the name is taken from either the `dtActionName` prop passed to it (option 1) or the name of the JSX component.
|
|
1086
|
+
The API to get and set the current privacy level looks like this:
|
|
1122
1087
|
|
|
1123
|
-
|
|
1088
|
+
```ts
|
|
1089
|
+
import { Platform, UserPrivacyOptions } from '@dynatrace/react-native-plugin';
|
|
1124
1090
|
|
|
1125
|
-
|
|
1091
|
+
interface IDynatrace {
|
|
1092
|
+
getUserPrivacyOptions(platform?: Platform): Promise<UserPrivacyOptions>;
|
|
1093
|
+
applyUserPrivacyOptions(userPrivacyOptions: UserPrivacyOptions, platform?: Platform): void;
|
|
1094
|
+
}
|
|
1095
|
+
```
|
|
1126
1096
|
|
|
1127
|
-
|
|
1097
|
+
To check the current privacy options that are set:
|
|
1128
1098
|
|
|
1129
|
-
|
|
1099
|
+
```ts
|
|
1100
|
+
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
1130
1101
|
|
|
1131
|
-
|
|
1102
|
+
const privacyOptions = await Dynatrace.getUserPrivacyOptions();
|
|
1103
|
+
```
|
|
1132
1104
|
|
|
1133
|
-
|
|
1134
|
-
* Run `npx react-native run-android --mode release` in your project root, or
|
|
1135
|
-
* Run `gradlew assembleRelease` in the `/android` directory
|
|
1105
|
+
If you want to create a new `UserPrivacyOptions` object and pass it to Dynatrace:
|
|
1136
1106
|
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
* Then run `npx react-native run-ios --mode Release`, or
|
|
1140
|
-
* Build for release in Xcode
|
|
1107
|
+
```ts
|
|
1108
|
+
import { Dynatrace, DataCollectionLevel, UserPrivacyOptions } from '@dynatrace/react-native-plugin';
|
|
1141
1109
|
|
|
1142
|
-
|
|
1110
|
+
const privacyConfig = new UserPrivacyOptions(DataCollectionLevel.UserBehavior, true);
|
|
1111
|
+
|
|
1112
|
+
// Getter and setter available for UserPrivacyOptions
|
|
1113
|
+
privacyConfig.crashReportingOptedIn = false;
|
|
1114
|
+
privacyConfig.dataCollectionLevel = DataCollectionLevel.Performance;
|
|
1115
|
+
|
|
1116
|
+
const level = privacyConfig.dataCollectionLevel;
|
|
1117
|
+
const crashReporting = privacyConfig.crashReportingOptedIn;
|
|
1143
1118
|
|
|
1144
|
-
|
|
1119
|
+
Dynatrace.applyUserPrivacyOptions(privacyConfig);
|
|
1120
|
+
```
|
|
1145
1121
|
|
|
1146
1122
|
## NPX Commands
|
|
1147
1123
|
|
|
@@ -1149,7 +1125,6 @@ The following npx commands are available for the plugin:
|
|
|
1149
1125
|
|
|
1150
1126
|
* npx instrumentDynatrace - Is triggering the configuration process and will insert the configuration into the Android and iOS application. This is mandatory and should usually happen automatically when doing `react-native run-android` or `react-native run-ios` command.
|
|
1151
1127
|
* npx configDynatrace - Is checking the current configuration and is creating a default configuration if there is none.
|
|
1152
|
-
* npx lineOffsetDynatrace - ...
|
|
1153
1128
|
|
|
1154
1129
|
### npx instrumentDynatrace
|
|
1155
1130
|
|
|
@@ -1160,6 +1135,7 @@ npx instrumentDynatrace [optional: config=... gradle=... plist=...]
|
|
|
1160
1135
|
* `gradle=C:\MyReactAndroidProject\build.gradle`: The location of the root build.gradle file. We will assume that the other gradle file resides in `/app/build.gradle`. This will add the whole agent dependencies automatically for you and will update the configuration.
|
|
1161
1136
|
* `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.
|
|
1162
1137
|
* `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.
|
|
1138
|
+
* `--reset`: Clear any previously-persisted custom config path and revert the Metro/Babel transformer to the default `dynatrace.config.js` lookup. Useful after switching between build flavors.
|
|
1163
1139
|
|
|
1164
1140
|
If `plist=...` is not provided, the plugin tries to resolve `Info.plist` automatically in this order:
|
|
1165
1141
|
|
|
@@ -1188,6 +1164,22 @@ Our scripts assumes that the usual React Native project structure is given. The
|
|
|
1188
1164
|
* `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.
|
|
1189
1165
|
* `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.
|
|
1190
1166
|
|
|
1167
|
+
### DYNATRACE_CONFIG environment variable
|
|
1168
|
+
|
|
1169
|
+
As an alternative to `config=`, you can set the `DYNATRACE_CONFIG` environment variable to specify the config file path. This is particularly useful in CI pipelines and Xcode schemes where multiple build flavors each need their own config file, because it does not require changing the instrumentation script — only the environment of the build step.
|
|
1170
|
+
|
|
1171
|
+
```
|
|
1172
|
+
DYNATRACE_CONFIG=dynatrace.config.prod.js npx instrumentDynatrace
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
**Precedence (highest to lowest):**
|
|
1176
|
+
|
|
1177
|
+
1. `config=` CLI argument — always wins
|
|
1178
|
+
2. `DYNATRACE_CONFIG` environment variable
|
|
1179
|
+
3. Default `dynatrace.config.js` in the project root
|
|
1180
|
+
|
|
1181
|
+
> **Note:** `DYNATRACE_CONFIG` applies to the **Metro/Babel transformer** as well as `npx instrumentDynatrace`. This means you can set it in your Xcode scheme's environment variables to ensure the correct config is used during iOS archive/bundling, independently of what was passed to the instrumentation step.
|
|
1182
|
+
|
|
1191
1183
|
Examples:
|
|
1192
1184
|
|
|
1193
1185
|
* React Native v0.60.1 or newer:
|
|
@@ -1503,18 +1495,6 @@ The changes our auto-instrumentation is making now get dumped into the `node_mod
|
|
|
1503
1495
|
|
|
1504
1496
|
> **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.
|
|
1505
1497
|
|
|
1506
|
-
#### Using our legacy jscodeshift auto-instrumentation
|
|
1507
|
-
|
|
1508
|
-
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:
|
|
1509
|
-
|
|
1510
|
-
```js
|
|
1511
|
-
react: {
|
|
1512
|
-
useLegacyJscodeshift: true
|
|
1513
|
-
}
|
|
1514
|
-
```
|
|
1515
|
-
|
|
1516
|
-
> **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.
|
|
1517
|
-
|
|
1518
1498
|
### Android block
|
|
1519
1499
|
|
|
1520
1500
|
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:
|
|
@@ -1684,7 +1664,7 @@ ios: {
|
|
|
1684
1664
|
* class name: If the display name is not available, the class name is used by taking the property name from the constructor
|
|
1685
1665
|
* Touchables, Buttons, Pressable
|
|
1686
1666
|
* dtActionName: Use a custom property called dtActionName
|
|
1687
|
-
* If [actionNamePrivacy](#
|
|
1667
|
+
* If [actionNamePrivacy](#manual-oneagent-startup) is activated anything below will not be detected
|
|
1688
1668
|
* title property
|
|
1689
1669
|
* accessibilityLabel property
|
|
1690
1670
|
* 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`.
|
|
@@ -1734,7 +1714,7 @@ import { Text } from 'react-native';
|
|
|
1734
1714
|
</TouchableHighlight>
|
|
1735
1715
|
```
|
|
1736
1716
|
|
|
1737
|
-
*Note:* [actionNamePrivacy](#
|
|
1717
|
+
*Note:* [actionNamePrivacy](#manual-oneagent-startup) has no impact on using dtActionName. dtActionName will always be used.
|
|
1738
1718
|
|
|
1739
1719
|
>*Attention:* If you are using Typescript and want to set this property with type-safety, look [here](#typescript-setup-for-dtactionignore-and-dtactionname).
|
|
1740
1720
|
|
|
@@ -1748,7 +1728,7 @@ In general, Dynatrace always closes the session when a crash occurs. Usually a c
|
|
|
1748
1728
|
* Fatal error: If the error is considered as fatal by the React Native crash handler, it will be treated as crash.
|
|
1749
1729
|
* Native crashes: If a crash appears solely on the native side and is not noticed by the internal React Native crash handler, it will be reported directly by the Android or iOS agent.
|
|
1750
1730
|
* Exception: Some JavaScript crashes will result in Native crashes. Therefore, they are filtered on the native side as normally the crash would be reported twice. On the JavaScript side, these crashes are already reported by us before they hit the native side resulting in no lost information.
|
|
1751
|
-
Additionally, you can use our crash and error reporting APIs which are available with [
|
|
1731
|
+
Additionally, you can use our crash and error reporting APIs which are available with [RUM Classic](#rum-classic).
|
|
1752
1732
|
|
|
1753
1733
|
|
|
1754
1734
|
## React Automatic Runtime
|
|
@@ -2073,6 +2053,33 @@ If you are struggling with a problem, submit a support ticket to Dynatrace (supp
|
|
|
2073
2053
|
|
|
2074
2054
|
In Progress
|
|
2075
2055
|
|
|
2056
|
+
2.345.1
|
|
2057
|
+
* Updated Android (8.345.1.1003) & iOS Agent (8.345.1.1003)
|
|
2058
|
+
* Renamed `monitorNavigation` to `useNavigationMonitor`; React Navigation screen changes are now detected automatically, stamped with `start_time` and `duration`, and trigger Session Replay capture after the incoming screen settles
|
|
2059
|
+
* Added React Navigation support: settle detection on both Android and iOS bridges, UI-change capture toggling restored
|
|
2060
|
+
* Removed the bridge-side settle helper — the native agent now owns coalescing on both platforms
|
|
2061
|
+
* Added a runtime deprecation warning system
|
|
2062
|
+
* Removed the option to use the legacy jscodeshift auto-instrumentation by removing the `useLegacyJscodeshift` flag from `dynatrace.config.js`
|
|
2063
|
+
* Removed leading slash from reported view names
|
|
2064
|
+
* Discard user interaction actions when 3rd-gen instrumentation is disabled, even without an `onPress` callback
|
|
2065
|
+
* Android: compatibility fixes for AGP 9 and Kotlin 2.2 (React Native 0.87)
|
|
2066
|
+
* iOS: app-start measurement fixes for the new architecture
|
|
2067
|
+
|
|
2068
|
+
2.343.1
|
|
2069
|
+
* Updated Android (8.343.1.1038) & iOS Agent (8.343.1.1007)
|
|
2070
|
+
* Added User Actions feature
|
|
2071
|
+
* Raised minimum platform requirements for Android and iOS
|
|
2072
|
+
* Android API level: 21 → 23
|
|
2073
|
+
* Java: 11 → 17
|
|
2074
|
+
* AGP: 7.0+ → 8.1.1+
|
|
2075
|
+
* iOS SDK: 12 → 15
|
|
2076
|
+
* Fixed iOS archive/bundle crash (`ENOENT: no such file or directory`) in projects that use app-specific config files (e.g. `dynatrace.config.prod.js`) instead of the default `dynatrace.config.js` at the repo root. The config resolution code was unconditionally reading the config file before `require()`, causing a hard crash in the Metro/Babel transformer instead of a graceful "config not found" fallback. Discovered via external report from a monorepo setup with multiple build flavors.
|
|
2077
|
+
* Fixed custom config path (`config=` argument to `npx instrumentDynatrace`) being lost between build steps: previously, running `npx instrumentDynatrace` without arguments in a subsequent build step (e.g. a generic iOS build phase) would silently delete the persisted custom path, causing Metro bundler to fall back to the hardcoded `dynatrace.config.js` and crash. The custom path is now preserved until explicitly overridden.
|
|
2078
|
+
* Added `DYNATRACE_CONFIG` environment variable as an alternative way to specify the config file path for the Metro/Babel transformer.
|
|
2079
|
+
* Added `npx instrumentDynatrace --reset` flag to clear a previously-persisted custom config path and revert the Metro/Babel transformer to the default `dynatrace.config.js` lookup. Useful after switching between build flavors that each use a different config file.
|
|
2080
|
+
* Fixed incorrect `start_time` on Android app start events when `3rd_gen_enabled` is false. The `EventPipeline` was suppressing the `forwardAppStartEvent` timing-correction call along with all other 3rd-gen events, causing the native Dynatrace SDK to report its own stale process-creation timestamp instead of the actual JS bundle load time.
|
|
2081
|
+
* CP now always forwards User Interaction Actions (UIA) to the native agent unconditionally, regardless of the `touch_interaction_enabled` server configuration flag. The native agent is responsible for deciding whether to record or discard each UIA. This applies to both the Babel-instrumented (`AnalyticsRoot`/`TouchCapture`) and the legacy JSX-wrapped Touchables UIA paths.
|
|
2082
|
+
|
|
2076
2083
|
2.341.1
|
|
2077
2084
|
* Updated Android (8.341.1.1004) & iOS Agent (8.341.1.1010)
|
|
2078
2085
|
* Added support for using `dtActionName` prop to customize User Interaction component names
|
|
@@ -2084,7 +2091,6 @@ In Progress
|
|
|
2084
2091
|
* Updated `@babel/runtime` to latest major version
|
|
2085
2092
|
* Fixed security vulnerabilities in `ws` and `brace-expansion` dependencies
|
|
2086
2093
|
|
|
2087
|
-
|
|
2088
2094
|
2.339.1
|
|
2089
2095
|
* Updated Android (8.339.1.1004) & iOS Agent (8.339.1.1011)
|
|
2090
2096
|
* Enabled User Interaction Feature by default
|
|
@@ -2100,7 +2106,7 @@ In Progress
|
|
|
2100
2106
|
* Updated Android (8.337.2.1010) & iOS Agent (8.337.1.1003)
|
|
2101
2107
|
* 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`).
|
|
2102
2108
|
* 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.
|
|
2103
|
-
* Added [actionNamePreference](#
|
|
2109
|
+
* Added [actionNamePreference](#manual-oneagent-startup) and [actionNameAlgorithm](#manual-oneagent-startup) configuration flags.
|
|
2104
2110
|
|
|
2105
2111
|
2.335.1
|
|
2106
2112
|
* Updated Android (8.335.1.1001) & iOS Agent (8.335.1.1009)
|
|
@@ -2124,12 +2130,12 @@ In Progress
|
|
|
2124
2130
|
|
|
2125
2131
|
2.329.1
|
|
2126
2132
|
* Updated Android (8.329.1.1014) & iOS Agent (8.329.1.1017)
|
|
2127
|
-
* [New RUM experience](#
|
|
2128
|
-
* [New RUM experience](#
|
|
2129
|
-
* [New RUM experience](#
|
|
2133
|
+
* [New RUM experience](#real-user-monitoring-rum) Removed Dynatrace.stopView() API
|
|
2134
|
+
* [New RUM experience](#real-user-monitoring-rum) Enforcing length limitation of 5000 characters for user input values
|
|
2135
|
+
* [New RUM experience](#real-user-monitoring-rum) React Native Deobfuscation service via sourcemaps
|
|
2130
2136
|
* Adding [`npx lineOffsetDynatrace`](#npx-lineoffsetdynatrace) command
|
|
2131
|
-
* [New RUM experience](#
|
|
2132
|
-
* [New RUM experience](#
|
|
2137
|
+
* [New RUM experience](#real-user-monitoring-rum) Added automated view tracking via [navigation](#automatic-navigation-tracking)
|
|
2138
|
+
* [New RUM experience](#real-user-monitoring-rum) Event and session properties are now sorted alphabetically when the limit of 50 is exceeded, ensuring deterministic property dropping
|
|
2133
2139
|
|
|
2134
2140
|
2.327.2
|
|
2135
2141
|
* Fixed iOS startup time calculation issues for React Native 0.72 and lower
|
|
@@ -2138,7 +2144,7 @@ In Progress
|
|
|
2138
2144
|
|
|
2139
2145
|
2.327.1
|
|
2140
2146
|
* Added [Compose Compatibility Note](#compose-compatibility-note)
|
|
2141
|
-
* Added [New RUM experience preview](#
|
|
2147
|
+
* Added [New RUM experience preview](#real-user-monitoring-rum) documentation
|
|
2142
2148
|
* Fixed iOS crash reporting by delaying the crash by 200ms on iOS to give the Agent enough time to report it
|
|
2143
2149
|
* Updated Android (8.327.2.1004) & iOS Agent (8.327.1.1020)
|
|
2144
2150
|
|
|
@@ -2147,8 +2153,8 @@ In Progress
|
|
|
2147
2153
|
|
|
2148
2154
|
2.325.1
|
|
2149
2155
|
* Updated Android (8.325.1.1007) & iOS Agent (8.325.1.1012)
|
|
2150
|
-
* [New RUM experience preview](#
|
|
2151
|
-
* [New RUM experience preview](#
|
|
2156
|
+
* [New RUM experience preview](#real-user-monitoring-rum) ReactNative version now added to RUM on Grail event base data
|
|
2157
|
+
* [New RUM experience preview](#real-user-monitoring-rum) Added API documentation for RUM on Grail API
|
|
2152
2158
|
|
|
2153
2159
|
2.323.2
|
|
2154
2160
|
* Fixed error "Execution failed for task ':app:mergeReleaseAssets'. A problem occured starting process 'command 'npx''" when building for release on Windows.
|
|
@@ -2334,7 +2340,7 @@ In Progress
|
|
|
2334
2340
|
2.247.1
|
|
2335
2341
|
* Updated Android Agent (8.247.1.1003) & iOS Agent (8.247.1.1007)
|
|
2336
2342
|
* Minimum supported Android SDK version raised to 21
|
|
2337
|
-
* Added [actionNamePrivacy](#
|
|
2343
|
+
* Added [actionNamePrivacy](#manual-oneagent-startup) configuration flag
|
|
2338
2344
|
* Removed `instrumentDynatrace` from package.json
|
|
2339
2345
|
* Adding [`npx instrumentDynatrace`](#npx-instrumentdynatrace) and [`npx configDynatrace`](#npx-configdynatrace) command
|
|
2340
2346
|
|