@dynatrace/react-native-plugin 2.331.1 → 2.333.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +96 -6
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +7 -1
  4. package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.kt +1 -0
  5. package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +1 -0
  6. package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +2 -1
  7. package/files/plugin.gradle +1 -1
  8. package/instrumentation/DynatraceInstrumentation.js +1 -1
  9. package/instrumentation/jsx/CreateElement.js +106 -6
  10. package/instrumentation/jsx/JsxDevRuntime.js +2 -6
  11. package/instrumentation/jsx/JsxRuntime.js +2 -6
  12. package/instrumentation/libs/withOnPressMonitoring.js +49 -3
  13. package/ios/DynatraceRNBridge.mm +8 -1
  14. package/lib/core/Application.js +2 -0
  15. package/lib/core/Dynatrace.js +2 -1
  16. package/lib/core/UserPrivacyOptions.js +8 -1
  17. package/lib/core/configuration/ConfigurationHandler.js +21 -0
  18. package/lib/features/ui-interaction/Config.js +36 -0
  19. package/lib/features/ui-interaction/IUserInteractionEvent.js +16 -0
  20. package/lib/features/ui-interaction/Plugin.js +945 -0
  21. package/lib/features/ui-interaction/RootDetection.js +51 -0
  22. package/lib/features/ui-interaction/RootWrapper.js +236 -0
  23. package/lib/features/ui-interaction/Run.js +34 -0
  24. package/lib/features/ui-interaction/Runtime.js +1494 -0
  25. package/lib/features/ui-interaction/Types.js +75 -0
  26. package/lib/next/Dynatrace.js +1 -1
  27. package/lib/next/configuration/INativeRuntimeConfiguration.js +1 -0
  28. package/lib/next/configuration/RuntimeConfigurationObserver.js +47 -12
  29. package/lib/next/events/EventPipeline.js +9 -0
  30. package/package.json +19 -10
  31. package/react-native-dynatrace.podspec +1 -1
  32. package/scripts/Config.js +1 -0
  33. package/src/lib/core/interface/NativeDynatraceBridge.ts +1 -0
  34. package/types.d.ts +22 -9
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Literals = exports.IdName = exports.AttrName = exports.PressKey = exports.DangerousWrapDeny = exports.StopMemberProp = exports.TabBase = exports.StopMemberBase = exports.StopId = void 0;
4
+ var StopId;
5
+ (function (StopId) {
6
+ StopId["React"] = "React";
7
+ StopId["Fragment"] = "Fragment";
8
+ StopId["Segment"] = "Segment";
9
+ StopId["AnalyticsRoot"] = "AnalyticsRoot";
10
+ StopId["PathPrefix"] = "PathPrefix";
11
+ StopId["NavigationTraceInner"] = "NavigationTraceInner";
12
+ StopId["TabButton"] = "TabButton";
13
+ StopId["NavigationContainer"] = "NavigationContainer";
14
+ })(StopId = exports.StopId || (exports.StopId = {}));
15
+ var StopMemberBase;
16
+ (function (StopMemberBase) {
17
+ StopMemberBase["Stack"] = "Stack";
18
+ StopMemberBase["NativeStack"] = "NativeStack";
19
+ StopMemberBase["MaterialBottomTab"] = "MaterialBottomTab";
20
+ StopMemberBase["MaterialTopTab"] = "MaterialTopTab";
21
+ StopMemberBase["Drawer"] = "Drawer";
22
+ })(StopMemberBase = exports.StopMemberBase || (exports.StopMemberBase = {}));
23
+ var TabBase;
24
+ (function (TabBase) {
25
+ TabBase["Tabs"] = "Tabs";
26
+ TabBase["Tab"] = "Tab";
27
+ TabBase["BottomTab"] = "BottomTab";
28
+ TabBase["MaterialBottomTab"] = "MaterialBottomTab";
29
+ TabBase["MaterialTopTab"] = "MaterialTopTab";
30
+ })(TabBase = exports.TabBase || (exports.TabBase = {}));
31
+ var StopMemberProp;
32
+ (function (StopMemberProp) {
33
+ StopMemberProp["Screen"] = "Screen";
34
+ StopMemberProp["Group"] = "Group";
35
+ })(StopMemberProp = exports.StopMemberProp || (exports.StopMemberProp = {}));
36
+ var DangerousWrapDeny;
37
+ (function (DangerousWrapDeny) {
38
+ DangerousWrapDeny["KeyboardAwareScrollView"] = "KeyboardAwareScrollView";
39
+ DangerousWrapDeny["SectionListWithKeyboardAwareScrollView"] = "SectionListWithKeyboardAwareScrollView";
40
+ })(DangerousWrapDeny = exports.DangerousWrapDeny || (exports.DangerousWrapDeny = {}));
41
+ var PressKey;
42
+ (function (PressKey) {
43
+ PressKey["onPress"] = "onPress";
44
+ PressKey["onLongPress"] = "onLongPress";
45
+ PressKey["onPressIn"] = "onPressIn";
46
+ PressKey["onPressOut"] = "onPressOut";
47
+ PressKey["onTap"] = "onTap";
48
+ PressKey["onClick"] = "onClick";
49
+ })(PressKey = exports.PressKey || (exports.PressKey = {}));
50
+ var AttrName;
51
+ (function (AttrName) {
52
+ AttrName["Options"] = "options";
53
+ AttrName["TabBarButton"] = "tabBarButton";
54
+ AttrName["DtUIMask"] = "dtMask";
55
+ AttrName["Key"] = "key";
56
+ AttrName["Name"] = "name";
57
+ })(AttrName = exports.AttrName || (exports.AttrName = {}));
58
+ var IdName;
59
+ (function (IdName) {
60
+ IdName["DtPrefix"] = "__DT_PREFIX";
61
+ IdName["DtEmit"] = "__DT_emit";
62
+ })(IdName = exports.IdName || (exports.IdName = {}));
63
+ exports.Literals = {
64
+ ReactFragmentFQN: 'React.Fragment',
65
+ NavigatorProp: 'Navigator',
66
+ PluginName: 'dt-user-interaction',
67
+ LogTag: '[dt] instrumented:',
68
+ RawHandlerTag: '[DT raw] handler',
69
+ KeySuffixPrefix: '~dt@',
70
+ DefaultRuntimeImport: '@dynatrace/react-native-plugin/lib/features/ui-interaction/Runtime',
71
+ DefaultArtifactsDir: 'node_modules/@dynatrace/react-native-plugin/build/ui_instrumented',
72
+ DefaultSegmentName: 'Segment',
73
+ DefaultTabButtonName: 'TabButton',
74
+ DefaultRootName: 'AnalyticsRoot',
75
+ };
@@ -38,7 +38,7 @@ class DynatraceImpl {
38
38
  }
