@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.
Files changed (78) hide show
  1. package/README.md +674 -668
  2. package/android/build.gradle +16 -3
  3. package/android/src/main/java/com/dynatrace/android/agent/DynatraceAppStartModule.kt +9 -31
  4. package/android/src/main/java/com/dynatrace/android/agent/DynatraceConfigurationModule.kt +1 -0
  5. package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +41 -0
  6. package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.kt +1 -0
  7. package/android/src/main/java/com/dynatrace/android/agent/ScreenshotSelfMonitor.kt +175 -0
  8. package/android/src/main/java/com/dynatrace/android/agent/UIChangeScreenshotListener.kt +124 -0
  9. package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +33 -0
  10. package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +40 -0
  11. package/files/plugin-runtime.gradle +17 -33
  12. package/files/plugin.gradle +1 -1
  13. package/instrumentation/BabelPluginDynatrace.js +1 -1
  14. package/instrumentation/libs/UserInteraction.js +21 -7
  15. package/instrumentation/libs/react-navigation/ReactNavigation.js +14 -58
  16. package/instrumentation/libs/withOnPressMonitoring.js +3 -54
  17. package/internal.d.ts +1 -0
  18. package/internal.js +3 -1
  19. package/ios/DTXScreenshotSelfMonitor.h +29 -0
  20. package/ios/DTXScreenshotSelfMonitor.mm +213 -0
  21. package/ios/DTXScreenshotSelfMonitorSwizzler.h +15 -0
  22. package/ios/DTXScreenshotSelfMonitorSwizzler.mm +68 -0
  23. package/ios/DynatraceRNBridge.h +6 -0
  24. package/ios/DynatraceRNBridge.mm +62 -0
  25. package/lib/core/Dynatrace.js +2 -0
  26. package/lib/core/configuration/ConfigurationHandler.js +0 -21
  27. package/lib/core/logging/LogMessages.js +42 -0
  28. package/lib/dynatrace-reporter.js +1 -30
  29. package/lib/dynatrace-transformer.js +6 -34
  30. package/lib/next/Dynatrace.js +26 -1
  31. package/lib/next/configuration/INativeRuntimeConfiguration.js +0 -1
  32. package/lib/next/configuration/RuntimeConfigurationObserver.js +1 -6
  33. package/lib/next/events/EventPipeline.js +48 -31
  34. package/lib/next/events/HttpRequestEventData.js +1 -1
  35. package/lib/next/events/spec/EventSpecContstants.js +1 -1
  36. package/lib/next/navigation/NavigationTracker.js +93 -0
  37. package/lib/next/navigation/useNavigationTracking.js +54 -0
  38. package/lib/next/userAction/NullUserAction.js +15 -0
  39. package/lib/next/userAction/UserActionConfiguration.js +10 -0
  40. package/lib/next/userAction/UserActionImpl.js +70 -0
  41. package/lib/next/util/TraceContextUtils.js +8 -14
  42. package/lib/next/util/Utils.js +13 -0
  43. package/package.json +10 -18
  44. package/public.js +5 -1
  45. package/react-native-dynatrace.podspec +10 -3
  46. package/scripts/Android.js +1 -20
  47. package/scripts/Config.js +17 -7
  48. package/scripts/Deprecations.js +18 -0
  49. package/scripts/Install.js +13 -0
  50. package/scripts/PathsConstants.js +0 -4
  51. package/scripts/Uninstall.js +0 -15
  52. package/scripts/core/InstrumentCall.js +14 -7
  53. package/scripts/util/DeprecationReport.js +24 -0
  54. package/src/lib/core/interface/NativeDynatraceBridge.ts +34 -1
  55. package/types.d.ts +236 -7
  56. package/instrumentation/DynatraceInstrumentation.js +0 -1
  57. package/instrumentation/libs/community/Picker.InstrInfo.js +0 -20
  58. package/instrumentation/libs/community/gesture-handler/Touchables.InstrInfo.js +0 -25
  59. package/instrumentation/libs/react-native/RefreshControl.InstrInfo.js +0 -12
  60. package/instrumentation/libs/react-native/Switch.InstrInfo.js +0 -12
  61. package/instrumentation/libs/react-native/Touchables.InstrInfo.js +0 -25
  62. package/instrumentation/parser/Babel.js +0 -60
  63. package/instrumentation/parser/ParserUtil.js +0 -11
  64. package/lib/features/ui-interaction/Config.js +0 -42
  65. package/lib/features/ui-interaction/IUserInteractionEvent.js +0 -16
  66. package/lib/features/ui-interaction/Plugin.Fragment.Test.js +0 -170
  67. package/lib/features/ui-interaction/Plugin.js +0 -289
  68. package/lib/features/ui-interaction/RootDetection.js +0 -51
  69. package/lib/features/ui-interaction/RootWrapper.js +0 -236
  70. package/lib/features/ui-interaction/Run.js +0 -38
  71. package/lib/features/ui-interaction/Runtime.js +0 -843
  72. package/lib/features/ui-interaction/TouchMetaResolver.js +0 -493
  73. package/lib/features/ui-interaction/Types.js +0 -14
  74. package/lib/metro/getSourceMapInfo.js +0 -26
  75. package/scripts/LineOffsetAnalyze.js +0 -25
  76. package/scripts/core/LineOffsetAnalyzeCall.js +0 -165
  77. package/scripts/util/SourceMapUtil.js +0 -68
  78. /package/{instrumentation/model/Reference.js → lib/next/userAction/UserAction.js} +0 -0
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useNavigationTracking = void 0;
4
+ const react_1 = require("react");
5
+ const react_native_1 = require("react-native");
6
+ const NavigationTracker_1 = require("./NavigationTracker");
7
+ const rootStateOf = (container) => container.getRootState();
8
+ const useNavigationTracking = (navigationRef) => {
9
+ const appStateRef = (0, react_1.useRef)(react_native_1.AppState.currentState);
10
+ const unsubscribeRef = (0, react_1.useRef)(null);
11
+ const containerRef = (0, react_1.useRef)(null);
12
+ (0, react_1.useEffect)(() => {
13
+ var _a;
14
+ const container = navigationRef.current;
15
+ if (container === containerRef.current) {
16
+ return;
17
+ }
18
+ (_a = unsubscribeRef.current) === null || _a === void 0 ? void 0 : _a.call(unsubscribeRef);
19
+ unsubscribeRef.current = null;
20
+ containerRef.current = container;
21
+ if (!container) {
22
+ return;
23
+ }
24
+ unsubscribeRef.current = container.addListener('state', () => {
25
+ (0, NavigationTracker_1.reportScreenChange)((0, NavigationTracker_1.buildPathFromState)(rootStateOf(container)));
26
+ });
27
+ (0, NavigationTracker_1.reportScreenChange)((0, NavigationTracker_1.buildPathFromState)(rootStateOf(container)));
28
+ });
29
+ (0, react_1.useEffect)(() => {
30
+ return () => {
31
+ var _a;
32
+ (_a = unsubscribeRef.current) === null || _a === void 0 ? void 0 : _a.call(unsubscribeRef);
33
+ unsubscribeRef.current = null;
34
+ containerRef.current = null;
35
+ };
36
+ }, []);
37
+ (0, react_1.useEffect)(() => {
38
+ const subscription = react_native_1.AppState.addEventListener('change', (nextAppState) => {
39
+ const prevAppState = appStateRef.current;
40
+ appStateRef.current = nextAppState;
41
+ if (nextAppState !== 'active' && prevAppState === 'active') {
42
+ (0, NavigationTracker_1.reportScreenBackground)();
43
+ }
44
+ else if (nextAppState === 'active' &&
45
+ prevAppState !== 'active') {
46
+ (0, NavigationTracker_1.reportScreenResume)();
47
+ }
48
+ });
49
+ return () => {
50
+ subscription.remove();
51
+ };
52
+ }, []);
53
+ };
54
+ exports.useNavigationTracking = useNavigationTracking;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NullUserAction = void 0;
4
+ class NullUserAction {
5
+ getCustomName() {
6
+ return '';
7
+ }
8
+ isCompleteAutomatically() {
9
+ return false;
10
+ }
11
+ setCompleteAutomatically(enabled) { }
12
+ complete() { }
13
+ addEventProperty(key, value) { }
14
+ }
15
+ exports.NullUserAction = NullUserAction;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserActionConfiguration = void 0;
4
+ class UserActionConfiguration {
5
+ constructor(customName, completeAutomatically = false) {
6
+ this.customName = customName;
7
+ this.completeAutomatically = completeAutomatically;
8
+ }
9
+ }
10
+ exports.UserActionConfiguration = UserActionConfiguration;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserActionImpl = void 0;
4
+ const DynatraceBridge_1 = require("../../core/DynatraceBridge");
5
+ const ConsoleLogger_1 = require("../../core/logging/ConsoleLogger");
6
+ const LogMessages_1 = require("../../core/logging/LogMessages");
7
+ const Utils_1 = require("../util/Utils");
8
+ const randomActionId = () => (0, Utils_1.randomHex)(16);
9
+ class UserActionImpl {
10
+ constructor(configuration) {
11
+ this.completed = false;
12
+ this.logger = new ConsoleLogger_1.ConsoleLogger('UserAction');
13
+ this.customName = configuration.customName;
14
+ this.completeAutomatically = configuration.completeAutomatically;
15
+ this.actionId = randomActionId();
16
+ DynatraceBridge_1.DynatraceNative.createUserAction(this.actionId, this.customName, this.completeAutomatically, null);
17
+ this.logger.debug(LogMessages_1.LogMessage.USER_ACTION_CREATED, {
18
+ customName: this.customName,
19
+ completeAutomatically: this.completeAutomatically,
20
+ actionId: this.actionId,
21
+ });
22
+ }
23
+ getCustomName() {
24
+ return this.customName;
25
+ }
26
+ isCompleteAutomatically() {
27
+ return this.completeAutomatically;
28
+ }
29
+ setCompleteAutomatically(enabled) {
30
+ if (this.completed) {
31
+ return;
32
+ }
33
+ this.logger.debug(LogMessages_1.LogMessage.USER_ACTION_SET_COMPLETE_AUTOMATICALLY, {
34
+ enabled,
35
+ customName: this.customName,
36
+ });
37
+ this.completeAutomatically = enabled;
38
+ DynatraceBridge_1.DynatraceNative.setCompleteUserActionAutomatically(this.actionId, enabled);
39
+ }
40
+ complete() {
41
+ if (this.completed) {
42
+ return;
43
+ }
44
+ this.completed = true;
45
+ this.logger.debug(LogMessages_1.LogMessage.USER_ACTION_COMPLETE, {
46
+ customName: this.customName,
47
+ });
48
+ DynatraceBridge_1.DynatraceNative.completeUserAction(this.actionId);
49
+ }
50
+ addEventProperty(key, value) {
51
+ if (this.completed) {
52
+ return;
53
+ }
54
+ this.logger.debug(LogMessages_1.LogMessage.USER_ACTION_ADD_EVENT_PROPERTY, {
55
+ key,
56
+ value: String(value),
57
+ customName: this.customName,
58
+ });
59
+ if (typeof value === 'string') {
60
+ DynatraceBridge_1.DynatraceNative.addEventStringPropertyToUserAction(this.actionId, key, value);
61
+ }
62
+ else if (typeof value === 'number') {
63
+ DynatraceBridge_1.DynatraceNative.addEventDoublePropertyToUserAction(this.actionId, key, value);
64
+ }
65
+ else {
66
+ DynatraceBridge_1.DynatraceNative.addEventBooleanPropertyToUserAction(this.actionId, key, value);
67
+ }
68
+ }
69
+ }
70
+ exports.UserActionImpl = UserActionImpl;
@@ -4,6 +4,7 @@ exports.trimTraceState = exports.generateTracestate = exports.generateTraceparen
4
4
  const ConsoleLogger_1 = require("../../core/logging/ConsoleLogger");
