@dynatrace/react-native-plugin 2.335.1 → 2.337.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +141 -61
  2. package/android/build.gradle +1 -1
  3. package/files/plugin.gradle +1 -1
  4. package/instrumentation/BabelPluginDynatrace.js +1 -1
  5. package/instrumentation/DynatraceInstrumentation.js +1 -1
  6. package/instrumentation/libs/community/Picker.js +1 -1
  7. package/instrumentation/libs/react-navigation/ReactNavigation.js +9 -0
  8. package/instrumentation/libs/withOnPressMonitoring.js +59 -14
  9. package/lib/core/Dynatrace.js +3 -0
  10. package/lib/core/DynatraceBridge.js +5 -7
  11. package/lib/core/configuration/ActionNameOptions.js +2 -0
  12. package/lib/core/configuration/Configuration.js +5 -1
  13. package/lib/core/configuration/ConfigurationBuilder.js +11 -1
  14. package/lib/core/configuration/ConfigurationDefaults.js +3 -1
  15. package/lib/core/configuration/ConfigurationHandler.js +64 -0
  16. package/lib/core/configuration/ConfigurationPreset.js +6 -0
  17. package/lib/core/configuration/ManualStartupConfiguration.js +9 -1
  18. package/lib/features/ui-interaction/Runtime.js +31 -19
  19. package/lib/next/Dynatrace.js +44 -0
  20. package/lib/next/configuration/INativeRuntimeConfiguration.js +9 -0
  21. package/lib/next/configuration/RuntimeConfigurationObserver.js +50 -6
  22. package/lib/next/events/EventPipeline.js +14 -6
  23. package/lib/next/events/HttpRequestEventData.js +26 -30
  24. package/lib/next/provider/TimestampProvider.js +20 -7
  25. package/lib/next/util/TraceContextUtils.js +108 -0
  26. package/package.json +3 -2
  27. package/react-native-dynatrace.podspec +1 -1
  28. package/scripts/Android.js +27 -10
  29. package/scripts/Config.js +1 -1
  30. package/scripts/Ios.js +288 -71
  31. package/scripts/PathsConstants.js +34 -20
  32. package/scripts/core/InstrumentCall.js +7 -1
  33. package/scripts/util/SourceMapUtil.js +49 -11
  34. package/types.d.ts +178 -39
@@ -128,30 +128,73 @@ const findTouchableName = (props) => {
128
128
  return findTouchableNameRecursive(props.children);
129
129
  };
130
130
  exports.findTouchableName = findTouchableName;