39
39
  startView(name) {
40
40
  if (typeof name !== 'string') {
41
- this.logger.info(`startView(name): Name must be a string!`);
41
+ this.logger.info('startView(name): Name must be a string!');
42
42
  return;
43
43
  }
44
44
  this.logger.debug(`startView(${name})`);
@@ -3,5 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateDefaultConfiguration = void 0;
4
4
  const generateDefaultConfiguration = () => ({
5
5
  '3rd_gen_enabled': true,
6
+ touch_interaction_enabled: false,
6
7
  });
7
8
  exports.generateDefaultConfiguration = generateDefaultConfiguration;
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RuntimeConfigurationObserver = void 0;
4
+ const react_native_1 = require("react-native");
4
5
  const DynatraceBridge_1 = require("../../core/DynatraceBridge");
5
- const DynatraceEventBus_1 = require("../DynatraceEventBus");
6
6
  const INativeRuntimeConfiguration_1 = require("./INativeRuntimeConfiguration");
7
7
  class RuntimeConfigurationObserverImpl {
8
8
  constructor() {
@@ -12,25 +12,60 @@ class RuntimeConfigurationObserverImpl {
12
12
  this.subscription = null;
13
13
  this.setupNativeEventEmitter();
14
14
  }
15
+ call() {
16
+ }
15
17
  getCurrentRuntimeConfiguration() {
16
18
  return this.runtimeConfiguration;
17
19
  }
18
20
  isInitiated() {
19
21
  return this.observerIsInitiated;
20
22
  }
23
+ updateRuntimeConfiguration(data) {
24
+ if (!data || typeof data !== 'object') {
25
+ return;
26
+ }
27
+ const payload = data;
28
+ const thirdGenEnabled = typeof payload['3rd_gen_enabled'] === 'boolean'
29
+ ? payload['3rd_gen_enabled']
30
+ : undefined;
31
+ const touchInteractionEnabled = typeof payload.touch_interaction_enabled === 'boolean'
32
+ ? payload.touch_interaction_enabled
33
+ : undefined;
34
+ const normalized = Object.assign(Object.assign({}, (typeof thirdGenEnabled === 'boolean'
35
+ ? { '3rd_gen_enabled': thirdGenEnabled }
36
+ : {})), (typeof touchInteractionEnabled === 'boolean'
37
+ ? { touch_interaction_enabled: touchInteractionEnabled }
38
+ : {}));
39
+ this.runtimeConfiguration = Object.assign(Object.assign({}, (0, INativeRuntimeConfiguration_1.generateDefaultConfiguration)()), normalized);
40
+ this.observerIsInitiated = true;
41
+ }
42
+ resolveBridgeModule() {
43
+ const dynatraceModule = DynatraceBridge_1.DynatraceNative;
44
+ const hasDynatraceBridgeAPI = !!dynatraceModule &&
45
+ (typeof dynatraceModule.addListener === 'function' ||
46
+ typeof dynatraceModule.getCurrentConfiguration === 'function');
47
+ if (hasDynatraceBridgeAPI) {
48
+ return dynatraceModule;
49
+ }
50
+ return react_native_1.NativeModules.DynatraceBridge;
51
+ }
21
52
  setupNativeEventEmitter() {
22
- const emitter = (0, DynatraceEventBus_1.createEmitterRuntimeConfig)();
23
- this.subscription = (0, DynatraceEventBus_1.addListenerOnce)(emitter, this.subscription, this.EMIT_CONFIGURATION, (data) => {
24
- this.runtimeConfiguration = data;
25
- this.observerIsInitiated = true;
26
- });
27
- if (typeof DynatraceBridge_1.DynatraceNative.getCurrentConfiguration === 'function') {
28
- Promise.resolve(DynatraceBridge_1.DynatraceNative.getCurrentConfiguration())
53
+ const bridgeModule = this.resolveBridgeModule();
54
+ if (!bridgeModule) {
55
+ return;
56
+ }
57
+ const iosModule = react_native_1.NativeModules.DynatraceBridge;
58
+ const nativeEmitterModule = react_native_1.Platform.OS === 'ios' ? iosModule || bridgeModule : bridgeModule;
59
+ const emitter = new react_native_1.NativeEventEmitter(nativeEmitterModule);
60
+ if (this.subscription == null) {
61
+ this.subscription = emitter.addListener(this.EMIT_CONFIGURATION, (data) => {
62
+ this.updateRuntimeConfiguration(data);
63
+ });
64
+ }
65
+ if (typeof bridgeModule.getCurrentConfiguration === 'function') {
66
+ Promise.resolve(bridgeModule.getCurrentConfiguration())
29
67
  .then((data) => {
30
- if (data) {
31
- this.runtimeConfiguration = data;
32
- this.observerIsInitiated = true;
33
- }
68
+ this.updateRuntimeConfiguration(data);
34
69
  })
35
70
  .catch(() => {
36
71
  });
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EventPipeline = void 0;
4
4
  const DynatraceBridge_1 = require("../../core/DynatraceBridge");
5
5
  const ConsoleLogger_1 = require("../../core/logging/ConsoleLogger");
6
+ const ConfigurationHandler_1 = require("../../core/configuration/ConfigurationHandler");
6
7
  const BaseDataEventModifier_1 = require("./modifier/BaseDataEventModifier");
7
8
  const ValueRestrictionModifier_1 = require("./modifier/ValueRestrictionModifier");
8
9
  const ModifyEventValidation_1 = require("./modifier/ModifyEventValidation");
@@ -24,6 +25,14 @@ class EventPipelineImpl {
24
25
  ];
25
26
  }
26
27
  insertEvent(event) {
28
+ if (!ConfigurationHandler_1.ConfigurationHandler.isRuntimeConfigurationInitiated()) {
29
+ this.logger.debug('isRuntimeConfigurationInitiated is not enabled! App start event will be discarded!');
30
+ return;
31
+ }
32
+ if (!ConfigurationHandler_1.ConfigurationHandler.isGrailEnabled()) {
33
+ this.logger.debug('RUM on Grail is not enabled! App start event will be discarded!');
34
+ return;
35
+ }
27
36
  this.logger.debug(`insertEvent(${JSON.stringify(event)})`);
28
37
  let isDiscarded = false;
29
38
  for (const modifier of this.getEventModifierChain()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynatrace/react-native-plugin",
3
- "version": "2.331.1",
3
+ "version": "2.333.1",
4
4
  "description": "This plugin gives you the ability to use the Dynatrace Mobile agent in your react native application.",
5
5
  "main": "index.js",
6
6
  "types": "types.d.ts",
@@ -68,7 +68,11 @@
68
68
  },
69
69
  "ast-types": "npm:ast-types-x",
70
70
  "flow-parser": "0.160",
71
- "fast-xml-parser@>=4.3.6 <=5.3.3": "5.3.4"
71
+ "fast-xml-parser@>=4.3.6 <=5.3.5": "5.3.6",
72
+ "@isaacs/brace-expansion": ">=5.0.1",
73
+ "minimatch@>=9.0.0 <9.0.6": ">=9.0.6",
74
+ "minimatch@>=10.0.0 <10.2.2": ">=10.2.2",
75
+ "minimatch@>=3.0.0 <3.1.3": ">=3.1.3"
72
76
  },
73
77
  "devDependencies": {
74
78
  "@babel/plugin-transform-class-properties": "^7.27.1",
@@ -80,33 +84,37 @@
80
84
  "@react-native/babel-preset": "^0.80.1",
81
85
  "@react-navigation/core": "^7.13.0",
82
86
  "@react-navigation/drawer": "^7.7.2",
83
- "@testing-library/react-native": "^13.2.0",
87
+ "@testing-library/react-native": "^13.3.3",
84
88
  "@types/jest": "^30.0.0",
85
89
  "@types/jscodeshift": "^17.3.0",
90
+ "@types/micromatch": "^4.0.10",
86
91
  "@types/node": "^18.19.123",
87
92
  "@types/plist": "^3.0.5",
88
93
  "@types/react": "^19.1.8",
89
94
  "@types/semver": "^7.7.0",
90
95
  "@types/shelljs": "^0.8.17",
91
96
  "@types/uglify-js": "^3.17.5",
92
- "@typescript-eslint/eslint-plugin": "^8.22.0",
93
- "@typescript-eslint/parser": "^8.22.0",
97
+ "@typescript-eslint/eslint-plugin": "^8.56.0",
98
+ "@typescript-eslint/parser": "^8.56.0",
94
99
  "compressing": "^1.10.3",
95
100
  "diff": "^8.0.2",
96
101
  "eslint": "^9.29.0",
97
102
  "eslint-config-prettier": "^8.5.0",
98
- "eslint-plugin-import": "^2.31.0",
103
+ "eslint-plugin-import": "^2.32.0",
99
104
  "eslint-plugin-jsdoc": "^50.6.3",
100
105
  "eslint-plugin-prefer-arrow": "^1.2.3",
101
- "eslint-plugin-unicorn": "^42.0.0",
106
+ "eslint-plugin-unicorn": "^63.0.0",
102
107
  "husky": "^9.1.6",
103
- "jest": "^30.0.4",
104
- "jest-each": "^30.0.2",
108
+ "jest": "^30.2.0",
109
+ "jest-each": "^30.2.0",
105
110
  "jest-junit": "^16.0.0",
106
- "jest-mock": "^30.0.2",
111
+ "jest-mock": "^30.2.0",
107
112
  "npm-check-updates": "^18.0.1",
108
113
  "prettier": "^2.6.1",
114
+ "react": "19.2.3",
115
+ "react-native": "^0.84.0",
109
116
  "react-native-gesture-handler": "^2.28.0",
117
+ "react-test-renderer": "19.2.3",
110
118
  "rollup": "^4.52.4",
111
119
  "rollup-plugin-dts": "^6.2.3",
112
120
  "shelljs": "^0.10.0",
@@ -167,6 +175,7 @@
167
175
  "lib/next/events/modifier/*.js",
168
176
  "lib/next/events/spec/*.js",
169
177
  "lib/next/provider/*.js",
178
+ "lib/features/ui-interaction/*.js",
170
179
  "src/lib/core/interface/NativeDynatraceBridge.ts",
171
180
  "types.d.ts"
172
181
  ],
@@ -111,7 +111,7 @@ Pod::Spec.new do |s|
111
111
  #
112
112
 
113
113
  s.dependency "React"
114
- s.dependency 'Dynatrace', '~> 8.331.1.1008'
114
+ s.dependency 'Dynatrace', '~> 8.333.1.1005'
115
115
 
116
116
  # Allows for better compatibility for older and newer versions
117
117
  if defined?(install_modules_dependencies)
package/scripts/Config.js CHANGED
@@ -34,6 +34,7 @@ exports.defaultConfig = {
34
34
  navigation: {
35
35
  enabled: true,
36
36
  },
37
+ userInteraction: false,
37
38
  sourcemap: {
38
39
  enabled: true,
39
40
  androidSourcemapLocation: 'app/build/generated/sourcemaps/react/release/index.android.bundle.map',
@@ -177,6 +177,7 @@ export interface Spec extends TurboModule {
177
177
  export type NativeUserPrivacyOptions = {
178
178
  dataCollectionLevel: string;
179
179
  crashReportingOptedIn: boolean;
180
+ screenRecordOptedIn?: boolean;
180
181
  };
181
182
 
182
183
  export default TurboModuleRegistry.getEnforcing<Spec>('DynatraceBridge');
package/types.d.ts CHANGED
@@ -126,11 +126,13 @@ declare enum DataCollectionLevel {
126
126
  declare class UserPrivacyOptions {
127
127
  private _dataCollectionLevel;
128
128
  private _crashReportingOptedIn;
129
+ private _screenRecordOptedIn;
129
130
  /**
130
131
  * Creates a new UserPrivacyOptions instance with the specified privacy settings.
131
132
  *
132
133
  * @param {DataCollectionLevel} dataCollectionLevel The level of data collection to allow
133
134
  * @param {boolean} crashReportingOptedIn Whether crash reporting should be enabled
135
+ * @param {boolean} screenRecordOptedIn Whether screen recording (Session Replay) should be enabled
134
136
  *
135
137
  * @example
136
138
  * ```ts
@@ -147,7 +149,7 @@ declare class UserPrivacyOptions {
147
149
  *
148
150
  * @see https://www.npmjs.com/package/@dynatrace/react-native-plugin#user-privacy-options
149
151
  */
150
- constructor(dataCollectionLevel: DataCollectionLevel, crashReportingOptedIn: boolean);
152
+ constructor(dataCollectionLevel: DataCollectionLevel, crashReportingOptedIn: boolean, screenRecordOptedIn?: boolean);
151
153
  /**
152
154
  * Gets the current data collection level.
153
155
  *
@@ -216,6 +218,8 @@ declare class UserPrivacyOptions {
216
218
  * @see https://www.npmjs.com/package/@dynatrace/react-native-plugin#user-privacy-options
217
219
  */
218
220
  set dataCollectionLevel(dataCollectionLevel: DataCollectionLevel);
221
+ get screenRecordOptedIn(): boolean;
222
+ set screenRecordOptedIn(screenRecordOptedIn: boolean);
219
223
  }
220
224
 
221
225
  /**
@@ -394,15 +398,16 @@ interface IDynatraceAction {
394
398
  */
395
399
  cancel(platform?: Platform): void;
396
400
  /**
397
- * Generates a Dynatrace request tag for manual web request tagging. This tag must be added as an
398
- * HTTP header to link the web request with this mobile action. The header key can be obtained
399
- * using `getRequestTagHeader()`.
401
+ * Generates a unique x-dynatrace header for the web request with a specified url,
402
+ * which has to be manually added as http header.
400
403
  *
401
- * The tag value is evaluated by the Dynatrace web server agent, which links server-side PurePath
402
- * data with this mobile user action for end-to-end tracing.
404
+ * This is the same tag that was provided when constructing the DynatraceWebRequestTiming instance.
405
+ * The header key can be obtained with the method getRequestTagHeader.
403
406
  *
404
- * **Note:** The returned string may be empty if the Dynatrace agent is disabled or not started yet,
405
- * if communication with the Dynatrace server fails, or if privacy settings do not allow monitoring of requests.
407
+ * The string value can be empty in cases when the agent is not able to send data, the agent is turned off completly,
408
+ * has not started yet or is not allowed to track web requests because of privacy reasons.
409
+ * The tag value is evaluated by the corresponding web server agent.
410
+ * The Dynatrace server will link the server-side PurePath data with this mobile user action.
406
411
  *
407
412
  * @param {string} url The URL of the request you want to track
408
413
  * @returns {Promise<string>} The request tag value to be used as the HTTP header value
@@ -2081,8 +2086,16 @@ interface IDynatraceWebRequestTiming {
2081
2086
  */
2082
2087
  stopWebRequestTimingWithSize(responseCode: number, responseMessage: string, requestSize: number, responseSize: number): void;
2083
2088
  /**
2084
- * Returns the request tag value that should be used as the HTTP header value for tracking.
2089
+ * Generates a unique x-dynatrace header for the web request with a specified url,
2090
+ * which has to be manually added as http header.
2091
+ *
2085
2092
  * This is the same tag that was provided when constructing the DynatraceWebRequestTiming instance.
2093
+ * The header key can be obtained with the method getRequestTagHeader.
2094
+ *
2095
+ * The string value can be empty in cases when the agent is not able to send data, the agent is turned off completly,
2096
+ * has not started yet or is not allowed to track web requests because of privacy reasons.
2097
+ * The tag value is evaluated by the corresponding web server agent.
2098
+ * The Dynatrace server will link the server-side PurePath data with this mobile user action.
2086
2099
  *
2087
2100
  * @returns {string} The request tag value to be used as the HTTP header value
2088
2101
  *