@dynatrace/react-native-plugin 2.331.1 → 2.335.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 (48) hide show
  1. package/README.md +136 -177
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +7 -1
  4. package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.kt +1 -0
  5. package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +1 -0
  6. package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +2 -1
  7. package/files/plugin-runtime.gradle +27 -13
  8. package/files/plugin.gradle +1 -1
  9. package/instrumentation/BabelPluginDynatrace.js +1 -0
  10. package/instrumentation/DynatraceInstrumentation.js +1 -1
  11. package/instrumentation/jsx/CreateElement.js +106 -6
  12. package/instrumentation/jsx/JsxDevRuntime.js +2 -6
  13. package/instrumentation/jsx/JsxRuntime.js +6 -10
  14. package/instrumentation/libs/UserInteraction.js +114 -0
  15. package/instrumentation/libs/community/gesture-handler/Touchables.InstrInfo.js +2 -0
  16. package/instrumentation/libs/community/gesture-handler/Touchables.js +3 -1
  17. package/instrumentation/libs/community/gesture-handler/index.js +3 -1
  18. package/instrumentation/libs/withOnPressMonitoring.js +55 -3
  19. package/ios/DynatraceRNBridge.mm +8 -1
  20. package/lib/core/Application.js +2 -0
  21. package/lib/core/Dynatrace.js +2 -1
  22. package/lib/core/UserPrivacyOptions.js +8 -1
  23. package/lib/core/configuration/ConfigurationHandler.js +21 -0
  24. package/lib/dynatrace-reporter.js +0 -14
  25. package/lib/dynatrace-transformer.js +10 -13
  26. package/lib/features/ui-interaction/Config.js +42 -0
  27. package/lib/features/ui-interaction/IUserInteractionEvent.js +16 -0
  28. package/lib/features/ui-interaction/Plugin.Fragment.Test.js +170 -0
  29. package/lib/features/ui-interaction/Plugin.js +289 -0
  30. package/lib/features/ui-interaction/RootDetection.js +51 -0
  31. package/lib/features/ui-interaction/RootWrapper.js +236 -0
  32. package/lib/features/ui-interaction/Run.js +38 -0
  33. package/lib/features/ui-interaction/Runtime.js +827 -0
  34. package/lib/features/ui-interaction/TouchMetaResolver.js +492 -0
  35. package/lib/features/ui-interaction/Types.js +14 -0
  36. package/lib/next/Dynatrace.js +1 -1
  37. package/lib/next/configuration/INativeRuntimeConfiguration.js +1 -0
  38. package/lib/next/configuration/RuntimeConfigurationObserver.js +47 -12
  39. package/lib/next/events/EventPipeline.js +9 -0
  40. package/package.json +19 -13
  41. package/react-native-dynatrace.podspec +1 -1
  42. package/scripts/Android.js +75 -62
  43. package/scripts/Config.js +12 -1
  44. package/scripts/core/InstrumentCall.js +1 -2
  45. package/scripts/core/LineOffsetAnalyzeCall.js +9 -15
  46. package/src/lib/core/interface/NativeDynatraceBridge.ts +1 -0
  47. package/types.d.ts +22 -9
  48. package/scripts/util/ReactOptions.js +0 -21