131
- function findTouchableNameRecursive(node) {
132
- if (typeof node === 'string') {
133
- return node;
131
+ const findTouchableNameRecursive = (node) => {
132
+ var _a, _b;
133
+ if (!ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) {
134
+ return dfs(node, matchAny);
134
135
  }
136
+ const algorithm = ConfigurationHandler_1.ConfigurationHandler.getActionNameAlgorithm() === 'breadth-first'
137
+ ? bfs
138
+ : dfs;
139
+ const preference = ConfigurationHandler_1.ConfigurationHandler.getActionNamePreference();
140
+ if (preference === 'text') {
141
+ return (_a = algorithm(node, matchText)) !== null && _a !== void 0 ? _a : algorithm(node, matchAny);
142
+ }
143
+ if (preference === 'icon') {
144
+ return (_b = algorithm(node, matchIcon)) !== null && _b !== void 0 ? _b : algorithm(node, matchAny);
145
+ }
146
+ return algorithm(node, matchAny);
147
+ };
148
+ const dfs = (node, matcher) => {
135
149
  if (isReactNodeIterable(node)) {
136
150
  for (const child of node) {
137
- const result = findTouchableNameRecursive(child);
151
+ const result = dfs(child, matcher);
138
152
  if (result !== null)
139
153
  return result;
140
154
  }
155
+ return null;
141
156
  }
142
- if (React.isValidElement(node)) {
143
- if (isReactNativeImage(node)) {
144
- const uri = getUriFromSource(node.props.source);
145
- return uri ? 'Image Button: ' + uri : 'Image Button';
157
+ const match = matcher(node);
158
+ if (match)
159
+ return match;
160
+ if (React.isValidElement(node) && hasReactNodeChildren(node)) {
161
+ return dfs(node.props.children, matcher);
162
+ }
163
+ return null;
164
+ };
165
+ const bfs = (root, matcher) => {
166
+ const queue = [root];
167
+ while (queue.length > 0) {
168
+ const node = queue.shift();
169
+ if (isReactNodeIterable(node)) {
170
+ queue.push(...node);
171
+ continue;
146
172
  }
147
- if (isCustomIcon(node)) {
148
- return node.props.name;
173
+ const match = matcher(node);
174
+ if (match)
175
+ return match;
176
+ if (React.isValidElement(node) && hasReactNodeChildren(node)) {
177
+ queue.push(node.props.children);
149
178
  }
150
- if (hasReactNodeChildren(node))
151
- return findTouchableNameRecursive(node.props.children);
152
179
  }
153
180
  return null;
154
- }
181
+ };
182
+ const matchText = (node) => typeof node === 'string' ? node : null;
183
+ const matchImage = (node) => {
184
+ if (React.isValidElement(node) && isReactNativeImage(node)) {
185
+ const uri = getUriFromSource(node.props.source);
186
+ return uri ? `Image Button: ${uri}` : 'Image Button';
187
+ }
188
+ return null;
189
+ };
190
+ const matchCustomIcon = (node) => {
191
+ if (React.isValidElement(node) && isCustomIcon(node)) {
192
+ return node.props.name;
193
+ }
194
+ return null;
195
+ };
196
+ const matchAny = (node) => { var _a, _b; return (_b = (_a = matchText(node)) !== null && _a !== void 0 ? _a : matchImage(node)) !== null && _b !== void 0 ? _b : matchCustomIcon(node); };
197
+ const matchIcon = (node) => { var _a; return (_a = matchImage(node)) !== null && _a !== void 0 ? _a : matchCustomIcon(node); };
155
198
  function getUriFromSource(source) {
156
199
  if (typeof source === 'object' &&
157
200
  'uri' in source &&
@@ -161,7 +204,9 @@ function getUriFromSource(source) {
161
204
  return null;
162
205
  }
163
206
  const isReactNodeIterable = (node) => typeof node === 'object' && node !== null && Symbol.iterator in node;
164
- const isReactNativeImage = (element) => element.type === ReactNative.Image;
207
+ const isReactNativeImage = (element) => element.type === ReactNative.Image ||
208
+ element.type.displayName ===
209
+ 'CssInterop.Image';
165
210
  const isCustomIcon = (element) => typeof element.type === 'function' &&
166
211
  element.type.name === 'Icon' &&
167
212
  typeof element.props === 'object' &&
@@ -354,4 +354,7 @@ exports.Dynatrace = {
354
354
  sendHttpRequestEvent: (httpRequestEvent) => {
355
355
  Dynatrace_1.Dynatrace.sendHttpRequestEvent(httpRequestEvent);
356
356
  },
357
+ generateTraceContext(traceparent, tracestate) {
358
+ return Dynatrace_1.Dynatrace.generateTraceContext(traceparent, tracestate);
359
+ },
357
360
  };
@@ -1,12 +1,10 @@
1
1
  "use strict";
2
+ var _a;
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.DynatraceNative = void 0;
4
5
  const react_native_1 = require("react-native");
5
6
  const isTurboModuleEnabled = globalThis.__turboModuleProxy != null;
6
- exports.DynatraceNative = isTurboModuleEnabled
7
- ? react_native_1.TurboModuleRegistry.get('DynatraceBridge') !== undefined
8
- ? react_native_1.TurboModuleRegistry.get('DynatraceBridge')
9
- : {}
10
- : react_native_1.NativeModules.DynatraceBridge !== undefined
11
- ? react_native_1.NativeModules.DynatraceBridge
12
- : {};
7
+ const turboModule = isTurboModuleEnabled
8
+ ? react_native_1.TurboModuleRegistry.get('DynatraceBridge')
9
+ : null;
10
+ exports.DynatraceNative = (_a = turboModule !== null && turboModule !== void 0 ? turboModule : react_native_1.NativeModules.DynatraceBridge) !== null && _a !== void 0 ? _a : {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Configuration = void 0;
4
4
  const LogLevelUtil_1 = require("../logging/LogLevelUtil");
5
5
  class Configuration {
6
- constructor(beaconUrl, applicationId, reportCrash, errorHandler, reportFatalErrorAsCrash, logLevel, lifecycleUpdate, userOptIn, actionNamePrivacy, bundleName, bundleVersion) {
6
+ constructor(beaconUrl, applicationId, reportCrash, errorHandler, reportFatalErrorAsCrash, logLevel, lifecycleUpdate, userOptIn, actionNamePrivacy, actionNamePreference, actionNameAlgorithm, bundleName, bundleVersion) {
7
7
  this.beaconUrl = beaconUrl;
8
8
  this.applicationId = applicationId;
9
9
  this.reportCrash = reportCrash;
@@ -13,6 +13,8 @@ class Configuration {
13
13
  this.lifecycleUpdate = lifecycleUpdate;
14
14
  this.userOptIn = userOptIn;
15
15
  this.actionNamePrivacy = actionNamePrivacy;
16
+ this.actionNamePreference = actionNamePreference;
17
+ this.actionNameAlgorithm = actionNameAlgorithm;
16
18
  this.bundleName = bundleName;
17
19
  this.bundleVersion = bundleVersion;
18
20
  }
@@ -29,6 +31,8 @@ class Configuration {
29
31
  `, lifecycleUpdate: ${this.lifecycleUpdate}` +
30
32
  (isAutoStart ? '' : `, userOptIn: ${this.userOptIn}`) +
31
33
  `, actionNamePrivacy: ${this.actionNamePrivacy}` +
34
+ `, actionNamePreference: ${this.actionNamePreference}` +
35
+ `, actionNameAlgorithm: ${this.actionNameAlgorithm}` +
32
36
  `, logLevel: ${(0, LogLevelUtil_1.LogLevelToString)(this.logLevel)}`;
33
37
  if (this.bundleName !== undefined) {
34
38
  configurationString += `, bundleName: ${this.bundleName}`;
@@ -18,6 +18,8 @@ class ConfigurationBuilder {
18
18
  this.lifecycleUpdate = preset.getLifecycleUpdate();
19
19
  this.userOptIn = ConfigurationDefaults_1.DEFAULT_USER_OPT_IN;
20
20
  this.actionNamePrivacy = preset.getActionNamePrivacy();
21
+ this.actionNamePreference = preset.getActionNamePreference();
22
+ this.actionNameAlgorithm = preset.getActionNameAlgorithm();
21
23
  this.bundleName = preset.getBundleName();
22
24
  this.bundleVersion = preset.getBundleVersion();
23
25
  this.autoStartup = preset.isAutoStartupEnabled();
@@ -50,6 +52,14 @@ class ConfigurationBuilder {
50
52
  this.actionNamePrivacy = actionNamePrivacy;
51
53
  return this;
52
54
  }
55
+ withActionNamePreference(actionNamePreference) {
56
+ this.actionNamePreference = actionNamePreference;
57
+ return this;
58
+ }
59
+ withActionNameAlgorithm(actionNameAlgorithm) {
60
+ this.actionNameAlgorithm = actionNameAlgorithm;
61
+ return this;
62
+ }
53
63
  withBundleName(bundleName) {
54
64
  this.bundleName = bundleName;
55
65
  return this;
@@ -66,7 +76,7 @@ class ConfigurationBuilder {
66
76
  throw new Error('applicationId configuration property is empty. ' +
67
77
  'This configuration is not possible! Please use a proper application ID.');
68
78
  }
69
- return new Configuration_1.Configuration(this.beaconUrl, this.applicationId, this.reportCrash, this.errorHandler, this.reportFatalErrorAsCrash, this.logLevel, this.lifecycleUpdate, this.userOptIn, this.actionNamePrivacy, this.bundleName, this.bundleVersion);
79
+ return new Configuration_1.Configuration(this.beaconUrl, this.applicationId, this.reportCrash, this.errorHandler, this.reportFatalErrorAsCrash, this.logLevel, this.lifecycleUpdate, this.userOptIn, this.actionNamePrivacy, this.actionNamePreference, this.actionNameAlgorithm, this.bundleName, this.bundleVersion);
70
80
  }
71
81
  }
72
82
  exports.ConfigurationBuilder = ConfigurationBuilder;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_ACTION_NAME_PRIVACY = exports.DEFAULT_USER_OPT_IN = exports.DEFAULT_LOGLEVEL = exports.DEFAULT_FATAL_AS_CRASH = exports.DEFAULT_ERROR_HANDLER = exports.DEFAULT_REPORT_CRASH = exports.DEFAULT_LIFECYCLE_UPDATE = void 0;
3
+ exports.DEFAULT_ACTION_NAME_ALGORITHM = exports.DEFAULT_ACTION_NAME_PREFERENCE = exports.DEFAULT_ACTION_NAME_PRIVACY = exports.DEFAULT_USER_OPT_IN = exports.DEFAULT_LOGLEVEL = exports.DEFAULT_FATAL_AS_CRASH = exports.DEFAULT_ERROR_HANDLER = exports.DEFAULT_REPORT_CRASH = exports.DEFAULT_LIFECYCLE_UPDATE = void 0;
4
4
  const LogLevel_1 = require("../logging/LogLevel");
5
5
  exports.DEFAULT_LIFECYCLE_UPDATE = false;
6
6
  exports.DEFAULT_REPORT_CRASH = true;
@@ -9,3 +9,5 @@ exports.DEFAULT_FATAL_AS_CRASH = true;
9
9
  exports.DEFAULT_LOGLEVEL = LogLevel_1.LogLevel.Info;
10
10
  exports.DEFAULT_USER_OPT_IN = false;
11
11
  exports.DEFAULT_ACTION_NAME_PRIVACY = false;
12
+ exports.DEFAULT_ACTION_NAME_PREFERENCE = 'any';
13
+ exports.DEFAULT_ACTION_NAME_ALGORITHM = 'depth-first';
@@ -5,6 +5,43 @@ const RuntimeConfigurationObserver_1 = require("../../next/configuration/Runtime
5
5
  const LogLevel_1 = require("../logging/LogLevel");
6
6
  let _configuration;
7
7
  let _uiiEnabledLastKnownGood = undefined;
8
+ const getRuntimeConfiguration = () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.getCurrentRuntimeConfiguration();
9
+ const getBaseThirdGenDecision = () => {
10
+ if (!RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.isInitiated()) {
11
+ return {
12
+ allowed: true,
13
+ reason: 'runtime_config_unavailable',
14
+ };
15
+ }
16
+ const runtimeConfiguration = getRuntimeConfiguration();
17
+ if (!runtimeConfiguration['3rd_gen_enabled']) {
18
+ return {
19
+ allowed: false,
20
+ reason: 'third_gen_disabled',
21
+ };
22
+ }
23
+ if (runtimeConfiguration.data_collection_level === 0) {
24
+ return {
25
+ allowed: false,
26
+ reason: 'data_collection_off',
27
+ };
28
+ }
29
+ if (!runtimeConfiguration.agent_status) {
30
+ return {
31
+ allowed: false,
32
+ reason: 'agent_inactive',
33
+ };
34
+ }
35
+ if (runtimeConfiguration.traffic_control) {
36
+ return {
37
+ allowed: false,
38
+ reason: 'traffic_control_active',
39
+ };
40
+ }
41
+ return {
42
+ allowed: true,
43
+ };
44
+ };
8
45
  exports.ConfigurationHandler = {
9
46
  setConfiguration(configuration) {
10
47
  _configuration = configuration;
@@ -19,7 +56,34 @@ exports.ConfigurationHandler = {
19
56
  _configuration.logLevel === LogLevel_1.LogLevel.Debug,
20
57
  isLifecycleUpdateEnabled: () => _configuration.lifecycleUpdate,
21
58
  isActionNamePrivacyEnabled: () => _configuration.actionNamePrivacy,
59
+ getActionNamePreference: () => _configuration.actionNamePreference,
60
+ getActionNameAlgorithm: () => _configuration.actionNameAlgorithm,
22
61
  isGrailEnabled: () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.getCurrentRuntimeConfiguration()['3rd_gen_enabled'],
62
+ getThirdGenDataReportingDecision: () => getBaseThirdGenDecision(),
63
+ getThirdGenHeaderPropagationDecision: () => getBaseThirdGenDecision(),
64
+ getThirdGenCrashReportingDecision: () => {
65
+ const decision = getBaseThirdGenDecision();
66
+ if (!decision.allowed) {
67
+ return decision;
68
+ }
69
+ if (decision.reason === 'runtime_config_unavailable') {
70
+ return decision;
71
+ }
72
+ if (!getRuntimeConfiguration().crash_reporting) {
73
+ return {
74
+ allowed: false,
75
+ reason: 'crash_reporting_disabled',
76
+ };
77
+ }
78
+ return {
79
+ allowed: true,
80
+ };
81
+ },
82
+ getInstanceId: () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.getCurrentRuntimeConfiguration()['instance_id'],
83
+ getSessionId: () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.getCurrentRuntimeConfiguration()['session_id'],
84
+ getApplicationId: () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.getCurrentRuntimeConfiguration()['application_id'],
85
+ getTracestateKeyPrefix: () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.getCurrentRuntimeConfiguration()['tracestate_key_prefix'],
86
+ getTraceContextEnabled: () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.getCurrentRuntimeConfiguration()['trace_context_enabled'],
23
87
  isUserInteractionEnabled: () => {
24
88
  const isRuntimeConfigInitiated = RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.isInitiated();
25
89
  if (isRuntimeConfigInitiated) {
@@ -21,6 +21,12 @@ class ConfigurationPreset {
21
21
  getActionNamePrivacy() {
22
22
  return ConfigurationDefaults_1.DEFAULT_ACTION_NAME_PRIVACY;
23
23
  }
24
+ getActionNamePreference() {
25
+ return ConfigurationDefaults_1.DEFAULT_ACTION_NAME_PREFERENCE;
26
+ }
27
+ getActionNameAlgorithm() {
28
+ return ConfigurationDefaults_1.DEFAULT_ACTION_NAME_ALGORITHM;
29
+ }
24
30
  getBundleName() {
25
31
  return undefined;
26
32
  }
@@ -5,7 +5,7 @@ const LogLevelUtil_1 = require("../logging/LogLevelUtil");
5
5
  const ConfigurationDefaults_1 = require("./ConfigurationDefaults");
6
6
  const ConfigurationPreset_1 = require("./ConfigurationPreset");
7
7
  class ManualStartupConfiguration {
8
- constructor(beaconUrl, applicationId, reportCrash, logLevel, lifecycleUpdate, userOptIn, actionNamePrivacy, bundleName, bundleVersion) {
8
+ constructor(beaconUrl, applicationId, reportCrash, logLevel, lifecycleUpdate, userOptIn, actionNamePrivacy, actionNamePreference, actionNameAlgorithm, bundleName, bundleVersion) {
9
9
  this.reportCrash = ConfigurationDefaults_1.DEFAULT_REPORT_CRASH;
10
10
  this.userOptIn = ConfigurationDefaults_1.DEFAULT_USER_OPT_IN;
11
11
  if (!applicationId || !beaconUrl) {
@@ -19,6 +19,8 @@ class ManualStartupConfiguration {
19
19
  this.reportFatalErrorAsCrash = preset.isReportFatalErrorAsCrash();
20
20
  this.lifecycleUpdate = preset.getLifecycleUpdate();
21
21
  this.actionNamePrivacy = preset.getActionNamePrivacy();
22
+ this.actionNamePreference = preset.getActionNamePreference();
23
+ this.actionNameAlgorithm = preset.getActionNameAlgorithm();
22
24
  this.bundleName = preset.getBundleName();
23
25
  if (reportCrash != null) {
24
26
  this.reportCrash = reportCrash;
@@ -35,6 +37,12 @@ class ManualStartupConfiguration {
35
37
  if (actionNamePrivacy != null) {
36
38
  this.actionNamePrivacy = actionNamePrivacy;
37
39
  }
40
+ if (actionNamePreference != null) {
41
+ this.actionNamePreference = actionNamePreference;
42
+ }
43
+ if (actionNameAlgorithm != null) {
44
+ this.actionNameAlgorithm = actionNameAlgorithm;
45
+ }
38
46
  if (bundleName != null) {
39
47
  this.bundleName = bundleName;
40
48
  }
@@ -11,11 +11,7 @@ const IUserInteractionEvent_1 = require("./IUserInteractionEvent");
11
11
  const ConfigurationHandler_1 = require("../../../lib/core/configuration/ConfigurationHandler");
12
12
  const RuntimeConfigurationObserver_1 = require("../../../lib/next/configuration/RuntimeConfigurationObserver");
13
13
  const TouchMetaResolver_1 = require("./TouchMetaResolver");
14
- class TimestampProvider {
15
- constructor() {
16
- this.getCurrentTimestamp = () => Date.now();
17
- }
18
- }
14
+ const TimestampProvider_1 = require("../../next/provider/TimestampProvider");
19
15
  const logger = new ConsoleLogger_1.ConsoleLogger('DyntraceUserInteraction');
20
16
  function isUiDebugEnabled() {
21
17
  return (globalThis
@@ -213,7 +209,7 @@ function findHostInfoHit(event, cfg) {
213
209
  };
214
210
  }
215
211
  function makeSid() {
216
- const t = Date.now().toString(36);
212
+ const t = TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp().toString(36);
217
213
  const r = Math.random().toString(36).slice(2, 6);
218
214
  return `tch_${t}_${r}`;
219
215
  }
@@ -417,7 +413,10 @@ function useTouchManager(cfg, log) {
417
413
  touchMasked: t.masked,
418
414
  pressPath: p.path,
419
415
  pressElementName: p.elementName,
420
- meta: { phase: 'press', ts: Date.now() },
416
+ meta: {
417
+ phase: 'press',
418
+ ts: TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp(),
419
+ },
421
420
  pos: pos ? { x: pos.x, y: pos.y } : undefined,
422
421
  reason: t.reason,
423
422
  sessionId: sidRef.current || undefined,
@@ -428,7 +427,10 @@ function useTouchManager(cfg, log) {
428
427
  out = buildUiEventShape({
429
428
  pressPath: p.path,
430
429
  pressElementName: p.elementName,
431
- meta: { phase: 'press', ts: Date.now() },
430
+ meta: {
431
+ phase: 'press',
432
+ ts: TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp(),
433
+ },
432
434
  pos: p.pos ? { x: p.pos.x, y: p.pos.y } : undefined,
433
435
  sessionId: sidRef.current || undefined,
434
436
  });
@@ -438,7 +440,10 @@ function useTouchManager(cfg, log) {
438
440
  touchPath: t.path,
439
441
  touchElementName: t.elementName || undefined,
440
442
  touchMasked: t.masked,
441
- meta: { phase: 'touch', ts: Date.now() },
443
+ meta: {
444
+ phase: 'touch',
445
+ ts: TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp(),
446
+ },
442
447
  pos: t.pos ? { x: t.pos.x, y: t.pos.y } : undefined,
443
448
  reason: t.reason,
444
449
  sessionId: sidRef.current || undefined,
@@ -515,7 +520,7 @@ function useTouchManager(cfg, log) {
515
520
  touchMasked: !!hit.isMasked,
516
521
  meta: {
517
522
  phase: phase === 'cancel' ? 'touch-cancel' : 'touch',
518
- ts: Date.now(),
523
+ ts: TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp(),
519
524
  },
520
525
  pos: pos ? { x: pos.x, y: pos.y } : undefined,
521
526
  reason: phaseReason(phase),
@@ -541,7 +546,8 @@ function useTouchManager(cfg, log) {
541
546
  if (!(hit === null || hit === void 0 ? void 0 : hit.path)) {
542
547
  clearAll();
543
548
  sidRef.current = makeSid();
544
- startTsRef.current = Date.now();
549
+ startTsRef.current =
550
+ TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp();
545
551
  startXRef.current = Number(ne === null || ne === void 0 ? void 0 : ne.pageX) || 0;
546
552
  startYRef.current = Number(ne === null || ne === void 0 ? void 0 : ne.pageY) || 0;
547
553
  movedRef.current = false;
@@ -550,7 +556,10 @@ function useTouchManager(cfg, log) {
550
556
  const pos = makePos(ne, (_c = (_b = cfg.click) === null || _b === void 0 ? void 0 : _b.capturePosition) !== null && _c !== void 0 ? _c : 'none');
551
557
  const out = buildUiEventShape({
552
558
  touchPath: startPathRef.current,
553
- meta: { phase: 'touch-start', ts: Date.now() },
559
+ meta: {
560
+ phase: 'touch-start',
561
+ ts: TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp(),
562
+ },
554
563
  pos: pos ? { x: pos.x, y: pos.y } : undefined,
555
564
  sessionId: sidRef.current || undefined,
556
565
  });
@@ -561,7 +570,7 @@ function useTouchManager(cfg, log) {
561
570
  clearAll();
562
571
  startPathRef.current = hit.path;
563
572
  sidRef.current = makeSid();
564
- startTsRef.current = Date.now();
573
+ startTsRef.current = TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp();
565
574
  startXRef.current = Number(ne === null || ne === void 0 ? void 0 : ne.pageX) || 0;
566
575
  startYRef.current = Number(ne === null || ne === void 0 ? void 0 : ne.pageY) || 0;
567
576
  movedRef.current = false;
@@ -571,7 +580,10 @@ function useTouchManager(cfg, log) {
571
580
  touchPath: hit.path,
572
581
  touchElementName: hit.element || undefined,
573
582
  touchMasked: !!hit.isMasked,
574
- meta: { phase: 'touch-start', ts: Date.now() },
583
+ meta: {
584
+ phase: 'touch-start',
585
+ ts: TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp(),
586
+ },
575
587
  pos: pos ? { x: pos.x, y: pos.y } : undefined,
576
588
  sessionId: sidRef.current || undefined,
577
589
  name_origin: hit.name_origin,
@@ -606,7 +618,7 @@ function useTouchManager(cfg, log) {
606
618
  }
607
619
  const pos = makePos(ne, (_c = (_b = cfg.click) === null || _b === void 0 ? void 0 : _b.capturePosition) !== null && _c !== void 0 ? _c : 'none');
608
620
  const hitRaw = resolveTouchHit(ne === null || ne === void 0 ? void 0 : ne.target, e);
609
- const now = Date.now();
621
+ const now = TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp();
610
622
  const lifted = maybeLiftTouchHit(hitRaw);
611
623
  const usePath = lifted.usePath;
612
624
  const useEl = lifted.useElement || '';
@@ -651,7 +663,7 @@ function useTouchManager(cfg, log) {
651
663
  var _a, _b, _c;
652
664
  if (!((_a = cfg.touch) === null || _a === void 0 ? void 0 : _a.enabled))
653
665
  return;
654
- const now = Date.now();
666
+ const now = TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp();
655
667
  uiDebugLog('registerPress', {
656
668
  path: info.path,
657
669
  elementName: info.elementName,
@@ -699,7 +711,7 @@ function TouchCapture({ children, cfg, mgr, }) {
699
711
  const last = getDtLastTouch();
700
712
  const onStart = React.useCallback((e) => {
701
713
  var _a, _b;
702
- last.ts = Date.now();
714
+ last.ts = TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp();
703
715
  last.x = Number((_a = e === null || e === void 0 ? void 0 : e.nativeEvent) === null || _a === void 0 ? void 0 : _a.pageX) || 0;
704
716
  last.y = Number((_b = e === null || e === void 0 ? void 0 : e.nativeEvent) === null || _b === void 0 ? void 0 : _b.pageY) || 0;
705
717
  return mgr === null || mgr === void 0 ? void 0 : mgr.onStart(e);
@@ -751,7 +763,7 @@ function AnalyticsRoot({ name = 'App', label, log, prefix, config, children, })
751
763
  }
752
764
  const phase = ((_b = (_a = e === null || e === void 0 ? void 0 : e.ui_element) === null || _a === void 0 ? void 0 : _a.meta) === null || _b === void 0 ? void 0 : _b.phase) || '';
753
765
  const id = ((_c = e === null || e === void 0 ? void 0 : e.ui_element) === null || _c === void 0 ? void 0 : _c.id) || '';
754
- const now = Date.now();
766
+ const now = TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp();
755
767
  if (phase === 'touch' &&
756
768
  LAST_PRESS_ID &&
757
769
  id &&
@@ -777,7 +789,7 @@ function AnalyticsRoot({ name = 'App', label, log, prefix, config, children, })
777
789
  LAST_PRESS_ID = id;
778
790
  LAST_PRESS_TS = now;
779
791
  }
780
- const eventTimestamp = new EventTimestamp_1.EventTimestamp(new TimestampProvider());
792
+ const eventTimestamp = new EventTimestamp_1.EventTimestamp(TimestampProvider_1.defaultTimestampProvider);
781
793
  const produceEvent = _an_flat(e);
782
794
  const event = Object.assign(Object.assign({}, produceEvent), eventTimestamp.getEventTimeInfo());
783
795
  EventPipeline_1.EventPipeline.insertEvent(event);
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Dynatrace = 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 EventCreator_1 = require("./events/EventCreator");
7
8
  const EventPipeline_1 = require("./events/EventPipeline");
8
9
  const EventTimestamp_1 = require("./events/EventTimestamp");
@@ -13,6 +14,15 @@ const SessionPropertyEventData_1 = require("./events/SessionPropertyEventData");
13
14
  const ExceptionEventData_1 = require("./events/ExceptionEventData");
14
15
  const HttpRequestEventData_1 = require("./events/HttpRequestEventData");
15
16
  const DynatraceArgValidators_1 = require("./DynatraceArgValidators");
17
+ const TraceContextUtils_1 = require("./util/TraceContextUtils");
18
+ const DECISION_REASON_TEXT = {
19
+ third_gen_disabled: '3rd generation RUM is disabled',
20
+ runtime_config_unavailable: 'Runtime configuration is not yet available',
21
+ data_collection_off: 'Data collection is disabled',
22
+ agent_inactive: 'Agent is inactive',
23
+ traffic_control_active: 'Traffic control is limiting data transmission',
24
+ crash_reporting_disabled: 'Crash reporting is disabled',
25
+ };
16
26
  class DynatraceImpl {
17
27
  constructor(timestampProvider) {
18
28
  this.timestampProvider = timestampProvider;
@@ -51,6 +61,14 @@ class DynatraceImpl {
51
61
  }
52
62
  reportCrash(crash, isApiReported, isFatal = true) {
53
63
  this.logger.debug(`reportCrash(${JSON.stringify(crash)}, ${isFatal})`);
64
+ const decision = ConfigurationHandler_1.ConfigurationHandler.getThirdGenCrashReportingDecision();
65
+ if (!decision.allowed) {
66
+ const reasonText = decision.reason
67
+ ? DECISION_REASON_TEXT[decision.reason]
68
+ : 'Unknown reason';
69
+ this.logger.debug(`3rd gen crash suppressed: ${reasonText}`);
70
+ return;
71
+ }
54
72
  const eventTimestamp = new EventTimestamp_1.EventTimestamp(this.timestampProvider);
55
73
  const event = Object.assign(Object.assign({}, (0, EventCreator_1.createCrashEvent)(crash.name, crash.message, crash.stack, isFatal)), eventTimestamp.getEventTimeInfo());
56
74
  if (isApiReported) {
@@ -123,5 +141,31 @@ class DynatraceImpl {
123
141
  EventPipeline_1.EventPipeline.insertEvent(sanitizedEvent);
124
142
  }
125
143
  }
144
+ generateTraceContext(existingTraceparent, existingTracestate) {
145
+ let traceparent = existingTraceparent;
146
+ let tracestate = existingTracestate;
147
+ if (!ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable()) {
148
+ this.logger.info(`generateTraceContext(${existingTraceparent}, ${existingTracestate}): React Native plugin has not been started yet! Trace context will not be generated!`);
149
+ return undefined;
150
+ }
151
+ this.logger.debug(`generateTraceContext(${existingTraceparent}, ${existingTracestate})`);
152
+ let parsedTraceparent = traceparent === undefined
153
+ ? undefined
154
+ : (0, TraceContextUtils_1.parseTraceparent)(traceparent);
155
+ if (parsedTraceparent === undefined) {
156
+ traceparent = (0, TraceContextUtils_1.generateTraceparentHeader)();
157
+ parsedTraceparent = (0, TraceContextUtils_1.parseTraceparent)(traceparent);
158
+ tracestate = undefined;
159
+ }
160
+ tracestate = (0, TraceContextUtils_1.generateTracestate)(parsedTraceparent.parentId, tracestate);
161
+ if (tracestate === undefined) {
162
+ this.logger.info(`generateTraceContext(${existingTraceparent}, ${existingTracestate}): Either trace context disabled or incomplete configuration! Trace context will not be generated!`);
163
+ return undefined;
164
+ }
165
+ return {
166
+ traceparent: traceparent,
167
+ tracestate,
168
+ };
169
+ }
126
170
  }
127
171
  exports.Dynatrace = new DynatraceImpl(TimestampProvider_1.defaultTimestampProvider);
@@ -4,5 +4,14 @@ exports.generateDefaultConfiguration = void 0;
4
4
  const generateDefaultConfiguration = () => ({
5
5
  '3rd_gen_enabled': true,
6
6
  touch_interaction_enabled: false,
7
+ instance_id: '',
8
+ session_id: '',
9
+ application_id: '',
10
+ tracestate_key_prefix: '',
11
+ trace_context_enabled: true,
12
+ data_collection_level: 1,
13
+ agent_status: true,
14
+ traffic_control: false,
15
+ crash_reporting: true,
7
16
  });
8
17
  exports.generateDefaultConfiguration = generateDefaultConfiguration;
@@ -31,10 +31,55 @@ class RuntimeConfigurationObserverImpl {
31
31
  const touchInteractionEnabled = typeof payload.touch_interaction_enabled === 'boolean'
32
32
  ? payload.touch_interaction_enabled
33
33
  : undefined;
34
- const normalized = Object.assign(Object.assign({}, (typeof thirdGenEnabled === 'boolean'
34
+ const traceContextEnabled = typeof payload.trace_context_enabled === 'boolean'
35
+ ? payload.trace_context_enabled
36
+ : undefined;
37
+ const dataCollectionLevel = payload.data_collection_level === 0 ||
38
+ payload.data_collection_level === 1 ||
39
+ payload.data_collection_level === 2
40
+ ? payload.data_collection_level
41
+ : undefined;
42
+ const agentStatus = typeof payload.agent_status === 'boolean'
43
+ ? payload.agent_status
44
+ : undefined;
45
+ const trafficControl = typeof payload.traffic_control === 'boolean'
46
+ ? payload.traffic_control
47
+ : undefined;
48
+ const crashReporting = typeof payload.crash_reporting === 'boolean'
49
+ ? payload.crash_reporting
50
+ : undefined;
51
+ const instanceId = typeof payload.instance_id === 'string'
52
+ ? payload.instance_id
53
+ : undefined;
54
+ const sessionId = typeof payload.session_id === 'string'
55
+ ? payload.session_id
56
+ : undefined;
57
+ const applicationId = typeof payload.application_id === 'string'
58
+ ? payload.application_id
59
+ : undefined;
60
+ const tracestateKeyPrefix = typeof payload.tracestate_key_prefix === 'string'
61
+ ? payload.tracestate_key_prefix
62
+ : 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'
35
64
  ? { '3rd_gen_enabled': thirdGenEnabled }
36
65
  : {})), (typeof touchInteractionEnabled === 'boolean'
37
66
  ? { touch_interaction_enabled: touchInteractionEnabled }
67
+ : {})), (typeof traceContextEnabled === 'boolean'
68
+ ? { trace_context_enabled: traceContextEnabled }
69
+ : {})), (typeof dataCollectionLevel === 'number'
70
+ ? { data_collection_level: dataCollectionLevel }
71
+ : {})), (typeof agentStatus === 'boolean'
72
+ ? { agent_status: agentStatus }
73
+ : {})), (typeof trafficControl === 'boolean'
74
+ ? { traffic_control: trafficControl }
75
+ : {})), (typeof crashReporting === 'boolean'
76
+ ? { crash_reporting: crashReporting }
77
+ : {})), (typeof instanceId === 'string'
78
+ ? { instance_id: instanceId }
79
+ : {})), (typeof sessionId === 'string' ? { session_id: sessionId } : {})), (typeof applicationId === 'string'
80
+ ? { application_id: applicationId }
81
+ : {})), (typeof tracestateKeyPrefix === 'string'
82
+ ? { tracestate_key_prefix: tracestateKeyPrefix }
38
83
  : {}));
39
84
  this.runtimeConfiguration = Object.assign(Object.assign({}, (0, INativeRuntimeConfiguration_1.generateDefaultConfiguration)()), normalized);
40
85
  this.observerIsInitiated = true;
@@ -50,6 +95,7 @@ class RuntimeConfigurationObserverImpl {
50
95
  return react_native_1.NativeModules.DynatraceBridge;
51
96
  }
52
97
  setupNativeEventEmitter() {
98
+ var _a;
53
99
  const bridgeModule = this.resolveBridgeModule();
54
100
  if (!bridgeModule) {
55
101
  return;
@@ -57,11 +103,9 @@ class RuntimeConfigurationObserverImpl {
57
103
  const iosModule = react_native_1.NativeModules.DynatraceBridge;
58
104
  const nativeEmitterModule = react_native_1.Platform.OS === 'ios' ? iosModule || bridgeModule : bridgeModule;
59
105
  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
- }
106
+ (_a = this.subscription) !== null && _a !== void 0 ? _a : (this.subscription = emitter.addListener(this.EMIT_CONFIGURATION, (data) => {
107
+ this.updateRuntimeConfiguration(data);
108
+ }));
65
109
  if (typeof bridgeModule.getCurrentConfiguration === 'function') {
66
110
  Promise.resolve(bridgeModule.getCurrentConfiguration())
67
111
  .then((data) => {