@dynatrace/react-native-plugin 2.343.1 → 2.347.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 (60) hide show
  1. package/README.md +674 -656
  2. package/android/build.gradle +6 -2
  3. package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +24 -0
  4. package/files/plugin-runtime.gradle +17 -33
  5. package/files/plugin.gradle +1 -1
  6. package/instrumentation/BabelPluginDynatrace.js +1 -1
  7. package/instrumentation/libs/UserInteraction.js +20 -6
  8. package/instrumentation/libs/react-native/Lists.js +94 -0
  9. package/instrumentation/libs/react-native/index.js +4 -1
  10. package/instrumentation/libs/react-native.js +3 -0
  11. package/instrumentation/libs/react-navigation/ReactNavigation.js +14 -58
  12. package/instrumentation/libs/withOnPressMonitoring.js +3 -54
  13. package/internal.d.ts +2 -0
  14. package/internal.js +5 -1
  15. package/ios/DynatraceRNBridge.mm +37 -1
  16. package/lib/core/configuration/ConfigurationHandler.js +0 -21
  17. package/lib/core/logging/LogMessages.js +50 -0
  18. package/lib/dynatrace-reporter.js +1 -30
  19. package/lib/dynatrace-transformer.js +6 -34
  20. package/lib/next/configuration/INativeRuntimeConfiguration.js +0 -1
  21. package/lib/next/configuration/RuntimeConfigurationObserver.js +1 -6
  22. package/lib/next/events/spec/EventSpecContstants.js +1 -1
  23. package/lib/next/navigation/NavigationTracker.js +101 -0
  24. package/lib/next/navigation/useNavigationTracking.js +54 -0
  25. package/lib/next/triggers/TableReloadTracker.js +23 -0
  26. package/package.json +11 -21
  27. package/public.js +3 -1
  28. package/react-native-dynatrace.podspec +1 -1
  29. package/scripts/Android.js +1 -20
  30. package/scripts/Config.js +0 -4
  31. package/scripts/Deprecations.js +18 -0
  32. package/scripts/Install.js +13 -0
  33. package/scripts/PathsConstants.js +0 -4
  34. package/scripts/Uninstall.js +0 -15
  35. package/scripts/core/InstrumentCall.js +2 -3
  36. package/scripts/util/DeprecationReport.js +24 -0
  37. package/types.d.ts +212 -10
  38. package/instrumentation/DynatraceInstrumentation.js +0 -1
  39. package/instrumentation/libs/community/Picker.InstrInfo.js +0 -20
  40. package/instrumentation/libs/community/gesture-handler/Touchables.InstrInfo.js +0 -25
  41. package/instrumentation/libs/react-native/RefreshControl.InstrInfo.js +0 -12
  42. package/instrumentation/libs/react-native/Switch.InstrInfo.js +0 -12
  43. package/instrumentation/libs/react-native/Touchables.InstrInfo.js +0 -25
  44. package/instrumentation/model/Reference.js +0 -2
  45. package/instrumentation/parser/Babel.js +0 -60
  46. package/instrumentation/parser/ParserUtil.js +0 -11
  47. package/lib/features/ui-interaction/Config.js +0 -42
  48. package/lib/features/ui-interaction/IUserInteractionEvent.js +0 -16
  49. package/lib/features/ui-interaction/Plugin.Fragment.Test.js +0 -170
  50. package/lib/features/ui-interaction/Plugin.js +0 -289
  51. package/lib/features/ui-interaction/RootDetection.js +0 -51
  52. package/lib/features/ui-interaction/RootWrapper.js +0 -236
  53. package/lib/features/ui-interaction/Run.js +0 -38
  54. package/lib/features/ui-interaction/Runtime.js +0 -843
  55. package/lib/features/ui-interaction/TouchMetaResolver.js +0 -493
  56. package/lib/features/ui-interaction/Types.js +0 -14
  57. package/lib/metro/getSourceMapInfo.js +0 -26
  58. package/scripts/LineOffsetAnalyze.js +0 -25
  59. package/scripts/core/LineOffsetAnalyzeCall.js +0 -165
  60. package/scripts/util/SourceMapUtil.js +0 -68
@@ -11,6 +11,7 @@
11
11
  #endif
12
12
 
13
13
  #import <Foundation/Foundation.h>
14
+ #import <QuartzCore/QuartzCore.h>
14
15
  #import <CoreLocation/CoreLocation.h>
