@dynatrace/react-native-plugin 2.321.2 → 2.323.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 CHANGED
@@ -32,8 +32,8 @@ If you want to start using this plugin and are not a Dynatrace customer yet, hea
32
32
  ## Agent Versions
33
33
  This agent versions are configured in this plugin:
34
34
 
35
- * Android Agent: 8.321.1.1009
36
- * iOS Agent: 8.321.1.1007
35
+ * Android Agent: 8.323.1.1002
36
+ * iOS Agent: 8.323.1.1009
37
37
 
38
38
  ## Quick Setup
39
39
 
@@ -83,6 +83,7 @@ This agent versions are configured in this plugin:
83
83
  * [Maven Central in top-level gradle file](#maven-central-in-top-level-gradle-file)
84
84
  * [Configuration of standalone React Native project](#configuration-of-standalone-react-native-project)
85
85
  * [Instrumentation Overhead](#instrumentation-overhead)
86
+ * [Typescript Setup for dtActionName and dtActionIgnore](#typescript-setup-for-dtactionignore-and-dtactionname)
86
87
 
87
88
  ## Troubleshooting
88
89
  * [Documentation](#dynatrace-documentation)
@@ -681,11 +682,7 @@ export default TouchableHighlightScreen;
681
682
 
682
683
  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.
683
684
 
684
- If you want to set this property and use typescript you can use the following workaround:
685
-
686
- ```ts
687
- <TouchableHighlight {...{ "dtActionIgnore": "true" }}><Text>TouchableHighlight that will be ignored</Text></TouchableHighlight>
688
- ```
685
+ >*Attention:* If you are using Typescript and want to set this property with type-safety, look [here](#typescript-setup-for-dtactionignore-and-dtactionname).
689
686
  ## NPX Commands
690
687
 
691
688
  The following npx commands are available for the plugin:
@@ -1128,20 +1125,18 @@ ios: {
1128
1125
 
1129
1126
  ## Using dtActionName to change the name of the action
1130
1127
 
1131
- We check for a property named `dtActionName` when creating an action. If `dtActionName` exists, this will be used for the action name above every other option listed in the previous section. Examples:
1132
-
1133
- Typescript:
1134
- ```ts
1135
- <TouchableHighlight {...{ "dtActionName": "CustomActionName" }}><Text>Custom Action Name</Text></TouchableHighlight>
1136
- ```
1128
+ We check for a property named `dtActionName` when creating an action. If `dtActionName` exists, this will be used for the action name above every other option listed in the previous section. Example:
1137
1129
 
1138
- JavaScript:
1139
1130
  ```js
1140
- <TouchableHighlight dtActionName="CustomActionName"><Text>Custom Action Name</Text></TouchableHighlight>
1131
+ <TouchableHighlight dtActionName="CustomActionName">
1132
+ <Text>Custom Action Name</Text>
1133
+ </TouchableHighlight>
1141
1134
  ```
1142
1135
 
1143
1136
  *Note:* [actionNamePrivacy](#plugin-startup) has no impact on using dtActionName. dtActionName will always be used.
1144
1137
 
1138
+ >*Attention:* If you are using Typescript and want to set this property with type-safety, look [here](#typescript-setup-for-dtactionignore-and-dtactionname).
1139
+
1145
1140
  ## How does Dynatrace automatically report crashes?
1146
1141
 
1147
1142
  In general, Dynatrace always closes the session when a crash occurs. Usually a crash is when the application gets fully terminated. In React Native, we also see fatal errors in the JavaScript part as a full crash even though the native application is still alive. When this happens we will end the session. This is due to visibility reasons and may change in the future. The automated crash reporting will be (automatically) put in place by the transformer at the very beginning of the application. Using a custom error handler afterwards will not interfere with our crash handler.
@@ -1424,6 +1419,24 @@ When using auto-instrumenation through our plugin, here are some examples of the
1424
1419
  | Android | Default new app | 0.74.3 | 50.7 MB | 50.9 MB | 0.2 MB |
1425
1420
  | iOS | Default new app | 0.74.3 | 28.1 MB | 36.5 MB | 8.4 MB |
1426
1421
 
1422
+ ## Typescript Setup for dtActionIgnore and dtActionName
1423
+
1424
+ We are using module augmentation to augment the IntrinsicAttributes Interface in the JSX namespace in the React module with dtActionName and dtActionIgnore. The IntrinsicAttributes Interface in the JSX namespace contains properties that you can pass to every JSX element, thus, in short, you can use dtActionName and dtActionIgnore with full type-safety on every JSX element if you follow the setup below.
1425
+
1426
+ In general, ambient/global type declarations in packages like @dynatrace/react-native-plugin in your node_modules are visible and thus available to you for type checking in at least these cases:
1427
+
1428
+ 1. You import any type from a .ts or .d.ts file located in our package anywhere in your project. For instance, if you do `import { Dynatrace } from '@dynatrace/react-native-plugin'` anywhere in your project, Typescript will consider our Types and the module augmentation will work.
1429
+
1430
+ 2. You update your `tsconfig.json` to include our types, which will also make the module augmentation work:
1431
+ ```json
1432
+ "compilerOptions": {
1433
+ "types": [
1434
+ "@dynatrace/react-native-plugin"
1435
+ ]
1436
+ }
1437
+ ```
1438
+ We recommend the second option, since it works independent of whether you import anything from `@dynatrace/react-native-plugin`. We simply show the first option in case you wonder why `dtActionName` and `dtActionIgnore` are available on JSX elements despite not having added any configuration.
1439
+
1427
1440
  ## Troubleshooting and applicable restrictions
1428
1441
 
1429
1442
  >**Attention:** If you think something is not working the way it should, ALWAYS try to reset the cache of metro first before starting a support case. You can do this via the CLI *react-native start --reset-cache*. If it still does not work feel free to open a support case.
@@ -1464,6 +1477,11 @@ If you are struggling with a problem, submit a support ticket to Dynatrace (supp
1464
1477
  <br/><br/>
1465
1478
  ## Changelog
1466
1479
 
1480
+ 2.323.1
1481
+ * Updated Android (8.323.1.1002) & iOS Agent (8.323.1.1009)
1482
+ * Fixing Touchable/Text instrumentation for React Native 0.81+
1483
+ * Added [module augmentation of React](#typescript-setup-for-dtactionignore-and-dtactionname) to allow using dtActionName and dtActionIgnore type-safely on every JSX Element
1484
+
1467
1485
  2.321.1
1468
1486
  * Updated Android (8.321.1.1009) & iOS Agent (8.321.1.1007)
1469
1487
  * Auto startup fixed for React Native v0.80 and higher
@@ -72,7 +72,7 @@ repositories {
72
72
  }
73
73
 
74
74
  dependencies {
75
- implementation 'com.dynatrace.agent:agent-android:8.321.1.1009'
75
+ implementation 'com.dynatrace.agent:agent-android:8.323.1.1002'
76
76
  implementation "com.facebook.react:react-native:${safeExtGet('reactNative', '+')}"
77
77
  }
78
78
 
@@ -1,4 +1,4 @@
1
1
  // TEMPLATE: plugin-gradle.template
2
2
  dependencies {
3
- classpath 'com.dynatrace.tools.android:gradle-plugin:8.321.1.1009'
3
+ classpath 'com.dynatrace.tools.android:gradle-plugin:8.323.1.1002'
4
4
  }
@@ -16,7 +16,7 @@ const createElement = (type, props, ...children) => {
16
16
  return _createElement(ClassComponent_1.DynatraceClassComponent, {}, _createElement(type, props, ...children));
17
17
  }
18
18
  else {
19
- (0, ElementHelper_1.modifyElement)(type, props, ...children);
19
+ (0, ElementHelper_1.modifyElement)(type, props);
20
20
  }
21
21
  }
22
22
  return _createElement(type, props, ...children);
@@ -2,11 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isDtActionIgnore = exports.modifyElement = exports.instrumentCreateElement = void 0;
4
4
  const Types_1 = require("../model/Types");
5
- const TypesUtil_1 = require("../model/TypesUtil");
6
5
  const Dynatrace_1 = require("../../lib/core/Dynatrace");
7
- const ConsoleLogger_1 = require("../../lib/core/logging/ConsoleLogger");
8
6
  const Picker_1 = require("./components/Picker");
9
- const Touchable_1 = require("./components/Touchable");
10
7
  const RefreshControl_1 = require("./components/RefreshControl");
11
8
  const Switch_1 = require("./components/Switch");
12
9
  const FunctionalComponent_1 = require("./components/FunctionalComponent");
@@ -27,7 +24,7 @@ const instrumentCreateElement = (reactModule) => {
27
24
  return reactCreateElement(ClassComponent_1.DynatraceClassComponent, {}, reactCreateElement(type, props, ...children));
28
25
  }
29
26
  else {
30
- (0, exports.modifyElement)(type, props, ...children);
27
+ (0, exports.modifyElement)(type, props);
31
28
  }
32
29
  }
33
30
  return reactCreateElement(type, props, ...children);
@@ -35,7 +32,7 @@ const instrumentCreateElement = (reactModule) => {
35
32
  }
36
33
  };
37
34
  exports.instrumentCreateElement = instrumentCreateElement;
38
- const modifyElement = (type, props, ...children) => {
35
+ const modifyElement = (type, props) => {
39
36
  if (props != null) {
40
37
  if (type._dtInfo.type === Types_1.Types.RefreshControl &&
41
38
  props.onRefresh != null) {
@@ -45,17 +42,6 @@ const modifyElement = (type, props, ...children) => {
45
42
  props.onValueChange != null) {
46
43
  (0, Switch_1.SwitchHelper)(Dynatrace_1.Dynatrace).attachOnValueChange(props);
47
44
  }
48
- else if (type._dtInfo.type === Types_1.Types.Button ||
49
- type._dtInfo.type === Types_1.Types.Text ||
50
- type._dtInfo.type === Types_1.Types.Pressable ||
51
- (0, TypesUtil_1.isTypeTouchable)(type._dtInfo.type)) {
52
- if (props.onPress != null) {
53
- props.onPress = (0, Touchable_1.TouchableHelper)(Dynatrace_1.Dynatrace, new ConsoleLogger_1.ConsoleLogger('TouchableHelper')).attachOnPress(false, props, children, type._dtInfo.type);
54
- }
55
- if (props.onLongPress != null) {
56
- props.onLongPress = (0, Touchable_1.TouchableHelper)(Dynatrace_1.Dynatrace, new ConsoleLogger_1.ConsoleLogger('TouchableHelper')).attachOnPress(true, props, children, type._dtInfo.type);
57
- }
58
- }
59
45
  else if (props.onValueChange != null &&
60
46
  type._dtInfo.type === Types_1.Types.Picker) {
61
47
  (0, Picker_1.PickerHelper)(Dynatrace_1.Dynatrace).attachOnValueChange(props);
@@ -1,9 +1,2 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isDynatraceIgnored = exports.isDynatraceNaming = void 0;
4
- const isDynatraceNaming = (properties) => properties.dtActionName !== undefined;
5
- exports.isDynatraceNaming = isDynatraceNaming;
6
- const isDynatraceIgnored = (properties) => (properties.dtActionIgnore !== undefined &&
7
- properties.dtActionIgnore === true) ||
8
- properties.dtActionIgnore === 'true';
9
- exports.isDynatraceIgnored = isDynatraceIgnored;
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ReactDevRuntime = require("react/jsx-dev-runtime");
3
4
  const Types_1 = require("../model/Types");
4
5
  const FunctionalComponent_1 = require("./components/FunctionalComponent");
5
6
  const ClassComponent_1 = require("./components/ClassComponent");
6
7
  const ElementHelper_1 = require("./ElementHelper");
7
- const ReactDevRuntime = require("react/jsx-dev-runtime");
8
8
  try {
9
9
  const jsxDEV = (...args) => {
10
10
  if (args[0] !== undefined &&
@@ -38,12 +38,7 @@ try {
38
38
  return ReactDevRuntime.jsxDEV(ClassComponent_1.DynatraceClassComponent, wrapperProps);
39
39
  }
40
40
  }
41
- if (Array.isArray(args[1].children)) {
42
- (0, ElementHelper_1.modifyElement)(args[0], args[1], ...args[1].children);
43
- }
44
- else {
45
- (0, ElementHelper_1.modifyElement)(args[0], args[1], args[1].children);
46
- }
41
+ (0, ElementHelper_1.modifyElement)(args[0], args[1]);
47
42
  }
48
43
  return ReactDevRuntime.jsxDEV(...args);
49
44
  };
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ReactRuntime = require("react/jsx-runtime");
3
4
  const Types_1 = require("../model/Types");
4
5
  const FunctionalComponent_1 = require("./components/FunctionalComponent");
5
6
  const ClassComponent_1 = require("./components/ClassComponent");
6
7
  const ElementHelper_1 = require("./ElementHelper");
7
- const ReactRuntime = require("react/jsx-runtime");
8
8
  const instrumentJsxCall = (jsxFunction) => (...args) => {
9
9
  if (args[0] !== undefined &&
10
10
  args[0]._dtInfo !== undefined &&
@@ -37,12 +37,7 @@ const instrumentJsxCall = (jsxFunction) => (...args) => {
37
37
  return jsxFunction(ClassComponent_1.DynatraceClassComponent, wrapperProps);
38
38
  }
39
39
  }
40
- if (Array.isArray(args[1].children)) {
41
- (0, ElementHelper_1.modifyElement)(args[0], args[1], ...args[1].children);
42
- }
43
- else {
44
- (0, ElementHelper_1.modifyElement)(args[0], args[1], args[1].children);
45
- }
40
+ (0, ElementHelper_1.modifyElement)(args[0], args[1]);
46
41
  }
47
42
  return jsxFunction(...args);
48
43
  };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getNameFromComponent = void 0;
3
+ exports.isDynatraceIgnored = exports.isDynatraceNaming = exports.getNameFromComponent = void 0;
4
4
  const getNameFromComponent = (props) => {
5
5
  if (props !== undefined && props.children !== undefined) {
6
6
  let child;
@@ -31,3 +31,14 @@ const getNameFromComponent = (props) => {
31
31
  }
32
32
  };
33
33
  exports.getNameFromComponent = getNameFromComponent;
34
+ const isDynatraceNaming = (properties) => typeof properties === 'object' &&
35
+ properties !== null &&
36
+ 'dtActionName' in properties &&
37
+ typeof properties.dtActionName === 'string';
38
+ exports.isDynatraceNaming = isDynatraceNaming;
39
+ const isDynatraceIgnored = (properties) => typeof properties === 'object' &&
40
+ properties !== null &&
41
+ 'dtActionIgnore' in properties &&
42
+ (properties.dtActionIgnore === true ||
43
+ properties.dtActionIgnore === 'true');
44
+ exports.isDynatraceIgnored = isDynatraceIgnored;
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PickerHelper = void 0;
4
- const IDynatraceProperties_1 = require("../IDynatraceProperties");
4
+ const ComponentUtil_1 = require("./ComponentUtil");
5
5
  const PickerHelper = (Dynatrace) => ({
6
6
  attachOnValueChange: (pickerProps) => {
7
- if ((0, IDynatraceProperties_1.isDynatraceIgnored)(pickerProps)) {
7
+ if ((0, ComponentUtil_1.isDynatraceIgnored)(pickerProps)) {
8
8
  return;
9
9
  }
10
10
  const origOnValueChange = pickerProps.onValueChange;
@@ -31,7 +31,7 @@ const PickerHelper = (Dynatrace) => ({
31
31
  exports.PickerHelper = PickerHelper;
32
32
  const isPickerItemProps = (props) => props.label !== undefined;
33
33
  const _findActionName = (pickerProps) => {
34
- if ((0, IDynatraceProperties_1.isDynatraceNaming)(pickerProps)) {
34
+ if ((0, ComponentUtil_1.isDynatraceNaming)(pickerProps)) {
35
35
  return pickerProps.dtActionName;
36
36
  }
37
37
  else if (pickerProps.accessibilityLabel != null) {
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RefreshControlHelper = void 0;
4
- const IDynatraceProperties_1 = require("../IDynatraceProperties");
4
+ const ComponentUtil_1 = require("./ComponentUtil");
5
5
  const RefreshControlHelper = (Dynatrace) => ({
6
6
  attachOnRefresh: (refreshControlProps) => {
7
- if ((0, IDynatraceProperties_1.isDynatraceIgnored)(refreshControlProps)) {
7
+ if ((0, ComponentUtil_1.isDynatraceIgnored)(refreshControlProps)) {
8
8
  return;
9
9
  }
10
10
  const origOnRefresh = refreshControlProps.onRefresh;
@@ -29,7 +29,7 @@ const RefreshControlHelper = (Dynatrace) => ({
29
29
  });
30
30
  exports.RefreshControlHelper = RefreshControlHelper;
31
31
  const _findActionName = (refreshControlProps) => {
32
- if ((0, IDynatraceProperties_1.isDynatraceNaming)(refreshControlProps)) {
32
+ if ((0, ComponentUtil_1.isDynatraceNaming)(refreshControlProps)) {
33
33
  return refreshControlProps.dtActionName;
34
34
  }
35
35
  else if (refreshControlProps.accessibilityLabel != null) {
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SwitchHelper = void 0;
4
- const IDynatraceProperties_1 = require("../IDynatraceProperties");
4
+ const ComponentUtil_1 = require("./ComponentUtil");
5
5
  const ConfigurationHandler_1 = require("../../../lib/core/configuration/ConfigurationHandler");
6
6
  const SwitchHelper = (Dynatrace) => ({
7
7
  attachOnValueChange: (switchProps) => {
8
- if ((0, IDynatraceProperties_1.isDynatraceIgnored)(switchProps)) {
8
+ if ((0, ComponentUtil_1.isDynatraceIgnored)(switchProps)) {
9
9
  return;
10
10
  }
11
11
  const origOnValueChange = switchProps.onValueChange;
@@ -13,7 +13,7 @@ const SwitchHelper = (Dynatrace) => ({
13
13
  if (origOnValueChange != null) {
14
14
  switchProps.onValueChange = (value) => {
15
15
  const useGenericName = nameOfAction == null ||
16
- (!(0, IDynatraceProperties_1.isDynatraceNaming)(switchProps) &&
16
+ (!(0, ComponentUtil_1.isDynatraceNaming)(switchProps) &&
17
17
  ConfigurationHandler_1.ConfigurationHandler.isActionNamePrivacyEnabled());
18
18
  const finalNameOfAction = useGenericName
19
19
  ? `Touch on Switch to ${value}`
@@ -44,7 +44,7 @@ const SwitchHelper = (Dynatrace) => ({
44
44
  });
45
45
  exports.SwitchHelper = SwitchHelper;
46
46
  const _findActionName = (switchProps) => {
47
- if ((0, IDynatraceProperties_1.isDynatraceNaming)(switchProps)) {
47
+ if ((0, ComponentUtil_1.isDynatraceNaming)(switchProps)) {
48
48
  return switchProps.dtActionName;
49
49
  }
50
50
  else if (switchProps.accessibilityLabel != null) {
@@ -1,40 +1,10 @@
1
1
  "use strict";
2
- var _a, _b, _c, _d;
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  exports.RectButton = exports.TouchableWithoutFeedback = exports.TouchableNativeFeedback = exports.TouchableHighlight = exports.TouchableOpacity = void 0;
5
- const Types_1 = require("../../../model/Types");
6
- const gestureHandler = require('react-native-gesture-handler');
7
- if (gestureHandler !== undefined) {
8
- if (typeof gestureHandler.TouchableOpacity !== 'object') {
9
- exports.TouchableOpacity = (_a = class TouchableOpacity extends (gestureHandler.TouchableOpacity) {
10
- },
11
- _a._dtInfo = { type: Types_1.Types.TouchableOpacityGestureHandler },
12
- _a);
13
- }
14
- if (typeof gestureHandler.TouchableHighlight !== 'object') {
15
- exports.TouchableHighlight = (_b = class TouchableHighlight extends (gestureHandler.TouchableHighlight) {
16
- },
17
- _b._dtInfo = { type: Types_1.Types.TouchableHighlightGestureHandler },
18
- _b);
19
- }
20
- if (typeof gestureHandler.TouchableNativeFeedback !== 'object') {
21
- exports.TouchableNativeFeedback = (_c = class TouchableNativeFeedback extends (gestureHandler.TouchableNativeFeedback) {
22
- },
23
- _c._dtInfo = {
24
- type: Types_1.Types.TouchableNativeFeedbackGestureHandler,
25
- },
26
- _c);
27
- }
28
- if (typeof gestureHandler.TouchableWithoutFeedback === 'object') {
29
- exports.TouchableWithoutFeedback = Object.assign({ _dtInfo: { type: Types_1.Types.TouchableWithoutFeedbackGestureHandler } }, gestureHandler.TouchableWithoutFeedback);
30
- }
31
- if (typeof gestureHandler.RectButton !== 'object') {
32
- exports.RectButton = (_d = class RectButton extends gestureHandler.RectButton {
33
- },
34
- _d._dtInfo = { type: Types_1.Types.RectButtonGestureHandler },
35
- _d);
36
- }
37
- else {
38
- exports.RectButton = Object.assign({ _dtInfo: { type: Types_1.Types.RectButtonGestureHandler } }, gestureHandler.RectButton);
39
- }
40
- }
4
+ const GestureHandler = require("react-native-gesture-handler");
5
+ const withOnPressMonitoring_1 = require("../../withOnPressMonitoring");
6
+ exports.TouchableOpacity = (0, withOnPressMonitoring_1.withOnPressMonitoring)(GestureHandler.TouchableOpacity, 'Touchable');
7
+ exports.TouchableHighlight = (0, withOnPressMonitoring_1.withOnPressMonitoring)(GestureHandler.TouchableHighlight, 'Touchable');
8
+ exports.TouchableNativeFeedback = (0, withOnPressMonitoring_1.withOnPressMonitoring)(GestureHandler.TouchableNativeFeedback, 'Touchable');
9
+ exports.TouchableWithoutFeedback = (0, withOnPressMonitoring_1.withOnPressMonitoring)(GestureHandler.TouchableWithoutFeedback, 'Touchable');
10
+ exports.RectButton = (0, withOnPressMonitoring_1.withOnPressMonitoring)(GestureHandler.RectButton, 'Button');
@@ -1,51 +1,12 @@
1
1
  "use strict";
2
- var _a, _b, _c, _d;
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  exports.Pressable = exports.Text = exports.TouchableWithoutFeedback = exports.TouchableNativeFeedback = exports.TouchableHighlight = exports.TouchableOpacity = exports.Button = void 0;
5
4
  const ReactNative = require("react-native");
6
- const React = require("react");
7
- const Types_1 = require("../../model/Types");
8
- exports.Button = React.forwardRef((props, ref) => (React.createElement(ReactNative.Button, Object.assign({ title: props.title }, props, { ref: ref }))));
9
- exports.Button._dtInfo = { type: Types_1.Types.Button };
10
- if (typeof ReactNative.TouchableOpacity === 'object') {
11
- exports.TouchableOpacity = Object.assign({ _dtInfo: { type: Types_1.Types.TouchableOpacity } }, ReactNative.TouchableOpacity);
12
- }
13
- else {
14
- exports.TouchableOpacity = (_a = class TouchableOpacity extends (ReactNative.TouchableOpacity) {
15
- },
16
- _a._dtInfo = { type: Types_1.Types.TouchableOpacity },
17
- _a);
18
- }
19
- if (typeof ReactNative.TouchableHighlight === 'object') {
20
- exports.TouchableHighlight = Object.assign({ _dtInfo: { type: Types_1.Types.TouchableHighlight } }, ReactNative.TouchableHighlight);
21
- }
22
- else {
23
- exports.TouchableHighlight = (_b = class TouchableHighlight extends (ReactNative.TouchableHighlight) {
24
- },
25
- _b._dtInfo = { type: Types_1.Types.TouchableHighlight },
26
- _b);
27
- }
28
- if (typeof ReactNative.TouchableNativeFeedback === 'object') {
29
- exports.TouchableNativeFeedback = Object.assign({ _dtInfo: { type: Types_1.Types.TouchableNativeFeedback } }, ReactNative.TouchableNativeFeedback);
30
- }
31
- else {
32
- exports.TouchableNativeFeedback = (_c = class TouchableNativeFeedback extends (ReactNative.TouchableNativeFeedback) {
33
- },
34
- _c._dtInfo = { type: Types_1.Types.TouchableNativeFeedback },
35
- _c);
36
- }
37
- exports.TouchableWithoutFeedback = React.forwardRef((props, ref) => (React.createElement(ReactNative.TouchableWithoutFeedback, Object.assign({}, props, { ref: ref }))));
38
- exports.TouchableWithoutFeedback._dtInfo = {
39
- type: Types_1.Types.TouchableWithoutFeedback,
40
- };
41
- if (typeof ReactNative.Text === 'object') {
42
- exports.Text = Object.assign({ _dtInfo: { type: Types_1.Types.Text } }, ReactNative.Text);
43
- }
44
- else {
45
- exports.Text = (_d = class Text extends ReactNative.Text {
46
- },
47
- _d._dtInfo = { type: Types_1.Types.Text },
48
- _d);
49
- }
50
- exports.Pressable = React.forwardRef((props, ref) => (React.createElement(ReactNative.Pressable, Object.assign({}, props, { ref: ref }))));
51
- exports.Pressable._dtInfo = { type: Types_1.Types.Pressable };
5
+ const withOnPressMonitoring_1 = require("../withOnPressMonitoring");
6
+ exports.Button = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.Button, 'Button');
7
+ exports.TouchableOpacity = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.TouchableOpacity, 'Touchable');
8
+ exports.TouchableHighlight = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.TouchableHighlight, 'Touchable');
9
+ exports.TouchableNativeFeedback = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.TouchableNativeFeedback, 'Touchable');
10
+ exports.TouchableWithoutFeedback = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.TouchableWithoutFeedback, 'Touchable');
11
+ exports.Text = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.Text, 'Text');
12
+ exports.Pressable = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.Pressable, 'Pressable');
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findTouchableName = exports.chooseTouchableName = exports.wrapOnPress = exports.withOnPressMonitoring = void 0;
4
+ const ReactNative = require("react-native");
5
+ const React = require("react");
6
+ const ConsoleLogger_1 = require("../../lib/core/logging/ConsoleLogger");
7
+ const ConfigurationHandler_1 = require("../../lib/core/configuration/ConfigurationHandler");
8
+ const Dynatrace_1 = require("../../lib/core/Dynatrace");
9
+ const ComponentUtil_1 = require("../jsx/components/ComponentUtil");
10
+ const Logger = new ConsoleLogger_1.ConsoleLogger('TouchableHelper');
11
+ function withOnPressMonitoring(Component, fallbackName) {
12
+ return React.forwardRef((props, ref) => {
13
+ const { onPress, onLongPress } = props;
14
+ const touchableName = (0, exports.chooseTouchableName)(props, fallbackName);
15
+ const dynatraceIgnored = (0, ComponentUtil_1.isDynatraceIgnored)(props);
16
+ const propsWithoutRef = Object.assign(Object.assign(Object.assign({}, props), (!dynatraceIgnored &&
17
+ onPress && {
18
+ onPress: (0, exports.wrapOnPress)(onPress, touchableName),
19
+ })), (!dynatraceIgnored &&
20
+ onLongPress && {
21
+ onLongPress: (0, exports.wrapOnPress)(onLongPress, touchableName),
22
+ }));
23
+ const propsWithRef = Object.assign(Object.assign({}, propsWithoutRef), { ref });
24
+ return React.createElement(Component, Object.assign({}, propsWithRef));
25
+ });
26
+ }
27
+ exports.withOnPressMonitoring = withOnPressMonitoring;
28
+ const wrapOnPress = (onPress, touchableName) => {
29
+ return (...args) => {
30
+ if (!ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) {
31
+ Logger.info('React Native plugin has not been started yet! Touch will not be reported!');
32
+ onPress(...args);
33
+ }
34
+ else {
35
+ const action = Dynatrace_1.Dynatrace.enterAutoAction(`Touch on ${touchableName}`);
36
+ let isSync = true;
37
+ try {
38
+ const returnValue = onPress(...args);
39
+ if (returnValue instanceof Promise) {
40
+ isSync = false;
41
+ return Promise.resolve(returnValue).finally(() => {
42
+ action.leaveAction();
43
+ });
44
+ }
45
+ }
46
+ finally {
47
+ if (isSync) {
48
+ action.leaveAction();
49
+ }
50
+ }
51
+ }
52
+ };
53
+ };
54
+ exports.wrapOnPress = wrapOnPress;
55
+ const chooseTouchableName = (props, fallbackName) => {
56
+ if (props.dtActionName) {
57
+ return props.dtActionName;
58
+ }
59
+ if (ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable() &&
60
+ ConfigurationHandler_1.ConfigurationHandler.isActionNamePrivacyEnabled()) {
61
+ return fallbackName;
62
+ }
63
+ return (0, exports.findTouchableName)(props) || fallbackName;
64
+ };
65
+ exports.chooseTouchableName = chooseTouchableName;
66
+ const findTouchableName = (props) => {
67
+ if ('title' in props) {
68
+ return props.title;
69
+ }
70
+ if (props.accessibilityLabel !== undefined) {
71
+ return props.accessibilityLabel;
72
+ }
73
+ if (typeof props.children === 'function') {
74
+ return findTouchableNameRecursive(props.children({ pressed: false }));
75
+ }
76
+ return findTouchableNameRecursive(props.children);
77
+ };
78
+ exports.findTouchableName = findTouchableName;
79
+ function findTouchableNameRecursive(node) {
80
+ if (typeof node === 'string') {
81
+ return node;
82
+ }
83
+ if (isReactNodeIterable(node)) {
84
+ for (const child of node) {
85
+ const result = findTouchableNameRecursive(child);
86
+ if (result !== null)
87
+ return result;
88
+ }
89
+ }
90
+ if (React.isValidElement(node)) {
91
+ if (isReactNativeImage(node)) {
92
+ const uri = getUriFromSource(node.props.source);
93
+ return uri ? 'Image Button: ' + uri : 'Image Button';
94
+ }
95
+ if (isCustomIcon(node)) {
96
+ return node.props.name;
97
+ }
98
+ if (hasReactNodeChildren(node))
99
+ return findTouchableNameRecursive(node.props.children);
100
+ }
101
+ return null;
102
+ }
103
+ function getUriFromSource(source) {
104
+ if (typeof source === 'object' &&
105
+ 'uri' in source &&
106
+ source.uri !== undefined) {
107
+ return source.uri;
108
+ }
109
+ return null;
110
+ }
111
+ const isReactNodeIterable = (node) => typeof node === 'object' && node !== null && Symbol.iterator in node;
112
+ const isReactNativeImage = (element) => element.type === ReactNative.Image;
113
+ const isCustomIcon = (element) => typeof element.type === 'function' &&
114
+ element.type.name === 'Icon' &&
115
+ typeof element.props === 'object' &&
116
+ element.props !== null &&
117
+ 'name' in element.props &&
118
+ typeof element.props.name === 'string';
119
+ const hasReactNodeChildren = (element) => typeof element.props === 'object' &&
120
+ element.props !== null &&
121
+ 'children' in element.props;
@@ -5,19 +5,7 @@ var Types;
5
5
  (function (Types) {
6
6
  Types[Types["FunctionalComponent"] = 0] = "FunctionalComponent";
7
7
  Types[Types["ClassComponent"] = 1] = "ClassComponent";
8
- Types[Types["Button"] = 2] = "Button";
9
- Types[Types["TouchableOpacity"] = 3] = "TouchableOpacity";
10
- Types[Types["TouchableHighlight"] = 4] = "TouchableHighlight";
11
- Types[Types["TouchableNativeFeedback"] = 5] = "TouchableNativeFeedback";
12
- Types[Types["TouchableWithoutFeedback"] = 6] = "TouchableWithoutFeedback";
13
- Types[Types["Text"] = 7] = "Text";
14
- Types[Types["Picker"] = 8] = "Picker";
15
- Types[Types["Pressable"] = 9] = "Pressable";
16
- Types[Types["TouchableOpacityGestureHandler"] = 10] = "TouchableOpacityGestureHandler";
17
- Types[Types["TouchableHighlightGestureHandler"] = 11] = "TouchableHighlightGestureHandler";
18
- Types[Types["TouchableNativeFeedbackGestureHandler"] = 12] = "TouchableNativeFeedbackGestureHandler";
19
- Types[Types["TouchableWithoutFeedbackGestureHandler"] = 13] = "TouchableWithoutFeedbackGestureHandler";
20
- Types[Types["RectButtonGestureHandler"] = 14] = "RectButtonGestureHandler";
21
- Types[Types["RefreshControl"] = 15] = "RefreshControl";
22
- Types[Types["Switch"] = 16] = "Switch";
8
+ Types[Types["Picker"] = 2] = "Picker";
9
+ Types[Types["RefreshControl"] = 3] = "RefreshControl";
10
+ Types[Types["Switch"] = 4] = "Switch";
23
11
  })(Types = exports.Types || (exports.Types = {}));
@@ -1,48 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getNameForType = exports.isTypeTouchable = exports.isTypeGestureHandlerTouchable = exports.isTypeReactNativeTouchable = void 0;
3
+ exports.getNameForType = void 0;
4
4
  const Types_1 = require("./Types");
5
- const isTypeReactNativeTouchable = (type) => type === Types_1.Types.TouchableHighlight ||
6
- type === Types_1.Types.TouchableNativeFeedback ||
7
- type === Types_1.Types.TouchableOpacity ||
8
- type === Types_1.Types.TouchableWithoutFeedback;
9
- exports.isTypeReactNativeTouchable = isTypeReactNativeTouchable;
10
- const isTypeGestureHandlerTouchable = (type) => type === Types_1.Types.TouchableHighlightGestureHandler ||
11
- type === Types_1.Types.TouchableNativeFeedbackGestureHandler ||
12
- type === Types_1.Types.TouchableOpacityGestureHandler ||
13
- type === Types_1.Types.TouchableWithoutFeedbackGestureHandler ||
14
- type === Types_1.Types.RectButtonGestureHandler;
15
- exports.isTypeGestureHandlerTouchable = isTypeGestureHandlerTouchable;
16
- const isTypeTouchable = (type) => (0, exports.isTypeGestureHandlerTouchable)(type) || (0, exports.isTypeReactNativeTouchable)(type);
17
- exports.isTypeTouchable = isTypeTouchable;
18
5
  const getNameForType = (type) => {
19
6
  switch (type) {
20
- case Types_1.Types.Button:
21
- case Types_1.Types.RectButtonGestureHandler:
22
- return 'Button';
23
- case Types_1.Types.Text:
24
- return 'Text';
25
- case Types_1.Types.TouchableHighlight:
26
- case Types_1.Types.TouchableNativeFeedback:
27
- case Types_1.Types.TouchableOpacity:
28
- case Types_1.Types.TouchableWithoutFeedback:
29
- case Types_1.Types.TouchableHighlightGestureHandler:
30
- case Types_1.Types.TouchableNativeFeedbackGestureHandler:
31
- case Types_1.Types.TouchableOpacityGestureHandler:
32
- case Types_1.Types.TouchableWithoutFeedbackGestureHandler:
33
- return 'Touchable';
34
- case Types_1.Types.Pressable:
35
- return 'Pressable';
7
+ case Types_1.Types.FunctionalComponent:
8
+ return 'Functional Component';
9
+ case Types_1.Types.ClassComponent:
10
+ return 'Class Component';
36
11
  case Types_1.Types.Picker:
37
12
  return 'Picker';
38
13
  case Types_1.Types.RefreshControl:
39
14
  return 'Refresh Control';
40
15
  case Types_1.Types.Switch:
41
16
  return 'Switch';
42
- case Types_1.Types.ClassComponent:
43
- return 'Class Component';
44
- case Types_1.Types.FunctionalComponent:
45
- return 'Functional Component';
46
17
  default:
47
18
  return 'Undefined';
48
19
  }
@@ -44,6 +44,7 @@ class DynatraceImpl {
44
44
  if (isApiReported) {
45
45
  event["characteristics.is_api_reported"] =
46
46
  true;
47
+ event["dt.support.is_legacy_api_reported"] = true;
47
48
  }
48
49
  EventPipeline_1.EventPipeline.insertEvent(event);
49
50
  }
@@ -54,6 +55,7 @@ class DynatraceImpl {
54
55
  if (isApiReported) {
55
56
  event["characteristics.is_api_reported"] =
56
57
  true;
58
+ event["dt.support.is_legacy_api_reported"] = true;
57
59
  }
58
60
  EventPipeline_1.EventPipeline.insertEvent(event);
59
61
  }
@@ -64,6 +66,7 @@ class DynatraceImpl {
64
66
  if (isApiReported) {
65
67
  event["characteristics.is_api_reported"] =
66
68
  true;
69
+ event["dt.support.is_legacy_api_reported"] = true;
67
70
  }
68
71
  EventPipeline_1.EventPipeline.insertEvent(event);
69
72
  }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ALL_APP_START_KEYS = exports.MODIFY_EVENT_WHITELIST_NAMESPACE = exports.MODIFY_EVENT_WHITELIST_FIELDS = exports.SEND_SESSION_PROPERTY_EVENT_WHITELIST_FIELDS = exports.SEND_EVENT_WHITELIST_FIELDS = exports.SEND_SESSION_PROPERTY_EVENT_WHITELIST_NAMESPACES = exports.SEND_EVENT_WHITELIST_NAMESPACES = exports.AllCharacteristicsKeys = exports.KEY_NAME_REGEX = exports.MAX_CUSTOM_EVENT_VALUE_LENGTH = exports.MAX_CUSTOM_EVENT_KEY_LENGTH = exports.MAX_CUSTOM_EVENT_FIELDS = void 0;
4
- const SPECIFICATION_VERSION = '0.20';
4
+ const SPECIFICATION_VERSION = '0.21';
5
5
  exports.MAX_CUSTOM_EVENT_FIELDS = 50;
6
6
  exports.MAX_CUSTOM_EVENT_KEY_LENGTH = 100;
7
7
  exports.MAX_CUSTOM_EVENT_VALUE_LENGTH = 5000;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynatrace/react-native-plugin",
3
- "version": "2.321.2",
3
+ "version": "2.323.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": "typings/react-native-dynatrace.d.ts",
@@ -101,6 +101,7 @@
101
101
  "jest-mock": "^30.0.2",
102
102
  "npm-check-updates": "^18.0.1",
103
103
  "prettier": "^2.6.1",
104
+ "react-native-gesture-handler": "^2.28.0",
104
105
  "shelljs": "^0.10.0",
105
106
  "ts-jest": "^29.4.0",
106
107
  "typescript": "^4.7.4",
@@ -154,7 +155,8 @@
154
155
  "lib/next/events/modifier/*.js",
155
156
  "lib/next/events/spec/*.js",
156
157
  "lib/next/provider/*.js",
157
- "src/lib/core/interface/NativeDynatraceBridge.ts"
158
+ "src/lib/core/interface/NativeDynatraceBridge.ts",
159
+ "src/instrumentation/jsx/IDynatraceProperties.ts"
158
160
  ],
159
161
  "codegenConfig": {
160
162
  "name": "DynatraceBridgeSpec",
@@ -111,7 +111,7 @@ Pod::Spec.new do |s|
111
111
  #
112
112
 
113
113
  s.dependency "React"
114
- s.dependency 'Dynatrace', '~> 8.321.1.1007'
114
+ s.dependency 'Dynatrace', '~> 8.323.1.1009'
115
115
 
116
116
  # Allows for better compatibility for older and newer versions
117
117
  if defined?(install_modules_dependencies)
package/scripts/Ios.js CHANGED
@@ -186,7 +186,7 @@ const createNewPListIfRequired = (parsedPList, configProps, pathToPList) => {
186
186
  const configIncludingFlavor = configProps + getAdditionalInternalPluginKeys() + updatedExcludedStr(configProps);
187
187
  if (isPropertyCountEqual(parsedPList, configIncludingFlavor) && comparePListAndConfig(parsedPList, configIncludingFlavor)) {
188
188
  Logger_1.default.logMessageSync('Not generating a new plist as the current plist and ' +
189
- ' dynatrace.config.js iOS properties are identical!', Logger_1.default.INFO);
189
+ 'dynatrace.config.js iOS properties are identical!', Logger_1.default.INFO);
190
190
  }
191
191
  else {
192
192
  Logger_1.default.logMessageSync('Generating a new plist as the current plist ' +
package/scripts/Logger.js CHANGED
@@ -41,19 +41,23 @@ const logMessageSync = (_message, _logLevel, _onlyConsole = false) => {
41
41
  catch (e) {
42
42
  }
43
43
  let logString;
44
+ let prefix = '';
44
45
  if (_logLevel === INFO) {
45
46
  logString = '#INFO ';
47
+ prefix = _prefix.info;
46
48
  }
47
49
  else if (_logLevel === WARNING) {
48
50
  logString = '#WARN ';
51
+ prefix = _prefix.warning;
49
52
  }
50
53
  else if (_logLevel === ERROR) {
51
54
  logString = '#ERROR ';
55
+ prefix = _prefix.error;
52
56
  }
53
57
  else {
54
58
  logString = '#NONE ';
55
59
  }
56
- const outputString = logString + '[' + currentDate() + ']: ' + _message;
60
+ const outputString = logString + '[' + currentDate() + ']: ' + prefix + _message;
57
61
  console.log(outputString);
58
62
  if (!_onlyConsole) {
59
63
  fs.appendFileSync(PathsConstants_1.default.getCurrentLogPath(), outputString + '\r\n');
@@ -67,10 +71,25 @@ const currentDate = () => {
67
71
  const localISOTime = (new Date(Date.now() - tzoffset)).toISOString().slice(0, -5);
68
72
  return localISOTime.replace('T', ' ');
69
73
  };
74
+ const noPrefix = {
75
+ info: '',
76
+ warning: '',
77
+ error: '',
78
+ };
79
+ let _prefix = noPrefix;
70
80
  exports.default = {
71
81
  ERROR,
72
82
  INFO,
73
83
  WARNING,
84
+ withPrefix(prefix, callback) {
85
+ try {
86
+ _prefix = Object.assign(Object.assign({}, _prefix), prefix);
87
+ return callback();
88
+ }
89
+ finally {
90
+ _prefix = noPrefix;
91
+ }
92
+ },
74
93
  closeLogFile,
75
94
  logMessageSync,
76
95
  logErrorSync,
@@ -6,14 +6,42 @@ const Logger_1 = require("../Logger");
6
6
  const Config_1 = require("../Config");
7
7
  const android = require("../Android");
8
8
  const PathsConstants_1 = require("../PathsConstants");
9
+ const nodePath = require("path");
9
10
  const Ios_1 = require("../Ios");
10
11
  const InstrumentUtil_1 = require("../util/InstrumentUtil");
11
12
  const CustomArgumentUtil_1 = require("../util/CustomArgumentUtil");
12
13
  const Platform_1 = require("../api/model/Platform");
13
14
  const SourceMapUtil_1 = require("../util/SourceMapUtil");
14
15
  const instrumentCommand = () => {
15
- Logger_1.default.logMessageSync('Starting instrumentation of React Native application ..', Logger_1.default.INFO);
16
- (0, InstrumentUtil_1.showVersionOfPlugin)();
16
+ if (process.argv.includes('--help')) {
17
+ Logger_1.default.logMessageSync(`
18
+ Usage: npx instrumentDynatrace [options]
19
+
20
+ Options:
21
+ --help Show this help message and exit.
22
+ config="/custom/path/to/dynatrace.config.js"
23
+ Specify a custom path to the Dynatrace configuration file.
24
+ Default: ${PathsConstants_1.default.getConfigFilePath()}
25
+ gradle="/custom/path/to/build.gradle(.kts)"
26
+ Specify a custom path to the top level build.gradle file of your android project.
27
+ Default: ${PathsConstants_1.default.getAndroidGradleFile(PathsConstants_1.default.getAndroidFolder())}
28
+ plist="/custom/path/to/Info.plist"
29
+ Specify a custom path to the Info.plist file of your ios project.
30
+ Default: Extracts <appName> from app.json and then tries
31
+ ${nodePath.join(PathsConstants_1.default.getIOSFolder(), "<appName>", 'Info.plist')}
32
+ and ${nodePath.join(PathsConstants_1.default.getIOSFolder(), "<appName>", "Supporting", "Info.plist")}
33
+ in that order
34
+
35
+ Examples:
36
+ npx instrumentDynatrace
37
+ npx instrumentDynatrace config="/custom/path/to/dynatrace.config.js"
38
+ npx instrumentDynatrace gradle="/custom/path/to/build.gradle"
39
+ npx instrumentDynatrace plist="/custom/path/to/Info.plist"
40
+ `, Logger_1.default.INFO);
41
+ return;
42
+ }
43
+ Logger_1.default.logMessageSync('⏳ Starting instrumentation of React Native application ..', Logger_1.default.INFO);
44
+ Logger_1.default.withPrefix({ info: ' ℹ️ ', warning: ' ⚠️ ' }, () => (0, InstrumentUtil_1.showVersionOfPlugin)());
17
45
  let pathToConfig = PathsConstants_1.default.getConfigFilePath();
18
46
  let pathToGradle = PathsConstants_1.default.getAndroidGradleFile(PathsConstants_1.default.getAndroidFolder());
19
47
  const pathToAppGradle = PathsConstants_1.default.getAndroidAppGradleFile(PathsConstants_1.default.getAndroidFolder());
@@ -30,69 +58,69 @@ const instrumentCommand = () => {
30
58
  if (argv.isCustomConfigurationPathSet()) {
31
59
  pathToConfig = argv.getCustomConfigurationPath();
32
60
  }
33
- if (argv.isCustomGradlePathSet()) {
34
- pathToGradle = argv.getCustomGradlePath();
35
- androidAvailable = (0, InstrumentUtil_1.isPlatformAvailable)(pathToGradle, Platform_1.Platform.Android);
36
- }
37
- else {
38
- androidAvailable = (0, InstrumentUtil_1.isPlatformAvailable)(PathsConstants_1.default.getAndroidFolder(), Platform_1.Platform.Android);
39
- }
40
- if (argv.isCustomPlistPathSet()) {
41
- pathToPList = (0, path_1.resolve)(argv.getCustomPlistPath());
42
- iosAvailable = (0, InstrumentUtil_1.isPlatformAvailable)(pathToPList, Platform_1.Platform.IOS);
43
- }
44
- else {
45
- iosAvailable = (0, InstrumentUtil_1.isPlatformAvailable)(PathsConstants_1.default.getIOSFolder(), Platform_1.Platform.IOS);
46
- }
61
+ Logger_1.default.withPrefix({ info: ' ℹ️ ', warning: ' ⚠️ ', error: ' ❌ ' }, () => {
62
+ if (argv.isCustomGradlePathSet()) {
63
+ pathToGradle = argv.getCustomGradlePath();
64
+ androidAvailable = (0, InstrumentUtil_1.isPlatformAvailable)(pathToGradle, Platform_1.Platform.Android);
65
+ }
66
+ else {
67
+ androidAvailable = (0, InstrumentUtil_1.isPlatformAvailable)(PathsConstants_1.default.getAndroidFolder(), Platform_1.Platform.Android);
68
+ }
69
+ if (argv.isCustomPlistPathSet()) {
70
+ pathToPList = (0, path_1.resolve)(argv.getCustomPlistPath());
71
+ iosAvailable = (0, InstrumentUtil_1.isPlatformAvailable)(pathToPList, Platform_1.Platform.IOS);
72
+ }
73
+ else {
74
+ iosAvailable = (0, InstrumentUtil_1.isPlatformAvailable)(PathsConstants_1.default.getIOSFolder(), Platform_1.Platform.IOS);
75
+ }
76
+ });
47
77
  pathToConfig = (0, path_1.resolve)(pathToConfig);
48
78
  pathToGradle = (0, path_1.resolve)(pathToGradle);
49
79
  if (iosAvailable || androidAvailable) {
50
80
  try {
51
- Logger_1.default.logMessageSync('Trying to read configuration file: ' + pathToConfig, Logger_1.default.INFO);
81
+ Logger_1.default.logMessageSync('Trying to read configuration file: ' + pathToConfig, Logger_1.default.INFO);
52
82
  const configAgent = (0, Config_1.readConfig)(pathToConfig);
53
83
  if (androidAvailable) {
54
84
  try {
55
- Logger_1.default.logMessageSync('Starting Android Instrumentation with Dynatrace!', Logger_1.default.INFO);
56
- android.instrumentAndroidPlatform(pathToGradle, false);
57
- android.writeGradleConfig(configAgent.android);
58
- android.ensureRuntimeScriptApplied(pathToAppGradle);
85
+ Logger_1.default.logMessageSync('Starting Android Instrumentation with Dynatrace!', Logger_1.default.INFO);
86
+ Logger_1.default.withPrefix({ info: ' ℹ️ ', warning: ' ⚠️ ', error: ' ❌ ' }, () => {
87
+ android.instrumentAndroidPlatform(pathToGradle, false);
88
+ android.writeGradleConfig(configAgent.android);
89
+ android.ensureRuntimeScriptApplied(pathToAppGradle);
90
+ });
59
91
  android.copyGradleConfigFile(pathToGradle);
92
+ Logger_1.default.logMessageSync(' ✅ Finished Android Instrumentation with Dynatrace!', Logger_1.default.INFO);
60
93
  }
61
94
  catch (e) {
62
95
  if (e instanceof Error) {
63
- Logger_1.default.logMessageSync(e.message, Logger_1.default.ERROR);
96
+ Logger_1.default.logMessageSync(' ❌ Android Instrumentation failed: ' + e.message, Logger_1.default.ERROR);
64
97
  }
65
98
  }
66
- finally {
67
- Logger_1.default.logMessageSync('Finished Android Instrumentation with Dynatrace!', Logger_1.default.INFO);
68
- }
69
99
  }
70
100
  if (iosAvailable) {
71
101
  try {
72
- Logger_1.default.logMessageSync('Starting iOS Instrumentation with Dynatrace!', Logger_1.default.INFO);
73
- Ios_1.default.modifyPListFile(pathToPList, configAgent.ios, false);
102
+ Logger_1.default.logMessageSync('Starting iOS Instrumentation with Dynatrace!', Logger_1.default.INFO);
103
+ Logger_1.default.withPrefix({ info: ' ℹ️ ', warning: ' ⚠️ ', error: ' ❌ ' }, () => Ios_1.default.modifyPListFile(pathToPList, configAgent.ios, false));
104
+ Logger_1.default.logMessageSync(' ✅ Finished iOS Instrumentation with Dynatrace!', Logger_1.default.INFO);
74
105
  }
75
106
  catch (e) {
76
107
  if (e instanceof Error) {
77
- Logger_1.default.logMessageSync(e.message, Logger_1.default.ERROR);
108
+ Logger_1.default.logMessageSync(' ❌ iOS Instrumentation failed: ' + e.message, Logger_1.default.ERROR);
78
109
  }
79
110
  }
80
- finally {
81
- Logger_1.default.logMessageSync('Finished iOS Instrumentation with Dynatrace!', Logger_1.default.INFO);
82
- }
83
111
  }
84
112
  (0, SourceMapUtil_1.patchMetroSourceMap)();
113
+ Logger_1.default.logMessageSync('🎉 Finished instrumentation of React Native application ..', Logger_1.default.INFO);
85
114
  }
86
115
  catch (e) {
87
116
  if (e instanceof Error) {
88
- Logger_1.default.logMessageSync(e.message, Logger_1.default.ERROR);
117
+ Logger_1.default.logMessageSync('❌ Instrumentation failed: ' + e.message, Logger_1.default.ERROR);
89
118
  }
90
119
  }
91
120
  }
92
121
  else {
93
- Logger_1.default.logMessageSync('Both Android and iOS Folder are not available - Skip instrumentation.', Logger_1.default.WARNING);
122
+ Logger_1.default.logMessageSync('⚠️ Both Android and iOS Folder are not available - Skip instrumentation.', Logger_1.default.WARNING);
94
123
  }
95
- Logger_1.default.logMessageSync('Finished instrumentation of React Native application ..', Logger_1.default.INFO);
96
124
  Logger_1.default.closeLogFile();
97
125
  };
98
126
  exports.instrumentCommand = instrumentCommand;
@@ -8,11 +8,11 @@ const FileOperationHelper_1 = require("../FileOperationHelper");
8
8
  exports.SOURCE_MAP_BACKUP_FILE = 'getSourceMapInfoOrig.js';
9
9
  exports.SOURCE_MAP_FILE = 'getSourceMapInfo.js';
10
10
  const patchMetroSourceMap = () => {
11
- Logger_1.default.logMessageSync('Patching SourceMap generation of Metro .. ', Logger_1.default.INFO);
11
+ Logger_1.default.logMessageSync('Patching SourceMap generation of Metro .. ', Logger_1.default.INFO);
12
12
  const origSourceMapPath = (0, path_1.join)(PathsConstants_1.default.getMetroSouceMapPath(), exports.SOURCE_MAP_BACKUP_FILE);
13
13
  try {
14
14
  FileOperationHelper_1.default.checkIfFileExistsSync(origSourceMapPath);
15
- Logger_1.default.logMessageSync('Patching of SourceMap already happened!', Logger_1.default.INFO);
15
+ Logger_1.default.logMessageSync(' ℹ️ Patching of SourceMap already happened!', Logger_1.default.INFO);
16
16
  }
17
17
  catch (e) {
18
18
  try {
@@ -20,10 +20,10 @@ const patchMetroSourceMap = () => {
20
20
  FileOperationHelper_1.default.checkIfFileExistsSync(currentSourceMapPath);
21
21
  FileOperationHelper_1.default.renameFileSync(currentSourceMapPath, origSourceMapPath);
22
22
  FileOperationHelper_1.default.copyFileSync(PathsConstants_1.default.getOurSourceMapFile(), currentSourceMapPath);
23
- Logger_1.default.logMessageSync('Patching of SourceMap successful!', Logger_1.default.INFO);
23
+ Logger_1.default.logMessageSync('Patching of SourceMap successful!', Logger_1.default.INFO);
24
24
  }
25
25
  catch (e) {
26
- Logger_1.default.logMessageSync('Patching of SourceMap generation failed!', Logger_1.default.ERROR);
26
+ Logger_1.default.logMessageSync('Patching of SourceMap generation failed!', Logger_1.default.ERROR);
27
27
  }
28
28
  }
29
29
  };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Interface which is containing the additional properties available for instrumentation.
3
+ */
4
+ export interface IDynatraceProperties {
5
+ /**
6
+ * This string is changing the name of the action. So it is possible to override the action naming.
7
+ */
8
+ dtActionName?: string;
9
+
10
+ /**
11
+ * If true is passed the auto instrumentation will skip the action creation. We allow both string
12
+ * and boolean.
13
+ */
14
+ dtActionIgnore?: boolean | 'true' | 'false';
15
+ }
@@ -1,3 +1,6 @@
1
+ import 'react'
2
+ import { IDynatraceProperties } from '../src/instrumentation/jsx/IDynatraceProperties';
3
+
1
4
  /**
2
5
  * react-native-dynatrace.d.ts
3
6
  *
@@ -1717,4 +1720,10 @@ export declare class ConfigurationBuilder {
1717
1720
  * @see https://www.npmjs.com/package/@dynatrace/react-native-plugin#plugin-startup
1718
1721
  */
1719
1722
  public buildConfiguration(): IConfiguration;
1723
+ }
1724
+
1725
+ declare module 'react' {
1726
+ namespace JSX {
1727
+ interface IntrinsicAttributes extends IDynatraceProperties {}
1728
+ }
1720
1729
  }
@@ -1,151 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TouchableHelper = void 0;
4
- const ConfigurationHandler_1 = require("../../../lib/core/configuration/ConfigurationHandler");
5
- const IDynatraceProperties_1 = require("../IDynatraceProperties");
6
- const TypesUtil_1 = require("../../model/TypesUtil");
7
- const TouchableHelper = (Dynatrace, Logger) => ({
8
- attachOnPress(longPress, props, children, type) {
9
- const origFunction = longPress && this._isLongPress(props)
10
- ? props.onLongPress
11
- : props.onPress;
12
- const nameOfAction = this._findActionName(props, children);
13
- const wrappedFunction = (event) => {
14
- if (nameOfAction == null) {
15
- Logger.debug('Skipping creation of action as no name was found!');
16
- if (origFunction != null) {
17
- return origFunction(event);
18
- }
19
- }
20
- else if (origFunction != null &&
21
- origFunction._dtWrapped !== undefined &&
22
- origFunction._dtWrapped === true) {
23
- Logger.debug(`Skip wrapping of ${nameOfAction} onPress as it is already wrapped!`);
24
- return origFunction(event);
25
- }
26
- else if (!ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) {
27
- Logger.info('React Native plugin has not been started yet! Touch will not be reported!');
28
- if (origFunction != null) {
29
- return origFunction(event);
30
- }
31
- }
32
- else {
33
- let finalNameOfAction = nameOfAction;
34
- if (!(0, IDynatraceProperties_1.isDynatraceNaming)(props) &&
35
- ConfigurationHandler_1.ConfigurationHandler.isActionNamePrivacyEnabled()) {
36
- finalNameOfAction = (0, TypesUtil_1.getNameForType)(type);
37
- }
38
- const action = Dynatrace.enterAutoAction(`Touch on ${finalNameOfAction}`);
39
- if (origFunction != null) {
40
- let isSyncError = true;
41
- try {
42
- const returnValue = origFunction(event);
43
- if (_isPromise(returnValue)) {
44
- isSyncError = false;
45
- return Promise.resolve(returnValue).finally(() => {
46
- action.leaveAction();
47
- });
48
- }
49
- else {
50
- action.leaveAction();
51
- }
52
- isSyncError = false;
53
- }
54
- finally {
55
- if (isSyncError) {
56
- action.leaveAction();
57
- }
58
- }
59
- }
60
- else {
61
- action.leaveAction();
62
- }
63
- }
64
- };
65
- wrappedFunction._dtWrapped = true;
66
- return wrappedFunction;
67
- },
68
- _findActionName(props, children) {
69
- if ((0, IDynatraceProperties_1.isDynatraceNaming)(props)) {
70
- return props.dtActionName;
71
- }
72
- else if (this._isPropsButton(props) && props.title != null) {
73
- return props.title;
74
- }
75
- else if (props.accessibilityLabel != null) {
76
- return props.accessibilityLabel;
77
- }
78
- else if (children != null && children.length > 0) {
79
- if (children.length === 1 && typeof children[0] === 'string') {
80
- return children[0];
81
- }
82
- else {
83
- return this._walkChildrenToFindText(children);
84
- }
85
- }
86
- else if (props.children != null) {
87
- if (typeof props.children === 'string') {
88
- return props.children;
89
- }
90
- else {
91
- return this._walkChildrenToFindText(props.children);
92
- }
93
- }
94
- return null;
95
- },
96
- _isPropsButton: (props) => props.title != null,
97
- _isImageButton: (props) => props.source != null,
98
- _isLongPress: (props) => props.onLongPress != null,
99
- _isImageURISourceType: (source) => source.uri != null,
100
- _isIconButton: (element) => {
101
- const type = element.type;
102
- return type != null && type.name === 'Icon';
103
- },
104
- _walkTreeToFindText(element) {
105
- if (element == null || element.props == null) {
106
- return null;
107
- }
108
- else if (this._isImageButton(element.props)) {
109
- if (this._isImageURISourceType(element.props.source)) {
110
- return 'Image Button: ' + element.props.source.uri;
111
- }
112
- else {
113
- return 'Image Button';
114
- }
115
- }
116
- else if (this._isIconButton(element) && element.props.name != null) {
117
- return 'Icon Button: ' + element.props.name;
118
- }
119
- return this._walkChildrenToFindText(element.props.children);
120
- },
121
- _walkChildrenToFindText(children) {
122
- if (typeof children === 'string') {
123
- return children;
124
- }
125
- else if (Array.isArray(children)) {
126
- for (const child of children) {
127
- if (this._isReactElement(child)) {
128
- const name = this._walkTreeToFindText(child);
129
- if (name != null) {
130
- return name;
131
- }
132
- }
133
- else if (typeof child === 'string') {
134
- return child;
135
- }
136
- else if (Array.isArray(child)) {
137
- return this._walkChildrenToFindText(child);
138
- }
139
- }
140
- return null;
141
- }
142
- else {
143
- return this._walkTreeToFindText(children);
144
- }
145
- },
146
- _isReactElement: (node) => node != null && node.props != null,
147
- });
148
- exports.TouchableHelper = TouchableHelper;
149
- const _isPromise = (object) => object != null &&
150
- typeof object.then === 'function' &&
151
- typeof object.catch === 'function';