@@ -0,0 +1,492 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTouchElementMeta = void 0;
4
+ class TouchMetaResolver {
5
+ constructor(config) {
6
+ this.rootWrapperLikePatterns = [
7
+ /Animated/,
8
+ /Controller/,
9
+ /Detector/,
10
+ /NativeComponent/,
11
+ /Wrapper/,
12
+ /Clipping/,
13
+ ];
14
+ this.genericContainerCodeTagNames = new Set([
15
+ 'View',
16
+ 'Background',
17
+ 'Drawer',
18
+ 'DrawerView',
19
+ 'DrawerViewBase',
20
+ 'Freeze',
21
+ 'DelayedFreeze',
22
+ 'Suspender',
23
+ 'MaybeScreen',
24
+ 'MaybeScreenContainer',
25
+ 'Screen',
26
+ 'ScreenContainer',
27
+ 'RNSScreen',
28
+ 'RNSScreenContainer',
29
+ 'GestureHandlerRootView',
30
+ 'RNGestureHandlerRootView',
31
+ 'PanGestureHandler',
32
+ ]);
33
+ this.internalCodeTagExactNames = new Set([
34
+ 'main(RootComponent)',
35
+ 'PerformanceLoggerContext',
36
+ 'RootTagContext',
37
+ 'Wrapped',
38
+ 'AnalyticsRoot',
39
+ ]);
40
+ this.uselessWrapperCodeTagExactNames = new Set([
41
+ 'DynatraceFunctionalComponent',
42
+ 'DynatraceClassComponent',
43
+ 'NavigationContainer',
44
+ 'BaseNavigationContainer',
45
+ 'Navigator',
46
+ 'DrawerNavigator',
47
+ 'SafeAreaProviderCompat',
48
+ 'Handler',
49
+ 'AnimatedComponent',
50
+ 'Component',
51
+ 'ScreenNavigationContainer',
52
+ 'ScreenWrapper',
53
+ 'Suspense',
54
+ 'AnimatedScreen',
55
+ 'ScreenComponent',
56
+ 'KeyboardControllerViewAnimated',
57
+ ]);
58
+ this.internalCodeTagPatterns = [
59
+ /Context$/,
60
+ /Provider$/,
61
+ /^Route(?:\(|$)/,
62
+ /^Animated(?:Component)?\(.+\)$/,
63
+ /^Anonymous$/,
64
+ /NavigationContent/,
65
+ /NavigationStateListenerProvider/,
66
+ /PreventRemoveProvider/,
67
+ /EnsureSingleNavigator/,
68
+ /SceneView/,
69
+ /StaticContainer/,
70
+ /GestureHandler/,
71
+ /expo-router\/build\//,
72
+ ];
73
+ this.pressHandlers = [
74
+ 'onPress',
75
+ 'onLongPress',
76
+ 'onPressIn',
77
+ 'onPressOut',
78
+ ];
79
+ this.config = Object.assign({ filterInternalCodeTags: true }, config);
80
+ }
81
+ resolve(event) {
82
+ var _a, _b, _c, _d;
83
+ try {
84
+ const raw = event;
85
+ const targetInst = (_a = raw._targetInst) !== null && _a !== void 0 ? _a : (_b = raw.nativeEvent) === null || _b === void 0 ? void 0 : _b._targetInst;
86
+ const touchElementName = (_c = this.getNodeName(targetInst)) !== null && _c !== void 0 ? _c : 'unknown';
87
+ const touchPath = this.buildAppCodeTagPathFromNode(targetInst !== null && targetInst !== void 0 ? targetInst : null);
88
+ const pressNode = this.findPressNode(targetInst !== null && targetInst !== void 0 ? targetInst : null);
89
+ const press = pressNode === null
90
+ ? null
91
+ : {
92
+ elementName: (_d = this.getNodeName(pressNode)) !== null && _d !== void 0 ? _d : 'unknown',
93
+ appCodeTagPath: this.buildAppCodeTagPathFromNode(pressNode),
94
+ isParent: Boolean(pressNode !== targetInst),
95
+ };
96
+ return {
97
+ touch: {
98
+ elementName: touchElementName,
99
+ appCodeTagPath: touchPath,
100
+ },
101
+ press,
102
+ };
103
+ }
104
+ catch (_e) {
105
+ return {
106
+ touch: { elementName: 'unknown', appCodeTagPath: 'unknown' },
107
+ press: null,
108
+ };
109
+ }
110
+ }
111
+ buildAppCodeTagPathFromNode(node) {
112
+ var _a;
113
+ if (node === null) {
114
+ return 'unknown';
115
+ }
116
+ const targetToRootCodeTags = [];
117
+ let pathCursor = node;
118
+ while (pathCursor !== null) {
119
+ const codeTagSegment = this.getNodeCodeTagSegment(pathCursor);
120
+ if (codeTagSegment !== null) {
121
+ targetToRootCodeTags.push(codeTagSegment);
122
+ }
123
+ pathCursor = (_a = pathCursor.return) !== null && _a !== void 0 ? _a : null;
124
+ }
125
+ const normalizedCodeTags = this.collapseConsecutiveDuplicates(targetToRootCodeTags);
126
+ const rootToTargetCodeTags = [...normalizedCodeTags].reverse();
127
+ const appRootTrimmedCodeTags = this.trimToAppRoot(rootToTargetCodeTags);
128
+ const uiRootTrimmedCodeTags = this.trimToUiRootAnchor(appRootTrimmedCodeTags);
129
+ const dtPathPreferredCodeTags = this.preferDtPathCodeTags(uiRootTrimmedCodeTags);
130
+ const dtPathPreferredCodeTagNames = dtPathPreferredCodeTags.map((segment) => segment.name);
131
+ const trimmedRootToTargetCodeTags = this.trimFrameworkPrefix(dtPathPreferredCodeTagNames);
132
+ const filteredRootToTargetCodeTags = this.config.filterInternalCodeTags
133
+ ? this.filterAppCodeTags(trimmedRootToTargetCodeTags)
134
+ : trimmedRootToTargetCodeTags;
135
+ const dedupedFilteredRootToTargetCodeTags = this.collapseConsecutiveDuplicateNames(filteredRootToTargetCodeTags);
136
+ let appRootToTargetCodeTags = ['unknown'];
137
+ if (dedupedFilteredRootToTargetCodeTags.length > 0) {
138
+ appRootToTargetCodeTags = dedupedFilteredRootToTargetCodeTags;
139
+ }
140
+ else if (trimmedRootToTargetCodeTags.length > 0) {
141
+ appRootToTargetCodeTags = trimmedRootToTargetCodeTags;
142
+ }
143
+ return appRootToTargetCodeTags.join('/') || 'unknown';
144
+ }
145
+ getNodeName(node) {
146
+ var _a, _b;
147
+ if (node === null || node === undefined) {
148
+ return null;
149
+ }
150
+ const props = (_a = node.memoizedProps) !== null && _a !== void 0 ? _a : {};
151
+ const dtName = props.dtName;
152
+ if (typeof dtName === 'string' && dtName.trim().length > 0) {
153
+ return dtName.trim();
154
+ }
155
+ const testId = props.testID;
156
+ if (typeof testId === 'string' && testId.trim().length > 0) {
157
+ return testId;
158
+ }
159
+ const accessibilityLabel = props.accessibilityLabel;
160
+ if (typeof accessibilityLabel === 'string' &&
161
+ accessibilityLabel.trim().length > 0) {
162
+ return accessibilityLabel;
163
+ }
164
+ const dtPathIdName = this.getCodeTagNameFromDtPathId(props);
165
+ if (dtPathIdName !== null) {
166
+ return dtPathIdName;
167
+ }
168
+ const codeTagName = this.getNodeCodeTagName(node);
169
+ const isTextLike = codeTagName === 'Text' || codeTagName === 'RCTText';
170
+ const shouldReadChildrenText = isTextLike || this.hasPressHandler(props);
171
+ if (shouldReadChildrenText) {
172
+ const childText = this.extractTextFromChildren(props.children);
173
+ if (childText !== null) {
174
+ return childText;
175
+ }
176
+ }
177
+ return ((_b = this.getComponentTypeName(node.elementType)) !== null && _b !== void 0 ? _b : this.getComponentTypeName(node.type));
178
+ }
179
+ findPressNode(startNode) {
180
+ var _a;
181
+ let cursor = startNode;
182
+ while (cursor !== null) {
183
+ if (this.hasPressHandler(cursor.memoizedProps)) {
184
+ return cursor;
185
+ }
186
+ cursor = (_a = cursor.return) !== null && _a !== void 0 ? _a : null;
187
+ }
188
+ return null;
189
+ }
190
+ collapseConsecutiveDuplicates(items) {
191
+ const result = [];
192
+ for (const item of items) {
193
+ const previous = result.at(-1);
194
+ if (previous === undefined || previous.name !== item.name) {
195
+ result.push(item);
196
+ continue;
197
+ }
198
+ if (item.fromDtPathId && !previous.fromDtPathId) {
199
+ previous.fromDtPathId = true;
200
+ }
201
+ if (item.isUiRoot && !previous.isUiRoot) {
202
+ previous.isUiRoot = true;
203
+ }
204
+ }
205
+ return result;
206
+ }
207
+ trimToUiRootAnchor(rootToTargetCodeTags) {
208
+ if (rootToTargetCodeTags.length === 0) {
209
+ return rootToTargetCodeTags;
210
+ }
211
+ let uiRootIndex = -1;
212
+ for (let i = rootToTargetCodeTags.length - 1; i >= 0; i--) {
213
+ if (rootToTargetCodeTags[i].isUiRoot) {
214
+ uiRootIndex = i;
215
+ break;
216
+ }
217
+ }
218
+ if (uiRootIndex < 0) {
219
+ return rootToTargetCodeTags;
220
+ }
221
+ return rootToTargetCodeTags.slice(uiRootIndex);
222
+ }
223
+ trimToAppRoot(rootToTargetCodeTags) {
224
+ if (rootToTargetCodeTags.length === 0) {
225
+ return rootToTargetCodeTags;
226
+ }
227
+ let start = 0;
228
+ const analyticsRootIndex = rootToTargetCodeTags.findIndex((segment) => segment.name === 'AnalyticsRoot');
229
+ if (analyticsRootIndex < 0) {
230
+ return [];
231
+ }
232
+ start = analyticsRootIndex + 1;
233
+ const enforceStableRootSignal = rootToTargetCodeTags
234
+ .slice(start)
235
+ .some((segment) => segment.fromDtPathId || segment.isUiRoot);
236
+ while (start < rootToTargetCodeTags.length - 1) {
237
+ const segment = rootToTargetCodeTags[start];
238
+ const name = segment.name;
239
+ const isProviderLike = /Provider(?:Compat)?$/.test(name);
240
+ const isBlacklistedStart = this.shouldDropCodeTagName(name, false);
241
+ const hasStableRootSignal = segment.fromDtPathId || segment.isUiRoot;
242
+ const shouldSkipByRootRule = enforceStableRootSignal && !hasStableRootSignal;
243
+ const isLikelyWrapperRoot = !hasStableRootSignal &&
244
+ this.rootWrapperLikePatterns.some((pattern) => pattern.test(name));
245
+ if (!isProviderLike &&
246
+ !isBlacklistedStart &&
247
+ !shouldSkipByRootRule &&
248
+ !isLikelyWrapperRoot) {
249
+ break;
250
+ }
251
+ start += 1;
252
+ }
253
+ return rootToTargetCodeTags.slice(start);
254
+ }
255
+ collapseConsecutiveDuplicateNames(items) {
256
+ const result = [];
257
+ for (const item of items) {
258
+ if (result.at(-1) !== item) {
259
+ result.push(item);
260
+ }
261
+ }
262
+ return result;
263
+ }
264
+ preferDtPathCodeTags(rootToTargetCodeTags) {
265
+ if (rootToTargetCodeTags.length === 0) {
266
+ return rootToTargetCodeTags;
267
+ }
268
+ const firstDtPathIndex = rootToTargetCodeTags.findIndex((segment) => segment.fromDtPathId);
269
+ if (firstDtPathIndex < 0) {
270
+ return rootToTargetCodeTags;
271
+ }
272
+ const fromFirstDtPath = rootToTargetCodeTags.slice(firstDtPathIndex);
273
+ return fromFirstDtPath.filter((segment, index) => {
274
+ if (segment.fromDtPathId) {
275
+ return true;
276
+ }
277
+ const isLeaf = index === fromFirstDtPath.length - 1;
278
+ return !this.shouldDropCodeTagName(segment.name, isLeaf);
279
+ });
280
+ }
281
+ isInternalCodeTagName(name) {
282
+ if (this.internalCodeTagExactNames.has(name)) {
283
+ return true;
284
+ }
285
+ return this.internalCodeTagPatterns.some((pattern) => pattern.test(name));
286
+ }
287
+ shouldDropCodeTagName(name, isLeaf) {
288
+ if (name.trim().length === 0) {
289
+ return true;
290
+ }
291
+ if (!isLeaf && this.uselessWrapperCodeTagExactNames.has(name)) {
292
+ return true;
293
+ }
294
+ if (this.isInternalCodeTagName(name)) {
295
+ return true;
296
+ }
297
+ if (!isLeaf && this.genericContainerCodeTagNames.has(name)) {
298
+ return true;
299
+ }
300
+ return false;
301
+ }
302
+ filterAppCodeTags(rootToTargetTags) {
303
+ return rootToTargetTags.filter((name, index) => {
304
+ const isLeaf = index === rootToTargetTags.length - 1;
305
+ return !this.shouldDropCodeTagName(name, isLeaf);
306
+ });
307
+ }
308
+ hasPressHandler(props) {
309
+ if (props === null || props === undefined) {
310
+ return false;
311
+ }
312
+ for (const key of this.pressHandlers) {
313
+ if (typeof props[key] === 'function') {
314
+ return true;
315
+ }
316
+ }
317
+ return false;
318
+ }
319
+ trimFrameworkPrefix(rootToTargetTags) {
320
+ if (rootToTargetTags.length === 0) {
321
+ return rootToTargetTags;
322
+ }
323
+ let indexRouteMarker = -1;
324
+ for (let i = rootToTargetTags.length - 1; i >= 0; i--) {
325
+ if (rootToTargetTags[i] === 'Index' ||
326
+ rootToTargetTags[i].startsWith('Index(')) {
327
+ indexRouteMarker = i;
328
+ break;
329
+ }
330
+ }
331
+ if (indexRouteMarker >= 0 &&
332
+ indexRouteMarker < rootToTargetTags.length - 1) {
333
+ return rootToTargetTags.slice(indexRouteMarker + 1);
334
+ }
335
+ const touchCaptureIndex = rootToTargetTags.lastIndexOf('TouchCapture');
336
+ if (touchCaptureIndex >= 0 &&
337
+ touchCaptureIndex < rootToTargetTags.length - 1) {
338
+ return rootToTargetTags.slice(touchCaptureIndex + 1);
339
+ }
340
+ return rootToTargetTags;
341
+ }
342
+ extractTextFromChildren(children, maxDepth = 5) {
343
+ var _a;
344
+ if (maxDepth <= 0) {
345
+ return null;
346
+ }
347
+ if (typeof children === 'string' || typeof children === 'number') {
348
+ const str = String(children).trim();
349
+ return str.length > 0 ? str : null;
350
+ }
351
+ if (Array.isArray(children)) {
352
+ for (const child of children) {
353
+ const text = this.extractTextFromChildren(child, maxDepth - 1);
354
+ if (text !== null) {
355
+ return text;
356
+ }
357
+ }
358
+ }
359
+ if (typeof children === 'object' &&
360
+ children !== null &&
361
+ 'props' in children &&
362
+ typeof children.props === 'object') {
363
+ const nestedChildren = (_a = children.props) === null || _a === void 0 ? void 0 : _a.children;
364
+ return this.extractTextFromChildren(nestedChildren, maxDepth - 1);
365
+ }
366
+ return null;
367
+ }
368
+ getCodeTagNameFromDtPathId(props) {
369
+ if (props === null || props === undefined) {
370
+ return null;
371
+ }
372
+ const rawDtPathId = props.dtPathID;
373
+ if (typeof rawDtPathId !== 'string') {
374
+ return null;
375
+ }
376
+ const trimmedDtPathId = rawDtPathId.trim();
377
+ if (trimmedDtPathId.length === 0) {
378
+ return null;
379
+ }
380
+ const strippedSuffix = trimmedDtPathId.replace(/_\d+_\d+$/, '');
381
+ const normalizedName = this.normalizeCodeTagName(strippedSuffix);
382
+ return normalizedName;
383
+ }
384
+ hasUiRootMarker(props) {
385
+ if (props === null || props === undefined) {
386
+ return false;
387
+ }
388
+ const rawUiRoot = props.dtUIRoot;
389
+ if (rawUiRoot === null || rawUiRoot === undefined) {
390
+ return false;
391
+ }
392
+ if (typeof rawUiRoot === 'boolean') {
393
+ return rawUiRoot;
394
+ }
395
+ if (typeof rawUiRoot === 'string') {
396
+ const normalized = rawUiRoot.trim().toLowerCase();
397
+ return normalized.length > 0 && normalized !== 'false';
398
+ }
399
+ return true;
400
+ }
401
+ getComponentTypeName(value) {
402
+ var _a, _b, _c, _d;
403
+ if (value === null || value === undefined) {
404
+ return null;
405
+ }
406
+ if (typeof value === 'string') {
407
+ return value;
408
+ }
409
+ if (typeof value === 'function') {
410
+ return ((_b = (_a = value
411
+ .displayName) !== null && _a !== void 0 ? _a : value.name) !== null && _b !== void 0 ? _b : null);
412
+ }
413
+ if (typeof value === 'object') {
414
+ const objectValue = value;
415
+ return (_d = (_c = objectValue.displayName) !== null && _c !== void 0 ? _c : objectValue.name) !== null && _d !== void 0 ? _d : null;
416
+ }
417
+ return null;
418
+ }
419
+ normalizeCodeTagName(name) {
420
+ if (name === null) {
421
+ return null;
422
+ }
423
+ const trimmedName = name.trim();
424
+ if (trimmedName.length === 0) {
425
+ return null;
426
+ }
427
+ if (trimmedName === 'RCTView' ||
428
+ trimmedName === 'RNView' ||
429
+ trimmedName === 'View') {
430
+ return 'View';
431
+ }
432
+ if (trimmedName === 'RCTText' ||
433
+ trimmedName === 'RNText' ||
434
+ trimmedName === 'Text') {
435
+ return 'Text';
436
+ }
437
+ if (trimmedName === 'RCTScrollView' || trimmedName === 'ScrollView') {
438
+ return 'ScrollView';
439
+ }
440
+ if (trimmedName === 'VirtualizedList') {
441
+ return 'FlatList';
442
+ }
443
+ return trimmedName;
444
+ }
445
+ getNodeCodeTagName(node) {
446
+ var _a, _b;
447
+ return (_b = (_a = this.getNodeCodeTagSegment(node)) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : null;
448
+ }
449
+ getNodeCodeTagSegment(node) {
450
+ var _a, _b;
451
+ if (node === null || node === undefined) {
452
+ return null;
453
+ }
454
+ const isUiRoot = this.hasUiRootMarker(node.memoizedProps);
455
+ const fromDtPathId = this.getCodeTagNameFromDtPathId(node.memoizedProps);
456
+ if (fromDtPathId !== null) {
457
+ return {
458
+ name: fromDtPathId,
459
+ fromDtPathId: true,
460
+ isUiRoot,
461
+ };
462
+ }
463
+ const dtInfoName = (_b = (_a = node.type) === null || _a === void 0 ? void 0 : _a._dtInfo) === null || _b === void 0 ? void 0 : _b.name;
464
+ if (typeof dtInfoName === 'string' && dtInfoName.trim().length > 0) {
465
+ return {
466
+ name: dtInfoName.trim(),
467
+ fromDtPathId: false,
468
+ isUiRoot,
469
+ };
470
+ }
471
+ const fromElementType = this.normalizeCodeTagName(this.getComponentTypeName(node.elementType));
472
+ if (fromElementType !== null) {
473
+ return {
474
+ name: fromElementType,
475
+ fromDtPathId: false,
476
+ isUiRoot,
477
+ };
478
+ }
479
+ const fromType = this.normalizeCodeTagName(this.getComponentTypeName(node.type));
480
+ if (fromType !== null) {
481
+ return {
482
+ name: fromType,
483
+ fromDtPathId: false,
484
+ isUiRoot,
485
+ };
486
+ }
487
+ return null;
488
+ }
489
+ }
490
+ const resolver = new TouchMetaResolver();
491
+ const getTouchElementMeta = (event) => resolver.resolve(event);
492
+ exports.getTouchElementMeta = getTouchElementMeta;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Literals = void 0;
4
+ exports.Literals = {
5
+ ReactFragmentFQN: 'React.Fragment',
6
+ NavigatorProp: 'Navigator',
7
+ PluginName: 'dt-user-interaction',
8
+ LogTag: '[dt] instrumented:',
9
+ RawHandlerTag: '[DT raw] handler',
10
+ KeySuffixPrefix: '~dt@',
11
+ DefaultRuntimeImport: '@dynatrace/react-native-plugin/lib/features/ui-interaction/Runtime',
12
+ DefaultArtifactsDir: 'node_modules/@dynatrace/react-native-plugin/build/ui_instrumented',
13
+ DefaultRootName: 'AnalyticsRoot',
14
+ };
@@ -38,7 +38,7 @@ class DynatraceImpl {
38
38
  }
39
39
  startView(name) {
40
40
  if (typeof name !== 'string') {
41
- this.logger.info(`startView(name): Name must be a string!`);
41
+ this.logger.info('startView(name): Name must be a string!');
42
42
  return;
43
43
  }
44
44
  this.logger.debug(`startView(${name})`);
@@ -3,5 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateDefaultConfiguration = void 0;
4
4
  const generateDefaultConfiguration = () => ({
5
5
  '3rd_gen_enabled': true,
6
+ touch_interaction_enabled: false,
6
7
  });
7
8
  exports.generateDefaultConfiguration = generateDefaultConfiguration;
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RuntimeConfigurationObserver = void 0;
4
+ const react_native_1 = require("react-native");
4
5
  const DynatraceBridge_1 = require("../../core/DynatraceBridge");
5
- const DynatraceEventBus_1 = require("../DynatraceEventBus");
6
6
  const INativeRuntimeConfiguration_1 = require("./INativeRuntimeConfiguration");
7
7
  class RuntimeConfigurationObserverImpl {
8
8
  constructor() {
@@ -12,25 +12,60 @@ class RuntimeConfigurationObserverImpl {
12
12
  this.subscription = null;
13
13
  this.setupNativeEventEmitter();
14
14
  }
15
+ call() {
16
+ }
15
17
  getCurrentRuntimeConfiguration() {
16
18
  return this.runtimeConfiguration;
17
19
  }
18
20
  isInitiated() {
19
21
  return this.observerIsInitiated;
20
22
  }
23
+ updateRuntimeConfiguration(data) {
24
+ if (!data || typeof data !== 'object') {
25
+ return;
26
+ }
27
+ const payload = data;
28
+ const thirdGenEnabled = typeof payload['3rd_gen_enabled'] === 'boolean'
29
+ ? payload['3rd_gen_enabled']
30
+ : undefined;
31
+ const touchInteractionEnabled = typeof payload.touch_interaction_enabled === 'boolean'
32
+ ? payload.touch_interaction_enabled
33
+ : undefined;
34
+ const normalized = Object.assign(Object.assign({}, (typeof thirdGenEnabled === 'boolean'
35
+ ? { '3rd_gen_enabled': thirdGenEnabled }
36
+ : {})), (typeof touchInteractionEnabled === 'boolean'
37
+ ? { touch_interaction_enabled: touchInteractionEnabled }
38
+ : {}));
39
+ this.runtimeConfiguration = Object.assign(Object.assign({}, (0, INativeRuntimeConfiguration_1.generateDefaultConfiguration)()), normalized);
40
+ this.observerIsInitiated = true;
41
+ }
42
+ resolveBridgeModule() {
43
+ const dynatraceModule = DynatraceBridge_1.DynatraceNative;
44
+ const hasDynatraceBridgeAPI = !!dynatraceModule &&
45
+ (typeof dynatraceModule.addListener === 'function' ||
46
+ typeof dynatraceModule.getCurrentConfiguration === 'function');
47
+ if (hasDynatraceBridgeAPI) {
48
+ return dynatraceModule;
49
+ }
50
+ return react_native_1.NativeModules.DynatraceBridge;
51
+ }
21
52
  setupNativeEventEmitter() {
22
- const emitter = (0, DynatraceEventBus_1.createEmitterRuntimeConfig)();
23
- this.subscription = (0, DynatraceEventBus_1.addListenerOnce)(emitter, this.subscription, this.EMIT_CONFIGURATION, (data) => {
24
- this.runtimeConfiguration = data;
25
- this.observerIsInitiated = true;
26
- });
27
- if (typeof DynatraceBridge_1.DynatraceNative.getCurrentConfiguration === 'function') {
28
- Promise.resolve(DynatraceBridge_1.DynatraceNative.getCurrentConfiguration())
53
+ const bridgeModule = this.resolveBridgeModule();
54
+ if (!bridgeModule) {
55
+ return;
56
+ }
57
+ const iosModule = react_native_1.NativeModules.DynatraceBridge;
58
+ const nativeEmitterModule = react_native_1.Platform.OS === 'ios' ? iosModule || bridgeModule : bridgeModule;
59
+ const emitter = new react_native_1.NativeEventEmitter(nativeEmitterModule);
60
+ if (this.subscription == null) {
61
+ this.subscription = emitter.addListener(this.EMIT_CONFIGURATION, (data) => {
62
+ this.updateRuntimeConfiguration(data);
63
+ });
64
+ }
65
+ if (typeof bridgeModule.getCurrentConfiguration === 'function') {
66
+ Promise.resolve(bridgeModule.getCurrentConfiguration())
29
67
  .then((data) => {
30
- if (data) {
31
- this.runtimeConfiguration = data;
32
- this.observerIsInitiated = true;
33
- }
68
+ this.updateRuntimeConfiguration(data);
34
69
  })
35
70
  .catch(() => {
36
71
  });
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EventPipeline = void 0;
4
4
  const DynatraceBridge_1 = require("../../core/DynatraceBridge");
5
5
  const ConsoleLogger_1 = require("../../core/logging/ConsoleLogger");
6
+ const ConfigurationHandler_1 = require("../../core/configuration/ConfigurationHandler");
6
7
  const BaseDataEventModifier_1 = require("./modifier/BaseDataEventModifier");
7
8
  const ValueRestrictionModifier_1 = require("./modifier/ValueRestrictionModifier");
8
9
  const ModifyEventValidation_1 = require("./modifier/ModifyEventValidation");
@@ -24,6 +25,14 @@ class EventPipelineImpl {
24
25
  ];
25
26
  }
26
27
  insertEvent(event) {
28
+ if (!ConfigurationHandler_1.ConfigurationHandler.isRuntimeConfigurationInitiated()) {
29
+ this.logger.debug('isRuntimeConfigurationInitiated is not enabled! App start event will be discarded!');
30
+ return;
31
+ }
32
+ if (!ConfigurationHandler_1.ConfigurationHandler.isGrailEnabled()) {
33
+ this.logger.debug('RUM on Grail is not enabled! App start event will be discarded!');
34
+ return;
35
+ }
27
36
  this.logger.debug(`insertEvent(${JSON.stringify(event)})`);
28
37
  let isDiscarded = false;
29
38
  for (const modifier of this.getEventModifierChain()) {