15
16
  #import <React/RCTPerformanceLogger.h>
16
17
  #import <React/RCTRootView.h>
@@ -178,7 +179,7 @@ int64_t getRunJSBundleEndTime() {
178
179
  }
179
180
 
180
181
  - (NSArray<NSString *> *)supportedEvents {
181
- return @[EmitAppMeasurementsIdentifier, EmitDynatraceConfiguration];
182
+ return @[EmitAppMeasurementsIdentifier, EmitDynatraceConfiguration, @"DTNavigationFrame"];
182
183
  }
183
184
 
184
185
  int64_t GetTimestampUnix()
@@ -225,11 +226,13 @@ template<typename T = void> std::enable_if_t<(facebook::react::ReactNativeVersio
225
226
  /**
226
227
  * When bridge is starting we will add an observer for content did appear so we can emit our app start measurements
227
228
  */
229
+ #if !RCT_NEW_ARCH_ENABLED
228
230
  - (void)setBridge:(RCTBridge *)bridge
229
231
  {
230
232
  [super setBridge:bridge];
231
233
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentAppeared) name:RCTContentDidAppearNotification object:nil];
232
234
  }
235
+ #endif
233
236
 
234
237
  - (BOOL)isReady
235
238
  {
@@ -289,6 +292,13 @@ template<typename T = void> std::enable_if_t<(facebook::react::ReactNativeVersio
289
292
  - (void)startObserving
290
293
  {
291
294
  hasListeners = YES;
295
+ #if RCT_NEW_ARCH_ENABLED
296
+ // On new arch setBridge: is not called, so RCTContentDidAppearNotification is never observed.
297
+ // JS adding a listener is the earliest signal we have that content is visible.
298
+ if (contentAppeared == -1) {
299
+ contentAppeared = GetTimestampUnix();
300
+ }
301
+ #endif
292
302
  [self emitMeasurements];
293
303
 
294
304
  [self setupRuntimeConfigurationListenerIfNeeded];
@@ -825,9 +835,35 @@ RCT_EXPORT_METHOD(getCurrentConfiguration:(RCTPromiseResolveBlock)resolve reject
825
835
  }
826
836
  }
827
837
 
838
+ static _Atomic int32_t _navGeneration = 0;
839
+
840
+ // NOTE: This callback is observational only — it measures the first rendered frame for
841
+ // diagnostic tooling (LOAD TIME display). It does not defer stopView(); deferring the
842
+ // view-end to the rendered frame to fix TTID under-reporting (DEM-32277) is a separate task.
828
843
  RCT_EXPORT_METHOD(startViewInternal:(NSDictionary<NSString*, id>*) fields)
829
844
  {
845
+ int32_t gen = ++_navGeneration;
846
+ CFTimeInterval imCATime = CACurrentMediaTime();
847
+
830
848
  [HybridBridge startView:fields];
849
+
850
+ dispatch_async(dispatch_get_main_queue(), ^{
851
+ __block CADisplayLink *link = [CADisplayLink displayLinkWithTarget:[NSBlockOperation blockOperationWithBlock:^{
852
+ [link invalidate];
853
+ link = nil;
854
+ if (_navGeneration != gen) return; // superseded by a newer navigation
855
+ CFTimeInterval frameCATime = CACurrentMediaTime();
856
+ uint64_t frameEpochMs = (uint64_t)([[NSDate date] timeIntervalSince1970] * 1000.0);
857
+ double deltaMs = (frameCATime - imCATime) * 1000.0;
858
+ if (hasListeners) {
859
+ [self sendEventWithName:@"DTNavigationFrame" body:@{
860
+ @"frameEndMs": @(frameEpochMs),
861
+ @"deltaMs": @(deltaMs)
862
+ }];
863
+ }
864
+ }] selector:@selector(main)];
865
+ [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
866
+ });
831
867
  }
832
868
 
833
869
  RCT_EXPORT_METHOD(stopViewInternal)
@@ -4,7 +4,6 @@ exports.ConfigurationHandler = void 0;
4
4
  const RuntimeConfigurationObserver_1 = require("../../next/configuration/RuntimeConfigurationObserver");
5
5
  const LogLevel_1 = require("../logging/LogLevel");
6
6
  let _configuration;
7
- let _uiiEnabledLastKnownGood = undefined;
8
7
  const getRuntimeConfiguration = () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.getCurrentRuntimeConfiguration();
9
8
  const getBaseThirdGenDecision = () => {
10
9
  if (!RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.isInitiated()) {
@@ -46,9 +45,6 @@ exports.ConfigurationHandler = {
46
45
  setConfiguration(configuration) {
47
46
  _configuration = configuration;
48
47
  },
49
- setUserInteractionEnabledLastKnownGood(value) {
50
- _uiiEnabledLastKnownGood = value;
51
- },
52
48
  isConfigurationAvailable: () => _configuration !== undefined,
53
49
  isErrorHandlerEnabled: () => _configuration.errorHandler,
54
50
  isReportFatalErrorAsCrash: () => _configuration.reportFatalErrorAsCrash,
@@ -84,23 +80,6 @@ exports.ConfigurationHandler = {
84
80
  getApplicationId: () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.getCurrentRuntimeConfiguration()['application_id'],
85
81
  getTracestateKeyPrefix: () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.getCurrentRuntimeConfiguration()['tracestate_key_prefix'],
86
82
  getTraceContextEnabled: () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.getCurrentRuntimeConfiguration()['trace_context_enabled'],
87
- isUserInteractionEnabled: () => {
88
- const isRuntimeConfigInitiated = RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.isInitiated();
89
- if (isRuntimeConfigInitiated) {
90
- const realTimeconfiguration = RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.getCurrentRuntimeConfiguration();
91
- const remoteUIConfiguration = realTimeconfiguration
92
- ? realTimeconfiguration.touch_interaction_enabled
93
- : undefined;
94
- if (typeof remoteUIConfiguration === 'boolean') {
95
- _uiiEnabledLastKnownGood = remoteUIConfiguration;
96
- return remoteUIConfiguration;
97
- }
98
- }
99
- if (typeof _uiiEnabledLastKnownGood === 'boolean') {
100
- return _uiiEnabledLastKnownGood;
101
- }
102
- return false;
103
- },
104
83
  isRuntimeConfigurationInitiated: () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.isInitiated(),
105
84
  getBundleName: () => _configuration.bundleName,
106
85
  getBundleVersion: () => _configuration.bundleVersion,
@@ -77,6 +77,7 @@ var LogMessage;
77
77
  LogMessage["KEY_SYNTAX_INVALID"] = "KEY_SYNTAX_INVALID";
78
78
  LogMessage["MODIFY_EVENT"] = "MODIFY_EVENT";
79
79
  LogMessage["MODIFY_EVENT_NULL"] = "MODIFY_EVENT_NULL";
80
+ LogMessage["NAVIGATION_FRAME_TIMING"] = "NAVIGATION_FRAME_TIMING";
80
81
  LogMessage["NAVIGATION_NOT_STARTED"] = "NAVIGATION_NOT_STARTED";
81
82
  LogMessage["PLUGIN_STARTED"] = "PLUGIN_STARTED";
82
83
  LogMessage["PROPERTY_LIMIT_EXCEEDED"] = "PROPERTY_LIMIT_EXCEEDED";
@@ -150,6 +151,15 @@ var LogMessage;
150
151
  LogMessage["WEB_REQUEST_TIMING_START_FAILED"] = "WEB_REQUEST_TIMING_START_FAILED";
151
152
  LogMessage["WEB_REQUEST_TIMING_STOP"] = "WEB_REQUEST_TIMING_STOP";
152
153
  LogMessage["WEB_REQUEST_TIMING_STOP_FAILED"] = "WEB_REQUEST_TIMING_STOP_FAILED";
154
+ LogMessage["TABLE_RELOAD_MOUNTED"] = "TABLE_RELOAD_MOUNTED";
155
+ LogMessage["TABLE_RELOAD_DATA_CHANGED"] = "TABLE_RELOAD_DATA_CHANGED";
156
+ LogMessage["TABLE_RELOAD_DATA_CHANGED_NOT_FOCUSED"] = "TABLE_RELOAD_DATA_CHANGED_NOT_FOCUSED";
157
+ LogMessage["TABLE_RELOAD_DEBOUNCE_ELAPSED"] = "TABLE_RELOAD_DEBOUNCE_ELAPSED";
158
+ LogMessage["TABLE_RELOAD_DEBOUNCE_LOST_FOCUS"] = "TABLE_RELOAD_DEBOUNCE_LOST_FOCUS";
159
+ LogMessage["TABLE_RELOAD_FOCUS_RESTORED"] = "TABLE_RELOAD_FOCUS_RESTORED";
160
+ LogMessage["TABLE_RELOAD_TRIGGER_REGISTERED"] = "TABLE_RELOAD_TRIGGER_REGISTERED";
161
+ LogMessage["TABLE_RELOAD_TRIGGER_SKIPPED"] = "TABLE_RELOAD_TRIGGER_SKIPPED";
162
+ LogMessage["TABLE_RELOAD_TRIGGER_FIRED"] = "TABLE_RELOAD_TRIGGER_FIRED";
153
163
  })(LogMessage = exports.LogMessage || (exports.LogMessage = {}));
154
164
  exports.LOG_MESSAGES = {
155
165
  [LogMessage.ACTION_CANCEL]: {
@@ -478,6 +488,10 @@ exports.LOG_MESSAGES = {
478
488
  logType: LogType_1.LogType.Warning,
479
489
  documentationUri: 'https://dt-url.net/7al37nc',
480
490
  },
491
+ [LogMessage.NAVIGATION_FRAME_TIMING]: {
492
+ template: ({ frameEndMs, deltaMs, }) => `[NavigationFrame]: frame_end=${frameEndMs} delta_ms=${deltaMs}`,
493
+ logType: LogType_1.LogType.Info,
494
+ },
481
495
  [LogMessage.NAVIGATION_NOT_STARTED]: {
482
496
  template: 'React Native plugin has not been started yet! Navigation will not be reported!',
483
497
  logType: LogType_1.LogType.Warning,
@@ -803,4 +817,40 @@ exports.LOG_MESSAGES = {
803
817
  logType: LogType_1.LogType.Warning,
804
818
  documentationUri: 'https://dt-url.net/4us39ur',
805
819
  },
820
+ [LogMessage.TABLE_RELOAD_MOUNTED]: {
821
+ template: ({ label, length }) => `${label} mounted — skipping initial value (length=${length})`,
822
+ logType: LogType_1.LogType.Info,
823
+ },
824
+ [LogMessage.TABLE_RELOAD_DATA_CHANGED]: {
825
+ template: ({ label, length }) => `${label} data changed — debouncing (length=${length})`,
826
+ logType: LogType_1.LogType.Info,
827
+ },
828
+ [LogMessage.TABLE_RELOAD_DATA_CHANGED_NOT_FOCUSED]: {
829
+ template: ({ label, length }) => `${label} data changed while not focused (length=${length}) — deferring until refocus`,
830
+ logType: LogType_1.LogType.Info,
831
+ },
832
+ [LogMessage.TABLE_RELOAD_DEBOUNCE_ELAPSED]: {
833
+ template: ({ label }) => `${label} debounce elapsed — firing tableReload`,
834
+ logType: LogType_1.LogType.Info,
835
+ },
836
+ [LogMessage.TABLE_RELOAD_DEBOUNCE_LOST_FOCUS]: {
837
+ template: ({ label }) => `${label} lost focus while debounce was running — deferring until refocus`,
838
+ logType: LogType_1.LogType.Info,
839
+ },
840
+ [LogMessage.TABLE_RELOAD_FOCUS_RESTORED]: {
841
+ template: ({ label }) => `${label} screen focused with pending reload — firing tableReload`,
842
+ logType: LogType_1.LogType.Info,
843
+ },
844
+ [LogMessage.TABLE_RELOAD_TRIGGER_REGISTERED]: {
845
+ template: ({ state }) => `TableReloadTracker: trigger ${state}`,
846
+ logType: LogType_1.LogType.Info,
847
+ },
848
+ [LogMessage.TABLE_RELOAD_TRIGGER_SKIPPED]: {
849
+ template: 'TableReloadTracker: tableReload skipped — no trigger registered (SR not enabled)',
850
+ logType: LogType_1.LogType.Info,
851
+ },
852
+ [LogMessage.TABLE_RELOAD_TRIGGER_FIRED]: {
853
+ template: 'TableReloadTracker: tableReload firing → bridge trackEvent("tableReload")',
854
+ logType: LogType_1.LogType.Info,
855
+ },
806
856
  };
@@ -1,14 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
2
  const TerminalReporter = (() => {
13
3
  try {
14
4
  return require('metro/src/lib/TerminalReporter');
@@ -18,23 +8,4 @@ const TerminalReporter = (() => {
18
8
  }
19
9
  })();
20
10
  const { Terminal } = require('metro-core');
21
- const files = require('../scripts/FileOperationHelper');
22
- const paths = require('../scripts/PathsConstants');
23
- const reporter = new TerminalReporter(new Terminal(process.stdout));
24
- const updateOrig = TerminalReporter.prototype.update;
25
- TerminalReporter.prototype.update = function update(event) {
26
- return updateOrig === null || updateOrig === void 0 ? void 0 : updateOrig.apply(this, arguments);
27
- };
28
- const update = (event) => __awaiter(void 0, void 0, void 0, function* () {
29
- if (event != null) {
30
- if (event.type === 'transform_cache_reset') {
31
- try {
32
- yield files.default.deleteDirectory(paths.default.getBuildPath());
33
- }
34
- catch (e) {
35
- }
36
- }
37
- }
38
- reporter.update(event);
39
- });
40
- module.exports.update = update;
11
+ module.exports = new TerminalReporter(new Terminal(process.stdout));
@@ -1,40 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getUpstreamTransformer = exports.transform = void 0;
4
- const config = require("../scripts/Config");
5
- const Logger_1 = require("../scripts/Logger");
6
4
  const BabelPluginDynatrace_1 = require("../instrumentation/BabelPluginDynatrace");
7
- const instrumentor = require("../instrumentation/DynatraceInstrumentation");
8
5
  const Config_1 = require("../scripts/Config");
9
6
  const transform = (args) => {
10
7
  var _a;
11
- let src = args.src;
12
- const { filename, options } = args;
13
- let reactOptions;
14
- try {
15
- reactOptions = (0, Config_1.readConfigDefault)();
16
- if (!reactOptions.react.useLegacyJscodeshift) {
17
- args.plugins = [BabelPluginDynatrace_1.default, ...((_a = args.plugins) !== null && _a !== void 0 ? _a : [])];
18
- return (0, exports.getUpstreamTransformer)(reactOptions === null || reactOptions === void 0 ? void 0 : reactOptions.react).transform(args);
19
- }
20
- src = instrumentor.instrument(src, filename, reactOptions.react);
21
- }
22
- catch (e) {
23
- if (e instanceof Error) {
24
- if (e.message === config.ERROR_CONFIG_NOT_AVAILABLE) {
25
- console.log('dynatrace.config.js not found!');
26
- }
27
- else {
28
- console.log("Couldn't instrument file: " + filename);
29
- Logger_1.default.logErrorSync(e.message);
30
- }
31
- }
32
- }
33
- return (0, exports.getUpstreamTransformer)(reactOptions === null || reactOptions === void 0 ? void 0 : reactOptions.react).transform({
34
- src,
35
- filename,
36
- options,
37
- });
8
+ args.plugins = [BabelPluginDynatrace_1.default, ...((_a = args.plugins) !== null && _a !== void 0 ? _a : [])];
9
+ return (0, exports.getUpstreamTransformer)((0, Config_1.readConfigDefault)().react).transform(args);
38
10
  };
39
11
  exports.transform = transform;
40
12
  const safeRequire = (modulePath) => {
@@ -45,10 +17,10 @@ const safeRequire = (modulePath) => {
45
17
  return null;
46
18
  }
47
19
  };
48
- const getUpstreamTransformer = (reactOptions) => {
49
- if (reactOptions !== undefined &&
50
- reactOptions.upstreamTransformer !== undefined) {
51
- return require(reactOptions.upstreamTransformer);
20
+ const getUpstreamTransformer = (transformerReactConfig) => {
21
+ const upstreamTransformer = transformerReactConfig === null || transformerReactConfig === void 0 ? void 0 : transformerReactConfig.upstreamTransformer;
22
+ if (upstreamTransformer !== undefined) {
23
+ return require(upstreamTransformer);
52
24
  }
53
25
  else {
54
26
  const transformer = safeRequire('@expo/metro-config/babel-transformer') ||
@@ -3,7 +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,
7
6
  instance_id: '',
8
7
  session_id: '',
9
8
  application_id: '',
@@ -28,9 +28,6 @@ class RuntimeConfigurationObserverImpl {
28
28
  const thirdGenEnabled = typeof payload['3rd_gen_enabled'] === 'boolean'
29
29
  ? payload['3rd_gen_enabled']
30
30
  : undefined;
31
- const touchInteractionEnabled = typeof payload.touch_interaction_enabled === 'boolean'
32
- ? payload.touch_interaction_enabled
33
- : undefined;
34
31
  const traceContextEnabled = typeof payload.trace_context_enabled === 'boolean'
35
32
  ? payload.trace_context_enabled
36
33
  : undefined;
@@ -60,10 +57,8 @@ class RuntimeConfigurationObserverImpl {
60
57
  const tracestateKeyPrefix = typeof payload.tracestate_key_prefix === 'string'
61
58
  ? payload.tracestate_key_prefix
62
59
  : undefined;
63
- const normalized = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (typeof thirdGenEnabled === 'boolean'
60
+ const normalized = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (typeof thirdGenEnabled === 'boolean'
64
61
  ? { '3rd_gen_enabled': thirdGenEnabled }
65
- : {})), (typeof touchInteractionEnabled === 'boolean'
66
- ? { touch_interaction_enabled: touchInteractionEnabled }
67
62
  : {})), (typeof traceContextEnabled === 'boolean'
68
63
  ? { trace_context_enabled: traceContextEnabled }
69
64
  : {})), (typeof dataCollectionLevel === 'number'
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ALL_APP_START_KEYS = exports.EVENT_WHITELIST_SIZE = exports.MODIFY_EVENT_WHITELIST_NAMESPACE = exports.MODIFY_EVENT_WHITELIST_STRING_FIELDS = exports.MODIFY_EVENT_WHITELIST_FIELDS = exports.SEND_SESSION_PROPERTY_EVENT_WHITELIST_FIELDS = exports.SEND_EXCEPTION_EVENT_WHITELIST_FIELDS = exports.SEND_EVENT_WHITELIST_FIELDS = exports.SEND_SESSION_PROPERTY_EVENT_WHITELIST_NAMESPACES = exports.SEND_EXCEPTION_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 = exports.SPECIFICATION_VERSION = void 0;
4
- exports.SPECIFICATION_VERSION = '0.24.0';
4
+ exports.SPECIFICATION_VERSION = '1.0.0';
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;
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports._resetForTest = exports.getActivePath = exports.reportScreenResume = exports.reportScreenBackground = exports.reportScreenChange = exports.buildPathFromState = exports.registerNavigationEventTrigger = void 0;
5
+ const ConsoleLogger_1 = require("../../core/logging/ConsoleLogger");
6
+ const LogMessages_1 = require("../../core/logging/LogMessages");
7
+ const ConfigurationHandler_1 = require("../../core/configuration/ConfigurationHandler");
8
+ const DynatraceBridge_1 = require("../../core/DynatraceBridge");
9
+ const BaseDataEventModifier_1 = require("../events/modifier/BaseDataEventModifier");
10
+ const DynatraceEventBus_1 = require("../DynatraceEventBus");
11
+ const logger = new ConsoleLogger_1.ConsoleLogger('NavigationTracker');
12
+ (_a = (0, DynatraceEventBus_1.createEmitterRuntimeConfig)()) === null || _a === void 0 ? void 0 : _a.addListener('DTNavigationFrame', (event) => {
13
+ logger.debug(LogMessages_1.LogMessage.NAVIGATION_FRAME_TIMING, {
14
+ frameEndMs: Math.round(event.frameEndMs),
15
+ deltaMs: event.deltaMs.toFixed(1),
16
+ });
17
+ });
18
+ let eventTrigger = null;
19
+ const registerNavigationEventTrigger = (fn) => {
20
+ eventTrigger = fn;
21
+ };
22
+ exports.registerNavigationEventTrigger = registerNavigationEventTrigger;
23
+ let activePath = '';
24
+ let isBackgrounded = false;
25
+ const buildPathFromState = (state) => {
26
+ var _a, _b;
27
+ let currentState = state;
28
+ const parts = [];
29
+ while (currentState === null || currentState === void 0 ? void 0 : currentState.routes[(_a = currentState.index) !== null && _a !== void 0 ? _a : 0]) {
30
+ const currentRoute = currentState.routes[(_b = currentState.index) !== null && _b !== void 0 ? _b : 0];
31
+ parts.push(currentRoute.name);
32
+ currentState = currentRoute.state;
33
+ }
34
+ return parts.join('/');
35
+ };
36
+ exports.buildPathFromState = buildPathFromState;
37
+ const startView = (newPath) => {
38
+ if (!ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) {
39
+ logger.info(LogMessages_1.LogMessage.NAVIGATION_NOT_STARTED);
40
+ return;
41
+ }
42
+ const startViewInternalEvent = new BaseDataEventModifier_1.BaseDataEventModifier().modifyEvent(Object.assign({ 'view.detected_name': newPath }, (activePath && {
43
+ 'view.source.detected_name': activePath,
44
+ })));
45
+ const fn = DynatraceBridge_1.DynatraceNative === null || DynatraceBridge_1.DynatraceNative === void 0 ? void 0 : DynatraceBridge_1.DynatraceNative.startViewInternal;
46
+ if (typeof fn === 'function') {
47
+ fn(startViewInternalEvent);
48
+ }
49
+ logger.debug(LogMessages_1.LogMessage.START_VIEW_INTERNAL, {
50
+ event: JSON.stringify(startViewInternalEvent),
51
+ });
52
+ };
53
+ const stopView = () => {
54
+ if (!ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) {
55
+ logger.info(LogMessages_1.LogMessage.NAVIGATION_NOT_STARTED);
56
+ return;
57
+ }
58
+ const fn = DynatraceBridge_1.DynatraceNative === null || DynatraceBridge_1.DynatraceNative === void 0 ? void 0 : DynatraceBridge_1.DynatraceNative.stopViewInternal;
59
+ if (typeof fn === 'function') {
60
+ fn();
61
+ }
62
+ logger.debug(LogMessages_1.LogMessage.STOP_VIEW_INTERNAL);
63
+ };
64
+ const reportScreenChange = (newPath) => {
65
+ if (newPath === activePath) {
66
+ return;
67
+ }
68
+ if (activePath !== '') {
69
+ stopView();
70
+ }
71
+ startView(newPath);
72
+ activePath = newPath;
73
+ if (newPath) {
74
+ eventTrigger === null || eventTrigger === void 0 ? void 0 : eventTrigger(newPath, Date.now());
75
+ }
76
+ };
77
+ exports.reportScreenChange = reportScreenChange;
78
+ const reportScreenBackground = () => {
79
+ isBackgrounded = true;
80
+ stopView();
81
+ };
82
+ exports.reportScreenBackground = reportScreenBackground;
83
+ const reportScreenResume = () => {
84
+ if (!isBackgrounded) {
85
+ return;
86
+ }
87
+ isBackgrounded = false;
88
+ startView(activePath);
89
+ if (activePath) {
90
+ eventTrigger === null || eventTrigger === void 0 ? void 0 : eventTrigger(activePath, Date.now());
91
+ }
92
+ };
93
+ exports.reportScreenResume = reportScreenResume;
94
+ const getActivePath = () => activePath;
95
+ exports.getActivePath = getActivePath;
96
+ const _resetForTest = () => {
97
+ activePath = '';
98
+ isBackgrounded = false;
99
+ eventTrigger = null;
100
+ };
101
+ exports._resetForTest = _resetForTest;
@@ -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,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.callTableReloadTrigger = exports.registerTableReloadTrigger = void 0;
4
+ const ConsoleLogger_1 = require("../../core/logging/ConsoleLogger");
5
+ const LogMessages_1 = require("../../core/logging/LogMessages");
6
+ const logger = new ConsoleLogger_1.ConsoleLogger('TableReload');
7
+ let tableReloadTrigger = null;
8
+ const registerTableReloadTrigger = (fn) => {
9
+ tableReloadTrigger = fn;
10
+ logger.debug(LogMessages_1.LogMessage.TABLE_RELOAD_TRIGGER_REGISTERED, {
11
+ state: fn ? 'registered (SR enabled)' : 'cleared (SR disabled)',
12
+ });
13
+ };
14
+ exports.registerTableReloadTrigger = registerTableReloadTrigger;
15
+ const callTableReloadTrigger = (timestamp) => {
16
+ if (tableReloadTrigger == null) {
17
+ logger.debug(LogMessages_1.LogMessage.TABLE_RELOAD_TRIGGER_SKIPPED);
18
+ return;
19
+ }
20
+ logger.debug(LogMessages_1.LogMessage.TABLE_RELOAD_TRIGGER_FIRED);
21
+ tableReloadTrigger(timestamp);
22
+ };
23
+ exports.callTableReloadTrigger = callTableReloadTrigger;
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@dynatrace/react-native-plugin",
3
- "version": "2.343.1",
3
+ "version": "2.347.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.4.0",
54
53
  "plist": "^3.1.0",
55
54
  "proxy-polyfill": "^0.3.2",
56
55
  "semver": "^7.8.5"
@@ -58,21 +57,14 @@
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",
73
- "@istanbuljs/load-nyc-config": {
74
- "js-yaml": "^3.15.0"
75
- }
64
+ "ws": "^8.21.1",
65
+ "js-yaml": "^5.2.2",
66
+ "brace-expansion": "5.0.9",
67
+ "@xmldom/xmldom": "^0.9.12"
76
68
  },
77
69
  "devDependencies": {
78
70
  "@babel/plugin-transform-class-properties": "^7.27.1",
@@ -80,6 +72,7 @@
80
72
  "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1",
81
73
  "@babel/plugin-transform-optional-chaining": "^7.27.1",
82
74
  "@babel/preset-env": "^7.27.2",
75
+ "@babel/preset-flow": "^7.27.1",
83
76
  "@babel/preset-react": "^7.27.1",
84
77
  "@react-native-picker/picker": "^2.11.4",
85
78
  "@react-native/babel-preset": "^0.80.1",
@@ -87,7 +80,6 @@
87
80
  "@react-navigation/drawer": "^7.7.2",
88
81
  "@testing-library/react-native": "^13.3.3",
89
82
  "@types/jest": "^30.0.0",
90
- "@types/jscodeshift": "^17.3.0",
91
83
  "@types/micromatch": "^4.0.10",
92
84
  "@types/node": "^18.19.123",
93
85
  "@types/plist": "^3.0.5",
@@ -98,7 +90,6 @@
98
90
  "@typescript-eslint/eslint-plugin": "^8.56.0",
99
91
  "@typescript-eslint/parser": "^8.56.0",
100
92
  "compressing": "^1.10.3",
101
- "diff": "^8.0.2",
102
93
  "eslint": "^9.29.0",
103
94
  "eslint-config-prettier": "^8.5.0",
104
95
  "eslint-plugin-import": "^2.32.0",
@@ -132,6 +123,7 @@
132
123
  "index.js",
133
124
  "public.js",
134
125
  "internal.js",
126
+ "internal.d.ts",
135
127
  "react-augmentation.js",
136
128
  "README.md",
137
129
  "LICENSE.md",
@@ -157,8 +149,6 @@
157
149
  "instrumentation/libs/react-native/*.js",
158
150
  "instrumentation/libs/react-native/Touchables.jsx",
159
151
  "instrumentation/model/*.js",
160
- "instrumentation/parser/*.js",
161
- "instrumentation/DynatraceInstrumentation.js",
162
152
  "instrumentation/BabelPluginDynatrace.js",
163
153
  "lib/*.js",
164
154
  "lib/core/*.js",
@@ -168,7 +158,6 @@
168
158
  "lib/core/model/*.js",
169
159
  "lib/core/util/*.js",
170
160
  "lib/core/*.js",
171
- "lib/metro/*.js",
172
161
  "lib/next/*.js",
173
162
  "lib/next/appstart/*.js",
174
163
  "lib/next/configuration/*.js",
@@ -179,7 +168,8 @@
179
168
  "lib/next/util/*.js",
180
169
  "lib/next/provider/*.js",
181
170
  "lib/next/userAction/*.js",
182
- "lib/features/ui-interaction/*.js",
171
+ "lib/next/navigation/*.js",
172
+ "lib/next/triggers/*.js",
183
173
  "src/lib/core/interface/NativeDynatraceBridge.ts",
184
174
  "types.d.ts"
185
175
  ],
package/public.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- 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;
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");
@@ -27,4 +27,6 @@ var ExceptionEventData_1 = require("./lib/next/events/ExceptionEventData");
27
27
  Object.defineProperty(exports, "ExceptionEventData", { enumerable: true, get: function () { return ExceptionEventData_1.default; } });
28
28
  var UserActionConfiguration_1 = require("./lib/next/userAction/UserActionConfiguration");
29
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; } });
30
32
  require("./react-augmentation");
@@ -118,7 +118,7 @@ Pod::Spec.new do |s|
118
118
  #
119
119
 
120
120
  s.dependency "React"
121
- s.dependency 'Dynatrace', '~> 8.343.1.1007'
121
+ s.dependency 'Dynatrace', '~> 8.347.1.1004'
122
122
 
123
123
  # Allows for better compatibility for older and newer versions
124
124
  if defined?(install_modules_dependencies)