5
5
  const LogMessages_1 = require("../../core/logging/LogMessages");
6
6
  const ConfigurationHandler_1 = require("../../core/configuration/ConfigurationHandler");
7
+ const Utils_1 = require("./Utils");
7
8
  const logger = new ConsoleLogger_1.ConsoleLogger('TraceContextUtils');
8
9
  const parseTraceparent = (traceparent) => {
9
10
  const traceparentRegex = /^[0-9a-f]{2}-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/i;
@@ -26,27 +27,18 @@ const parseTraceparent = (traceparent) => {
26
27
  exports.parseTraceparent = parseTraceparent;
27
28
  const allZeros = (str) => /^0*$/.test(str);
28
29
  const generateTraceparentHeader = () => {
29
- let traceId = randomHex(32);
30
+ let traceId = (0, Utils_1.randomHex)(32);
30
31
  if (/^0+$/.test(traceId)) {
31
32
  traceId = '1' + traceId.slice(1);
32
33
  }
33
- let spanId = randomHex(16);
34
+ let spanId = (0, Utils_1.randomHex)(16);
34
35
  if (/^0+$/.test(spanId)) {
35
36
  spanId = '1' + spanId.slice(1);
36
37
  }
37
38
  return `00-${traceId}-${spanId}-01`;
38
39
  };
39
40
  exports.generateTraceparentHeader = generateTraceparentHeader;
40
- const randomHex = (length) => {
41
- let hex = '';
42
- while (hex.length < length) {
43
- hex += Math.floor(Math.random() * 0xffffffff)
44
- .toString(16)
45
- .padStart(8, '0');
46
- }
47
- return hex.slice(0, length);
48
- };
49
- const generateTracestate = (parentId, existingTracestate) => {
41
+ const generateTracestate = (parentId, traceparentFromDynatrace, existingTracestate) => {
50
42
  const instanceId = ConfigurationHandler_1.ConfigurationHandler.getInstanceId();
51
43
  const sessionId = ConfigurationHandler_1.ConfigurationHandler.getSessionId();
52
44
  const applicationId = ConfigurationHandler_1.ConfigurationHandler.getApplicationId();
@@ -55,10 +47,12 @@ const generateTracestate = (parentId, existingTracestate) => {
55
47
  !(instanceId && sessionId && applicationId && tracestateKeyPrefix)) {
56
48
  return undefined;
57
49
  }
58
- const version = 1;
59
50
  const originMarker = 'dtr';
51
+ const version = 2;
60
52
  const capture = 0;
61
- let tracestate = `${tracestateKeyPrefix}@${originMarker}=${version};${parentId};${capture};${formatApplicationId(applicationId)};${instanceId};${sessionId}`;
53
+ const formattedApplicationId = formatApplicationId(applicationId);
54
+ const tpSource = traceparentFromDynatrace ? 1 : 2;
55
+ let tracestate = `${tracestateKeyPrefix}@${originMarker}=${version};${parentId};${capture};${formattedApplicationId};${instanceId};${sessionId};${tpSource}`;
62
56
  if (typeof existingTracestate === 'string' && existingTracestate.trim()) {
63
57
  tracestate += `,${existingTracestate}`;
64
58
  }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.randomHex = void 0;
4
+ const randomHex = (length) => {
5
+ let hex = '';
6
+ while (hex.length < length) {
7
+ hex += Math.floor(Math.random() * 0xffffffff)
8
+ .toString(16)
9
+ .padStart(8, '0');
10
+ }
11
+ return hex.slice(0, length);
12
+ };
13
+ exports.randomHex = randomHex;
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@dynatrace/react-native-plugin",
3
- "version": "2.341.1",
3
+ "version": "2.345.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",
7
7
  "bin": {
8
8
  "instrumentDynatrace": "scripts/Instrument.js",
9
- "configDynatrace": "scripts/CheckConfig.js",
10
- "lineOffsetDynatrace": "scripts/LineOffsetAnalyze.js"
9
+ "configDynatrace": "scripts/CheckConfig.js"
11
10
  },
12
11
  "keywords": [
13
12
  "react-native",
@@ -22,6 +21,7 @@
22
21
  "plugin": "./command/command.js"
23
22
  },
24
23
  "scripts": {
24
+ "postinstall": "node ./scripts/Install.js",
25
25
  "uninstall": "node ./scripts/Uninstall.js",
26
26
  "test": "jest --runInBand",
27
27
  "test:coverage": "jest --runInBand --coverage",
@@ -50,7 +50,6 @@
50
50
  "license": "SEE LICENSE IN LICENSE.md",
51
51
  "dependencies": {
52
52
  "@babel/runtime": "^8.0.0",
53
- "jscodeshift": "^17.3.0",
54
53
  "plist": "^3.1.0",
55
54
  "proxy-polyfill": "^0.3.2",
56
55
  "semver": "^7.8.5"
@@ -58,18 +57,13 @@
58
57
  "homepage": "https://www.dynatrace.com/",
59
58
  "peerDependencies": {
60
59
  "@babel/core": ">=7.4.4",
61
- "diff": "^8.0.2",
62
60
  "react": ">=16.11.0",
63
61
  "react-native": ">=0.62.0"
64
62
  },
65
63
  "overrides": {
66
- "jscodeshift": {
67
- "ast-types": "npm:ast-types-x"
68
- },
69
- "ast-types": "npm:ast-types-x",
70
- "flow-parser": "0.160",
71
- "tmp": ">=0.2.6",
72
- "ws": "^7.5.11"
64
+ "ws": "^8.21.1",
65
+ "js-yaml": "^5.2.2",
66
+ "brace-expansion": "5.0.9"
73
67
  },
74
68
  "devDependencies": {
75
69
  "@babel/plugin-transform-class-properties": "^7.27.1",
@@ -77,6 +71,7 @@
77
71
  "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1",
78
72
  "@babel/plugin-transform-optional-chaining": "^7.27.1",
79
73
  "@babel/preset-env": "^7.27.2",
74
+ "@babel/preset-flow": "^7.27.1",
80
75
  "@babel/preset-react": "^7.27.1",
81
76
  "@react-native-picker/picker": "^2.11.4",
82
77
  "@react-native/babel-preset": "^0.80.1",
@@ -84,7 +79,6 @@
84
79
  "@react-navigation/drawer": "^7.7.2",
85
80
  "@testing-library/react-native": "^13.3.3",
86
81
  "@types/jest": "^30.0.0",
87
- "@types/jscodeshift": "^17.3.0",
88
82
  "@types/micromatch": "^4.0.10",
89
83
  "@types/node": "^18.19.123",
90
84
  "@types/plist": "^3.0.5",
@@ -95,7 +89,6 @@
95
89
  "@typescript-eslint/eslint-plugin": "^8.56.0",
96
90
  "@typescript-eslint/parser": "^8.56.0",
97
91
  "compressing": "^1.10.3",
98
- "diff": "^8.0.2",
99
92
  "eslint": "^9.29.0",
100
93
  "eslint-config-prettier": "^8.5.0",
101
94
  "eslint-plugin-import": "^2.32.0",
@@ -129,6 +122,7 @@
129
122
  "index.js",
130
123
  "public.js",
131
124
  "internal.js",
125
+ "internal.d.ts",
132
126
  "react-augmentation.js",
133
127
  "README.md",
134
128
  "LICENSE.md",
@@ -154,8 +148,6 @@
154
148
  "instrumentation/libs/react-native/*.js",
155
149
  "instrumentation/libs/react-native/Touchables.jsx",
156
150
  "instrumentation/model/*.js",
157
- "instrumentation/parser/*.js",
158
- "instrumentation/DynatraceInstrumentation.js",
159
151
  "instrumentation/BabelPluginDynatrace.js",
160
152
  "lib/*.js",
161
153
  "lib/core/*.js",
@@ -165,7 +157,6 @@
165
157
  "lib/core/model/*.js",
166
158
  "lib/core/util/*.js",
167
159
  "lib/core/*.js",
168
- "lib/metro/*.js",
169
160
  "lib/next/*.js",
170
161
  "lib/next/appstart/*.js",
171
162
  "lib/next/configuration/*.js",
@@ -175,7 +166,8 @@
175
166
  "lib/next/events/spec/*.js",
176
167
  "lib/next/util/*.js",
177
168
  "lib/next/provider/*.js",
178
- "lib/features/ui-interaction/*.js",
169
+ "lib/next/userAction/*.js",
170
+ "lib/next/navigation/*.js",
179
171
  "src/lib/core/interface/NativeDynatraceBridge.ts",
180
172
  "types.d.ts"
181
173
  ],
package/public.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ExceptionEventData = exports.SessionPropertyEventData = exports.EventData = exports.HttpRequestEventData = exports.DynatraceWebRequestTiming = exports.UserPrivacyOptions = exports.LogLevel = exports.Platform = exports.ConfigurationBuilder = exports.ManualStartupConfiguration = exports.DataCollectionLevel = exports.Dynatrace = void 0;
3
+ exports.useNavigationTracking = exports.UserActionConfiguration = exports.ExceptionEventData = exports.SessionPropertyEventData = exports.EventData = exports.HttpRequestEventData = exports.DynatraceWebRequestTiming = exports.UserPrivacyOptions = exports.LogLevel = exports.Platform = exports.ConfigurationBuilder = exports.ManualStartupConfiguration = exports.DataCollectionLevel = exports.Dynatrace = void 0;
4
4
  var Dynatrace_1 = require("./lib/core/Dynatrace");
5
5
  Object.defineProperty(exports, "Dynatrace", { enumerable: true, get: function () { return Dynatrace_1.Dynatrace; } });
6
6
  var DataCollectionLevel_1 = require("./lib/core/model/DataCollectionLevel");
@@ -25,4 +25,8 @@ var SessionPropertyEventData_1 = require("./lib/next/events/SessionPropertyEvent
25
25
  Object.defineProperty(exports, "SessionPropertyEventData", { enumerable: true, get: function () { return SessionPropertyEventData_1.default; } });
26
26
  var ExceptionEventData_1 = require("./lib/next/events/ExceptionEventData");
27
27
  Object.defineProperty(exports, "ExceptionEventData", { enumerable: true, get: function () { return ExceptionEventData_1.default; } });
28
+ var UserActionConfiguration_1 = require("./lib/next/userAction/UserActionConfiguration");
29
+ Object.defineProperty(exports, "UserActionConfiguration", { enumerable: true, get: function () { return UserActionConfiguration_1.UserActionConfiguration; } });
30
+ var useNavigationTracking_1 = require("./lib/next/navigation/useNavigationTracking");
31
+ Object.defineProperty(exports, "useNavigationTracking", { enumerable: true, get: function () { return useNavigationTracking_1.useNavigationTracking; } });
28
32
  require("./react-augmentation");
@@ -12,10 +12,17 @@ Pod::Spec.new do |s|
12
12
  s.version = package['version']
13
13
  s.summary = package['description']
14
14
  s.homepage = package['homepage']
15
- s.ios.deployment_target = "12.0"
16
- s.tvos.deployment_target = "12.0"
15
+ s.ios.deployment_target = "15.0"
16
+ s.tvos.deployment_target = "15.0"
17
17
  s.source_files = ["ios/*.{h,mm}"]
18
18
 
19
+ # Build-time off-switch for screenshot self-monitoring (replay metrics), passed at `pod install`:
20
+ # DYNATRACE_REPLAY_METRICS_ENABLED=0 pod install
21
+ # Defaults to enabled; when set to 0 the monitor is compiled out (DynatraceRNBridge.mm #if guard).
22
+ if ENV['DYNATRACE_REPLAY_METRICS_ENABLED'] == '0'
23
+ s.prefix_header_contents = '#define DTX_REPLAY_METRICS_ENABLED 0'
24
+ end
25
+
19
26
  s.license = { :type => 'Commercial', :text => 'https://github.com/Dynatrace/dem-license/blob/main/LICENSE.md'}
20
27
 
21
28
  # --- License ----------------------------------------------------------- #
@@ -111,7 +118,7 @@ Pod::Spec.new do |s|
111
118
  #
112
119
 
113
120
  s.dependency "React"
114
- s.dependency 'Dynatrace', '~> 8.341.1.1010'
121
+ s.dependency 'Dynatrace', '~> 8.345.1.1003'
115
122
 
116
123
  # Allows for better compatibility for older and newer versions
117
124
  if defined?(install_modules_dependencies)
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.ensureRuntimeScriptApplied = exports.writeGradleConfig = exports.instrumentAndroidPlatform = exports.GRADLE_APPLY_RUNTIME_SCRIPT_KTS = exports.GRADLE_APPLY_RUNTIME_SCRIPT = exports.GRADLE_APPLY_BUILDSCRIPT_KTS = exports.GRADLE_APPLY_BUILDSCRIPT = exports.GRADLE_DYNATRACE_FILE_KTS = exports.GRADLE_DYNATRACE_FILE = void 0;
4
+ exports.writeGradleConfig = exports.instrumentAndroidPlatform = exports.GRADLE_APPLY_BUILDSCRIPT_KTS = exports.GRADLE_APPLY_BUILDSCRIPT = exports.GRADLE_DYNATRACE_FILE_KTS = exports.GRADLE_DYNATRACE_FILE = void 0;
5
5
  const path_1 = require("path");
6
6
  const Logger_1 = require("./Logger");
7
7
  const FileOperationHelper_1 = require("./FileOperationHelper");
@@ -14,19 +14,15 @@ const GRADLE_BUILDSCRIPT_IDENTIFIER = 'buildscript';
14
14
  exports.GRADLE_APPLY_BUILDSCRIPT = 'apply from: "../node_modules/@dynatrace/react-native-plugin/files/plugin.gradle", to: buildscript';
15
15
  exports.GRADLE_APPLY_BUILDSCRIPT_KTS = 'apply(from = "../node_modules/@dynatrace/react-native-plugin/files/plugin.gradle", to = buildscript)';
16
16
  const GRADLE_REACT_NATIVE_PLUGIN = 'apply plugin: "com.facebook.react.rootproject"';
17
- exports.GRADLE_APPLY_RUNTIME_SCRIPT = 'apply from: "../../node_modules/@dynatrace/react-native-plugin/files/plugin-runtime.gradle"';
18
- exports.GRADLE_APPLY_RUNTIME_SCRIPT_KTS = 'apply(from = "../../node_modules/@dynatrace/react-native-plugin/files/plugin-runtime.gradle")';
19
17
  const isKotlinDslGradleFile = (pathToGradle) => pathToGradle.endsWith('.gradle.kts');
20
18
  const getGradleStatements = (pathToGradle) => isKotlinDslGradleFile(pathToGradle)
21
19
  ? {
22
20
  applyBuildscript: exports.GRADLE_APPLY_BUILDSCRIPT_KTS,
23
21
  dynatraceFile: exports.GRADLE_DYNATRACE_FILE_KTS,
24
- runtimeScript: exports.GRADLE_APPLY_RUNTIME_SCRIPT_KTS,
25
22
  }
26
23
  : {
27
24
  applyBuildscript: exports.GRADLE_APPLY_BUILDSCRIPT,
28
25
  dynatraceFile: exports.GRADLE_DYNATRACE_FILE,
29
- runtimeScript: exports.GRADLE_APPLY_RUNTIME_SCRIPT,
30
26
  };
31
27
  const instrumentAndroidPlatform = (pathToGradle, remove) => {
32
28
  const path = FileOperationHelper_1.default.checkIfFileExistsSync(pathToGradle);
@@ -165,18 +161,3 @@ const removeOldGradleConfig = (gradleFileContent) => {
165
161
  gradleFileContentLines.splice(gradleConfigIndex[0] + 1, gradleConfigIndex[1] - (gradleConfigIndex[0] + 1));
166
162
  return gradleFileContentLines;
167
163
  };
168
- const ensureRuntimeScriptApplied = (pathToGradle) => {
169
- const gradleContent = FileOperationHelper_1.default.readTextFromFileSync(pathToGradle);
170
- const gradleLines = gradleContent.split('\n');
171
- const { runtimeScript } = getGradleStatements(pathToGradle);
172
- const alreadyApplied = gradleLines.some((line) => line.includes('plugin-runtime.gradle'));
173
- if (!alreadyApplied) {
174
- gradleLines.push(runtimeScript);
175
- FileOperationHelper_1.default.writeTextToFileSync(pathToGradle, gradleLines.join('\n'));
176
- Logger_1.default.logMessageSync(`Added runtime script to ${pathToGradle}`, Logger_1.default.INFO);
177
- }
178
- else {
179
- Logger_1.default.logMessageSync(`Runtime script already present in ${pathToGradle}`, Logger_1.default.INFO);
180
- }
181
- };
182
- exports.ensureRuntimeScriptApplied = ensureRuntimeScriptApplied;
package/scripts/Config.js CHANGED
@@ -12,6 +12,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.checkConfiguration = exports.addDefaultConfigs = exports.readConfig = exports.readConfigDefault = exports.defaultConfig = exports.ERROR_CONFIG_NOT_AVAILABLE = void 0;
14
14
  const path = require("node:path");
15
+ const node_fs_1 = require("node:fs");
15
16
  const FileOperationHelper_1 = require("./FileOperationHelper");
16
17
  const Logger_1 = require("./Logger");
17
18
  const PathsConstants_1 = require("./PathsConstants");
@@ -37,17 +38,23 @@ exports.defaultConfig = {
37
38
  enabled: true,
38
39
  },
39
40
  userInteraction: true,
40
- sourcemap: {
41
- enabled: true,
42
- androidSourcemapLocation: 'app/build/generated/sourcemaps/react/release/index.android.bundle.map',
43
- },
44
41
  },
45
42
  };
46
43
  const readConfigDefault = () => {
47
44
  const customArguments = (0, CustomArgumentUtil_1.readCustomArguments)();
48
- const configPath = customArguments.isCustomConfigurationPathSet()
49
- ? path.resolve(PathsConstants_1.default.getApplicationPath(), customArguments.getCustomConfigurationPath())
50
- : PathsConstants_1.default.getConfigFilePath();
45
+ let configPath;
46
+ if (customArguments.isCustomConfigurationPathSet()) {
47
+ configPath = path.resolve(PathsConstants_1.default.getApplicationPath(), customArguments.getCustomConfigurationPath());
48
+ }
49
+ else {
50
+ const envConfig = process.env.DYNATRACE_CONFIG;
51
+ if (envConfig === undefined || envConfig.trim() === '') {
52
+ configPath = PathsConstants_1.default.getConfigFilePath();
53
+ }
54
+ else {
55
+ configPath = path.resolve(PathsConstants_1.default.getApplicationPath(), envConfig.trim());
56
+ }
57
+ }
51
58
  return (0, exports.readConfig)(configPath);
52
59
  };
53
60
  exports.readConfigDefault = readConfigDefault;
@@ -87,6 +94,9 @@ const logConfigCreatedMessage = () => {
87
94
  Logger_1.default.logMessageSync(message, Logger_1.default.INFO);
88
95
  };
89
96
  const patchMalformedConfiguration = (pathToDynatraceConfig) => {
97
+ if (!(0, node_fs_1.existsSync)(pathToDynatraceConfig)) {
98
+ return;
99
+ }
90
100
  const configContent = FileOperationHelper_1.default.readTextFromFileSync(pathToDynatraceConfig);
91
101
  if (configContent.indexOf('\u200B') !== -1) {
92
102
  FileOperationHelper_1.default.writeTextToFileSync(pathToDynatraceConfig, configContent.split('\u200B').join(''));
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEPRECATIONS = exports.readInstalledPackageVersion = void 0;
4
+ const node_path_1 = require("node:path");
5
+ const FileOperationHelper_1 = require("./FileOperationHelper");
6
+ const PathsConstants_1 = require("./PathsConstants");
7
+ const readInstalledPackageVersion = (packageName) => {
8
+ var _a;
9
+ try {
10
+ const raw = FileOperationHelper_1.default.readTextFromFileSync((0, node_path_1.join)(PathsConstants_1.default.getApplicationPath(), 'node_modules', packageName, 'package.json'));
11
+ return (_a = JSON.parse(raw).version) !== null && _a !== void 0 ? _a : null;
12
+ }
13
+ catch (_b) {
14
+ return null;
15
+ }
16
+ };
17
+ exports.readInstalledPackageVersion = readInstalledPackageVersion;
18
+ exports.DEPRECATIONS = [];
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const DeprecationReport_1 = require("./util/DeprecationReport");
5
+ const Logger_1 = require("./Logger");
6
+ module.exports = (() => {
7
+ try {
8
+ (0, DeprecationReport_1.showDeprecationWarnings)();
9
+ Logger_1.default.closeLogFile();
10
+ }
11
+ catch (_a) {
12
+ }
13
+ })();
@@ -30,10 +30,6 @@ exports.default = {
30
30
  getPackageJsonFile() {
31
31
  return (0, node_path_1.join)(this.getApplicationPath(), 'package.json');
32
32
  },
33
- getMetroSouceMapPath() {
34
- return (0, node_path_1.join)(this.getApplicationPath(), 'node_modules', 'metro', 'src', 'DeltaBundler', 'Serializers', 'helpers');
35
- },
36
- getOurSourceMapFile: () => (0, node_path_1.join)(getPluginPath(), 'lib', 'metro', 'getSourceMapInfo.js'),
37
33
  getInternalPackageJsonFile: () => (0, node_path_1.join)(getPluginPath(), 'package.json'),
38
34
  getDefaultConfig: () => (0, node_path_1.join)(getPluginPath(), PATH_FILES, 'default.config.js'),
39
35
  getBuildPath: () => (0, node_path_1.join)(getPluginPath(), 'build'),
@@ -16,20 +16,6 @@ const FileOperationHelper_1 = require("./FileOperationHelper");
16
16
  const PathsConstants_1 = require("./PathsConstants");
17
17
  const android = require("./Android");
18
18
  const Ios_1 = require("./Ios");
19
- const removePatchMetroSourceMap = () => __awaiter(void 0, void 0, void 0, function* () {
20
- Logger_1.default.logMessageSync('Undo Patching SourceMap generation of Metro .. ', Logger_1.default.INFO);
21
- try {
22
- const currentSourceMapPath = nodePath.join(PathsConstants_1.default.getMetroSouceMapPath(), 'getSourceMapInfo.js');
23
- const origSourceMapPath = nodePath.join(PathsConstants_1.default.getMetroSouceMapPath(), 'getSourceMapInfoOrig.js');
24
- yield FileOperationHelper_1.default.checkIfFileExists(origSourceMapPath);
25
- yield FileOperationHelper_1.default.deleteFile(currentSourceMapPath);
26
- yield FileOperationHelper_1.default.renameFile(origSourceMapPath, currentSourceMapPath);
27
- Logger_1.default.logMessageSync('Removed patch for SourceMap generation of Metro!', Logger_1.default.INFO);
28
- }
29
- catch (e) {
30
- Logger_1.default.logMessageSync('Removing of patch for SourceMap generation failed!', Logger_1.default.ERROR);
31
- }
32
- });
33
19
  const removeGradleModification = () => __awaiter(void 0, void 0, void 0, function* () {
34
20
  try {
35
21
  const path = yield FileOperationHelper_1.default.checkIfFileExists(nodePath.join(PathsConstants_1.default.getAndroidFolder(), 'build.gradle'));
@@ -48,7 +34,6 @@ const removePListModification = () => __awaiter(void 0, void 0, void 0, function
48
34
  }
49
35
  });
50
36
  module.exports = (() => __awaiter(void 0, void 0, void 0, function* () {
51
- yield removePatchMetroSourceMap();
52
37
  yield removeGradleModification();
53
38
  yield removePListModification();
54
39
  }))();
@@ -8,9 +8,9 @@ const android = require("../Android");
8
8
  const PathsConstants_1 = require("../PathsConstants");
9
9
  const Ios_1 = require("../Ios");
10
10
  const InstrumentUtil_1 = require("../util/InstrumentUtil");
11
+ const DeprecationReport_1 = require("../util/DeprecationReport");
11
12
  const CustomArgumentUtil_1 = require("../util/CustomArgumentUtil");
12
13
  const Platform_1 = require("../api/model/Platform");
13
- const SourceMapUtil_1 = require("../util/SourceMapUtil");
14
14
  const platformLogPrefix = { info: ' ℹ️ ', warning: ' ⚠️ ', error: ' ❌ ' };
15
15
  const logHelpMessage = () => {
16
16
  const iOSDefaultPath = (0, node_path_1.join)(PathsConstants_1.default.getIOSFolder(), '<appName>', 'Info.plist');
@@ -20,6 +20,10 @@ const logHelpMessage = () => {
20
20
 
21
21
  Options:
22
22
  --help Show this help message and exit.
23
+ --reset Clear any previously-persisted custom config path and
24
+ revert the Metro/Babel transformer to the default
25
+ dynatrace.config.js lookup. Use this if you previously
26
+ ran with config="..." and want to go back to the default.
23
27
  config="/custom/path/to/dynatrace.config.js"
24
28
  Specify a custom path to the Dynatrace configuration file.
25
29
  Default: ${PathsConstants_1.default.getConfigFilePath()}
@@ -38,14 +42,13 @@ const logHelpMessage = () => {
38
42
  npx instrumentDynatrace config="/custom/path/to/dynatrace.config.js"
39
43
  npx instrumentDynatrace gradle="/custom/path/to/build.gradle"
40
44
  npx instrumentDynatrace plist="/custom/path/to/Info.plist"
45
+ npx instrumentDynatrace --reset
41
46
  `, Logger_1.default.INFO);
42
47
  };
43
48
  const persistCustomArguments = (argv) => {
44
- if (argv.isEmpty()) {
45
- (0, CustomArgumentUtil_1.clearCustomArguments)();
46
- return;
49
+ if (!argv.isEmpty()) {
50
+ (0, CustomArgumentUtil_1.writeCustomArguments)(argv);
47
51
  }
48
- (0, CustomArgumentUtil_1.writeCustomArguments)(argv);
49
52
  };
50
53
  const resolveInstrumentationPaths = (argv) => {
51
54
  let pathToConfig = PathsConstants_1.default.getConfigFilePath();
@@ -90,7 +93,6 @@ const instrumentAndroidIfAvailable = (androidAvailable, pathToGradle, pathToAppG
90
93
  Logger_1.default.withPrefix(platformLogPrefix, () => {
91
94
  android.instrumentAndroidPlatform(pathToGradle, false);
92
95
  android.writeGradleConfig(androidConfig, pathToGradle);
93
- android.ensureRuntimeScriptApplied(pathToAppGradle);
94
96
  });
95
97
  Logger_1.default.logMessageSync(' ✅ Finished Android Instrumentation with Dynatrace!', Logger_1.default.INFO);
96
98
  }
@@ -125,7 +127,6 @@ const runPlatformInstrumentation = (paths, availability) => {
125
127
  const configAgent = (0, Config_1.readConfig)(paths.pathToConfig);
126
128
  instrumentAndroidIfAvailable(availability.androidAvailable, paths.pathToGradle, paths.pathToAppGradle, configAgent.android);
127
129
  instrumentIosIfAvailable(availability.iosAvailable, paths.pathToPList, configAgent.ios);
128
- (0, SourceMapUtil_1.patchMetroSourceMap)();
129
130
  Logger_1.default.logMessageSync('🎉 Finished instrumentation of React Native application ..', Logger_1.default.INFO);
130
131
  }
131
132
  catch (e) {
@@ -140,8 +141,14 @@ const instrumentCommand = () => {
140
141
  logHelpMessage();
141
142
  return;
142
143
  }
144
+ if (commandArgs.includes('--reset')) {
145
+ (0, CustomArgumentUtil_1.clearCustomArguments)();
146
+ Logger_1.default.logMessageSync('✅ Custom config path cleared. Metro/Babel transformer will use dynatrace.config.js.', Logger_1.default.INFO);
147
+ return;
148
+ }
143
149
  Logger_1.default.logMessageSync('⏳ Starting instrumentation of React Native application ..', Logger_1.default.INFO);
144
150
  Logger_1.default.withPrefix({ info: ' ℹ️ ', warning: ' ⚠️ ' }, () => (0, InstrumentUtil_1.showVersionOfPlugin)());
151
+ (0, DeprecationReport_1.showDeprecationWarnings)();
145
152
  const argv = (0, CustomArgumentUtil_1.parseCommandLine)(commandArgs.slice(2));
146
153
  persistCustomArguments(argv);
147
154
  const instrumentationPaths = resolveInstrumentationPaths(argv);
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.showDeprecationWarnings = void 0;
4
+ const Logger_1 = require("../Logger");
5
+ const Deprecations_1 = require("../Deprecations");
6
+ const formatEntry = (entry) => `⚠️ Deprecation [${entry.id}]: ${entry.description}\n` +
7
+ ` Deprecated since: plugin v${entry.deprecatedSince}\n` +
8
+ ` Removal planned: plugin v${entry.removalVersion}\n` +
9
+ ` Migration: ${entry.migration}`;
10
+ const showDeprecationWarnings = () => {
11
+ for (const entry of Deprecations_1.DEPRECATIONS) {
12
+ let applicable;
13
+ try {
14
+ applicable = entry.isApplicable();
15
+ }
16
+ catch (_a) {
17
+ applicable = false;
18
+ }
19
+ if (applicable) {
20
+ Logger_1.default.logMessageSync(formatEntry(entry), Logger_1.default.WARNING);
21
+ }
22
+ }
23
+ };
24
+ exports.showDeprecationWarnings = showDeprecationWarnings;