@dynatrace/react-native-plugin 2.307.1 → 2.311.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 (134) hide show
  1. package/README.md +13 -4
  2. package/android/build.gradle +3 -1
  3. package/android/src/main/java/com/dynatrace/android/agent/DynatraceAppStartModule.kt +128 -0
  4. package/android/src/main/java/com/dynatrace/android/agent/DynatraceInternalModule.kt +22 -0
  5. package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +411 -0
  6. package/android/src/main/java/com/dynatrace/android/agent/DynatraceReactPackage.kt +54 -0
  7. package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.kt +86 -0
  8. package/android/src/main/java/com/dynatrace/android/agent/model/AppStartMeasurement.kt +15 -0
  9. package/android/src/main/java/com/dynatrace/android/agent/model/AppStartMeasurementType.kt +18 -0
  10. package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +228 -0
  11. package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +258 -0
  12. package/files/plugin.gradle +1 -1
  13. package/index.js +10 -10
  14. package/instrumentation/DynatraceInstrumentation.js +1 -0
  15. package/{lib → instrumentation/jsx}/CreateElement.js +6 -5
  16. package/{lib/instrumentor/base → instrumentation/jsx}/ElementHelper.js +14 -12
  17. package/instrumentation/jsx/JsxDevRuntime.js +54 -0
  18. package/instrumentation/jsx/JsxRuntime.js +57 -0
  19. package/instrumentation/jsx/JsxRuntimeUtil.js +31 -0
  20. package/instrumentation/jsx/components/ClassComponent.js +49 -0
  21. package/instrumentation/jsx/components/ComponentUtil.js +33 -0
  22. package/instrumentation/jsx/components/FunctionalComponent.js +15 -0
  23. package/{lib/instrumentor/base → instrumentation/jsx/components}/Picker.js +1 -1
  24. package/{lib/instrumentor/base → instrumentation/jsx/components}/RefreshControl.js +1 -1
  25. package/{lib/instrumentor/base → instrumentation/jsx/components}/Switch.js +8 -8
  26. package/{lib/instrumentor/base → instrumentation/jsx/components}/Touchable.js +8 -8
  27. package/instrumentation/libs/community/Picker.InstrInfo.js +20 -0
  28. package/{lib → instrumentation/libs}/community/Picker.js +1 -1
  29. package/instrumentation/libs/community/gesture-handler/Touchables.InstrInfo.js +23 -0
  30. package/{lib → instrumentation/libs}/community/gesture-handler/Touchables.js +1 -1
  31. package/{lib → instrumentation/libs}/react-native/RefreshControl.InstrInfo.js +2 -2
  32. package/{lib → instrumentation/libs}/react-native/RefreshControl.js +5 -5
  33. package/{lib → instrumentation/libs}/react-native/Switch.InstrInfo.js +2 -2
  34. package/{lib → instrumentation/libs}/react-native/Switch.js +5 -5
  35. package/instrumentation/libs/react-native/Touchables.InstrInfo.js +25 -0
  36. package/{lib → instrumentation/libs}/react-native/Touchables.js +1 -1
  37. package/{lib → instrumentation/libs}/react-navigation/ReactNavigation.js +6 -5
  38. package/{lib/instrumentor → instrumentation}/model/Types.js +1 -14
  39. package/instrumentation/model/TypesUtil.js +50 -0
  40. package/ios/DynatraceRNBridge.h +10 -1
  41. package/ios/DynatraceRNBridge.mm +152 -1
  42. package/jsx-dev-runtime.js +1 -1
  43. package/jsx-runtime.js +1 -1
  44. package/lib/core/Application.js +20 -0
  45. package/lib/{instrumentor/base → core}/Dynatrace.js +72 -48
  46. package/lib/{instrumentor/base → core}/DynatraceAction.js +23 -22
  47. package/lib/core/DynatraceInternal.js +46 -0
  48. package/lib/{instrumentor/base → core}/DynatraceRootAction.js +5 -4
  49. package/lib/{instrumentor/base → core}/DynatraceWebRequestTiming.js +6 -5
  50. package/lib/{instrumentor/base → core}/ErrorHandler.js +6 -5
  51. package/lib/{instrumentor/base → core}/configuration/Configuration.js +1 -1
  52. package/lib/{instrumentor/base → core}/configuration/ConfigurationDefaults.js +1 -2
  53. package/lib/{instrumentor/base → core}/configuration/ConfigurationHandler.js +2 -2
  54. package/lib/{instrumentor/base → core}/configuration/ManualStartupConfiguration.js +1 -1
  55. package/lib/core/logging/ConsoleLogger.js +27 -0
  56. package/lib/core/logging/LogLevel.js +12 -0
  57. package/lib/dynatrace-transformer.js +1 -1
  58. package/lib/next/Dynatrace.js +88 -0
  59. package/lib/next/DynatraceSecondGenForwarder.js +35 -0
  60. package/lib/next/IDynatrace.js +2 -0
  61. package/lib/next/IDynatraceForwarder.js +2 -0
  62. package/lib/next/appstart/AppStartObserver.js +34 -0
  63. package/lib/next/appstart/AppStartType.js +38 -0
  64. package/lib/next/events/EventCreator.js +77 -0
  65. package/lib/next/events/EventPipeline.js +58 -0
  66. package/lib/next/events/EventTimestamp.js +27 -0
  67. package/lib/next/events/ViewInfoCreator.js +27 -0
  68. package/lib/next/events/modifier/BaseDataEventModifier.js +31 -0
  69. package/lib/next/events/modifier/EventLimitation.js +69 -0
  70. package/lib/next/events/modifier/EventModifierUtil.js +89 -0
  71. package/lib/next/events/modifier/IEventModifier.js +2 -0
  72. package/lib/next/events/modifier/ModifyEventValidation.js +189 -0
  73. package/lib/next/events/modifier/SendEventValidation.js +86 -0
  74. package/lib/next/events/modifier/ValueRestrictionModifier.js +56 -0
  75. package/lib/next/events/spec/EventFieldKeysEnum.js +2 -0
  76. package/lib/next/events/spec/EventSpecContstants.js +47 -0
  77. package/lib/next/events/spec/IAppStartEvent.js +2 -0
  78. package/lib/next/events/spec/ICrashEvent.js +2 -0
  79. package/lib/next/events/spec/IErrorCodeEvent.js +2 -0
  80. package/lib/next/events/spec/IErrorExceptionEvent.js +2 -0
  81. package/lib/next/events/spec/IReactNativeEvent.js +2 -0
  82. package/lib/next/events/spec/IRumEvent.js +2 -0
  83. package/lib/next/provider/ITimestampProvider.js +2 -0
  84. package/lib/next/provider/TimestampProvider.js +10 -0
  85. package/package.json +42 -33
  86. package/react-native-dynatrace.podspec +1 -1
  87. package/scripts/Android.js +10 -4
  88. package/scripts/PathsConstants.js +3 -1
  89. package/scripts/core/InstrumentCall.js +1 -0
  90. package/src/lib/{instrumentor/base → core}/interface/NativeDynatraceBridge.ts +8 -0
  91. package/typings/react-native-dynatrace.d.ts +73 -0
  92. package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.java +0 -366
  93. package/android/src/main/java/com/dynatrace/android/agent/DynatraceReactPackage.java +0 -67
  94. package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.java +0 -108
  95. package/android/src/main/java/com/dynatrace/android/agent/PrivateDTBridge.java +0 -28
  96. package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.java +0 -192
  97. package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.java +0 -194
  98. package/lib/community/Picker.InstrInfo.js +0 -20
  99. package/lib/community/gesture-handler/Touchables.InstrInfo.js +0 -56
  100. package/lib/instrumentor/DynatraceInstrumentation.js +0 -1
  101. package/lib/instrumentor/base/Application.js +0 -16
  102. package/lib/instrumentor/base/DynatraceInternal.js +0 -34
  103. package/lib/instrumentor/base/Logger.js +0 -16
  104. package/lib/instrumentor/base/model/LogLevel.js +0 -17
  105. package/lib/jsx-dev-runtime.js +0 -70
  106. package/lib/jsx-runtime.js +0 -69
  107. package/lib/react/Component.js +0 -90
  108. package/lib/react-native/Touchables.InstrInfo.js +0 -60
  109. /package/{lib/instrumentor/base/interface → instrumentation/jsx}/IDynatraceProperties.js +0 -0
  110. /package/{lib → instrumentation/libs}/community/gesture-handler/index.js +0 -0
  111. /package/{lib → instrumentation/libs}/gesture-handler.js +0 -0
  112. /package/{lib → instrumentation/libs}/react-native/index.js +0 -0
  113. /package/{lib → instrumentation/libs}/react-native.js +0 -0
  114. /package/{lib/instrumentor → instrumentation}/model/Reference.js +0 -0
  115. /package/{lib/instrumentor → instrumentation}/parser/Babel.js +0 -0
  116. /package/lib/{instrumentor/base → core}/DynatraceBridge.js +0 -0
  117. /package/lib/{instrumentor/base → core}/NullAction.js +0 -0
  118. /package/lib/{instrumentor/base → core}/NullRootAction.js +0 -0
  119. /package/lib/{instrumentor/base → core}/NullWebRequestTiming.js +0 -0
  120. /package/lib/{instrumentor/base → core}/UserPrivacyOptions.js +0 -0
  121. /package/lib/{instrumentor/base → core}/configuration/ConfigurationBuilder.js +0 -0
  122. /package/lib/{instrumentor/base → core}/configuration/ConfigurationPreset.js +0 -0
  123. /package/lib/{instrumentor/base → core}/configuration/IConfiguration.js +0 -0
  124. /package/lib/{instrumentor/base → core}/interface/IDynatrace.js +0 -0
  125. /package/lib/{instrumentor/base → core}/interface/IDynatraceAction.js +0 -0
  126. /package/lib/{instrumentor/base → core}/interface/IDynatraceInternal.js +0 -0
  127. /package/lib/{instrumentor/base → core}/interface/IDynatraceRootAction.js +0 -0
  128. /package/lib/{instrumentor/base → core}/interface/IWebRequestTiming.js +0 -0
  129. /package/lib/{instrumentor/base → core}/interface/NativeDynatraceBridge.js +0 -0
  130. /package/lib/{instrumentor/base/interface → core/logging}/ILogger.js +0 -0
  131. /package/lib/{instrumentor/base → core}/model/DataCollectionLevel.js +0 -0
  132. /package/lib/{instrumentor/base → core}/model/Json.js +0 -0
  133. /package/lib/{instrumentor/base → core}/model/Platform.js +0 -0
  134. /package/lib/{instrumentor/base → core}/util/StringUtils.js +0 -0
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAppStartEvent = exports.createErrorEvent = exports.createErrorCodeEvent = exports.createCrashEvent = void 0;
4
+ const AppStartType_1 = require("../appstart/AppStartType");
5
+ const createCrashEvent = (type, message, stacktrace, isFatal) => {
6
+ const event = {
7
+ 'characteristics.has_crash': true,
8
+ 'characteristics.has_error': true,
9
+ 'error.is_fatal': isFatal,
10
+ };
11
+ if (type != null) {
12
+ event["exception.type"] = type;
13
+ }
14
+ if (message != null) {
15
+ event["exception.message"] = message;
16
+ }
17
+ if (stacktrace != null) {
18
+ event["exception.stack_trace"] = stacktrace;
19
+ }
20
+ return event;
21
+ };
22
+ exports.createCrashEvent = createCrashEvent;
23
+ const createErrorCodeEvent = (errorName, errorCode) => {
24
+ const event = {
25
+ 'characteristics.has_error': true,
26
+ 'error.is_fatal': false,
27
+ };
28
+ if (errorName != null) {
29
+ event["name"] = errorName;
30
+ }
31
+ if (errorCode != null) {
32
+ event["error.code"] = errorCode;
33
+ }
34
+ return event;
35
+ };
36
+ exports.createErrorCodeEvent = createErrorCodeEvent;
37
+ const createErrorEvent = (type, message, stacktrace) => {
38
+ const event = {
39
+ 'characteristics.has_error': true,
40
+ 'characteristics.has_exception': true,
41
+ 'error.is_fatal': false,
42
+ };
43
+ if (type != null) {
44
+ event["exception.type"] = type;
45
+ }
46
+ if (message != null) {
47
+ event["exception.message"] = message;
48
+ }
49
+ if (stacktrace != null) {
50
+ event["exception.stack_trace"] = stacktrace;
51
+ }
52
+ return event;
53
+ };
54
+ exports.createErrorEvent = createErrorEvent;
55
+ const createAppStartEvent = (appStartMeasurements) => {
56
+ const event = {
57
+ 'characteristics.is_app_start': true,
58
+ };
59
+ let timings = [];
60
+ for (const { type, key } of AppStartType_1.AppStartTypeKeyMapping) {
61
+ if (appStartMeasurements[type] !== undefined) {
62
+ event[key] = appStartMeasurements[type];
63
+ timings.push(appStartMeasurements[type]);
64
+ }
65
+ }
66
+ timings = timings.sort((a, b) => a - b);
67
+ if (timings.length > 0) {
68
+ event["start_time"] = timings[0];
69
+ event["duration"] =
70
+ timings[timings.length - 1] - timings[0];
71
+ }
72
+ else {
73
+ return null;
74
+ }
75
+ return event;
76
+ };
77
+ exports.createAppStartEvent = createAppStartEvent;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventPipeline = void 0;
4
+ const DynatraceBridge_1 = require("../../core/DynatraceBridge");
5
+ const ConsoleLogger_1 = require("../../core/logging/ConsoleLogger");
6
+ const BaseDataEventModifier_1 = require("./modifier/BaseDataEventModifier");
7
+ const ValueRestrictionModifier_1 = require("./modifier/ValueRestrictionModifier");
8
+ const ModifyEventValidation_1 = require("./modifier/ModifyEventValidation");
9
+ const ViewInfoCreator_1 = require("./ViewInfoCreator");
10
+ class EventPipelineImpl {
11
+ constructor() {
12
+ this.customEventModifierChain = new ModifyEventValidation_1.ModifyEventValidation();
13
+ this.logger = new ConsoleLogger_1.ConsoleLogger('EventPipeline');
14
+ }
15
+ getEventModifierChain() {
16
+ return [
17
+ new BaseDataEventModifier_1.BaseDataEventModifier(this.viewInfo),
18
+ this.customEventModifierChain,
19
+ ValueRestrictionModifier_1.ValueRestrictionModifier,
20
+ ];
21
+ }
22
+ insertEvent(event, context) {
23
+ this.logger.debug(`insertEvent(${JSON.stringify(event)})`);
24
+ this.getEventModifierChain().forEach((modifier) => {
25
+ try {
26
+ event = modifier.modifyEvent(event, context);
27
+ }
28
+ catch (error) {
29
+ if (event != null) {
30
+ event["dt.rum.api.has_enrich_exception"] =
31
+ true;
32
+ }
33
+ }
34
+ });
35
+ if (event != null) {
36
+ this.logger.debug(`forwardEvent(${JSON.stringify(event)})`);
37
+ DynatraceBridge_1.DynatraceNative.forwardEvent(event);
38
+ }
39
+ }
40
+ addEventModifier(eventModifier) {
41
+ this.logger.debug('addEventModifier()');
42
+ return this.customEventModifierChain.addEventModifier(eventModifier);
43
+ }
44
+ removeEventModifier(eventModifier) {
45
+ this.logger.debug('removeEventModifier()');
46
+ return this.customEventModifierChain.removeEventModifier(eventModifier);
47
+ }
48
+ generateViewData(name) {
49
+ this.logger.debug(`generateViewData(${name})`);
50
+ if (name != null) {
51
+ this.viewInfo = (0, ViewInfoCreator_1.createViewInfo)(name);
52
+ }
53
+ }
54
+ releaseViewData() {
55
+ this.viewInfo = undefined;
56
+ }
57
+ }
58
+ exports.EventPipeline = new EventPipelineImpl();
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventTimestamp = void 0;
4
+ const ConsoleLogger_1 = require("../../core/logging/ConsoleLogger");
5
+ class EventTimestamp {
6
+ constructor(timestampProvider) {
7
+ this.duration = 0;
8
+ this.timestampProvider = timestampProvider;
9
+ this.startTimestamp = timestampProvider.getCurrentTimestamp();
10
+ this.logger = new ConsoleLogger_1.ConsoleLogger('EventTimestamp');
11
+ }
12
+ getEventTimeInfo() {
13
+ return {
14
+ duration: this.duration,
15
+ start_time: this.startTimestamp,
16
+ };
17
+ }
18
+ setEndTimestamp(endTimestamp = this.timestampProvider.getCurrentTimestamp()) {
19
+ if (endTimestamp > this.startTimestamp) {
20
+ this.duration = endTimestamp - this.startTimestamp;
21
+ }
22
+ else {
23
+ this.logger.debug(`End timestamp (${endTimestamp}) can't be before start timestamp (${this.startTimestamp})!`);
24
+ }
25
+ }
26
+ }
27
+ exports.EventTimestamp = EventTimestamp;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createViewInfo = void 0;
4
+ const VIEW_ID_LENGTH = 16;
5
+ const MAX_HEXADECIMAL_VALUE = 16;
6
+ const ASCII_CODE_NUMERIC_0 = 48;
7
+ const ASCII_CODE_A = 65;
8
+ const NUMERICAL_CHARACTER_COUNT = 10;
9
+ const OFFSET_A = ASCII_CODE_A - NUMERICAL_CHARACTER_COUNT;
10
+ const createViewInfo = (name) => ({
11
+ ["view.id"]: createRandomHexString(VIEW_ID_LENGTH),
12
+ ["view.name"]: name,
13
+ });
14
+ exports.createViewInfo = createViewInfo;
15
+ const createRandomHexString = (length) => createRandomString(length, MAX_HEXADECIMAL_VALUE);
16
+ const createRandomString = (length, maxRange) => {
17
+ const resultArray = Array(length);
18
+ for (let i = 0; i < length; i++) {
19
+ const randomInRange = Math.floor(Math.random() * maxRange);
20
+ const character = String.fromCharCode(randomInRange +
21
+ (randomInRange < NUMERICAL_CHARACTER_COUNT
22
+ ? ASCII_CODE_NUMERIC_0
23
+ : OFFSET_A));
24
+ resultArray.push(character);
25
+ }
26
+ return resultArray.join('');
27
+ };
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseDataEventModifier = void 0;
4
+ const ConfigurationHandler_1 = require("../../../core/configuration/ConfigurationHandler");
5
+ const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger");
6
+ class BaseDataEventModifier {
7
+ constructor(viewInfo) {
8
+ this.viewInfo = viewInfo;
9
+ this.logger = new ConsoleLogger_1.ConsoleLogger('BaseDataEventModifier');
10
+ }
11
+ modifyEvent(event) {
12
+ if (event == null) {
13
+ this.logger.debug(`modifyEvent(${JSON.stringify(event)}): Event is null!`);
14
+ return event;
15
+ }
16
+ Object.assign(event, this.viewInfo);
17
+ event["dt.rum.event.source.type"] = 'react_native';
18
+ const bundleName = ConfigurationHandler_1.ConfigurationHandler.getBundleName();
19
+ if (bundleName !== undefined) {
20
+ event["app.react_native.bundle.name"] =
21
+ bundleName;
22
+ }
23
+ const bundleVersion = ConfigurationHandler_1.ConfigurationHandler.getBundleVersion();
24
+ if (bundleVersion !== undefined) {
25
+ event["app.react_native.bundle.version"] =
26
+ bundleVersion;
27
+ }
28
+ return event;
29
+ }
30
+ }
31
+ exports.BaseDataEventModifier = BaseDataEventModifier;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventLimitation = void 0;
4
+ const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger");
5
+ const EventSpecContstants_1 = require("../spec/EventSpecContstants");
6
+ class EventLimitation {
7
+ constructor() {
8
+ this.logger = new ConsoleLogger_1.ConsoleLogger('EventLimitation');
9
+ }
10
+ limitEventEntries(customEntries) {
11
+ const fieldEntries = customEntries.slice();
12
+ fieldEntries.forEach(this.restrictingValueSize, this);
13
+ const validEntries = fieldEntries
14
+ .filter(this.isNotObject, this)
15
+ .filter(this.doesNotExceedKeySize, this)
16
+ .filter(this.isKeySyntaxAllowed, this);
17
+ if (fieldEntries.length !== validEntries.length) {
18
+ return validEntries;
19
+ }
20
+ else {
21
+ return fieldEntries;
22
+ }
23
+ }
24
+ limitEventProperties(eventEntries) {
25
+ const allowedEntries = [];
26
+ let propertyCounter = 0;
27
+ for (const [key, value] of eventEntries) {
28
+ if (key.startsWith("event_properties") ||
29
+ key.startsWith("session_properties")) {
30
+ propertyCounter++;
31
+ if (propertyCounter > EventSpecContstants_1.MAX_CUSTOM_EVENT_FIELDS) {
32
+ this.logger.debug(`limitEventProperties(): Dropped ${key} because overall property limit is reached!`);
33
+ continue;
34
+ }
35
+ }
36
+ allowedEntries.push([key, value]);
37
+ }
38
+ return allowedEntries;
39
+ }
40
+ isKeySyntaxAllowed(entry) {
41
+ const [key] = entry;
42
+ const rV = EventSpecContstants_1.KEY_NAME_REGEX.test(key);
43
+ if (!rV) {
44
+ this.logger.debug(`isKeySyntaxAllowed(): Filtering key ${key} as it doesnt fulfill character rules!`);
45
+ }
46
+ return rV;
47
+ }
48
+ restrictingValueSize(entry) {
49
+ const [key, value] = entry;
50
+ if (typeof value === 'string' &&
51
+ value.length > EventSpecContstants_1.MAX_CUSTOM_EVENT_VALUE_LENGTH) {
52
+ this.logger.debug(`restrictingValueSize(): Limiting value of ${key} as maximum value length (${EventSpecContstants_1.MAX_CUSTOM_EVENT_VALUE_LENGTH}) is reached!`);
53
+ entry[1] = value.slice(0, EventSpecContstants_1.MAX_CUSTOM_EVENT_VALUE_LENGTH);
54
+ }
55
+ }
56
+ doesNotExceedKeySize([key]) {
57
+ if (key.length <= EventSpecContstants_1.MAX_CUSTOM_EVENT_KEY_LENGTH) {
58
+ return true;
59
+ }
60
+ else {
61
+ this.logger.debug(`doesNotExceedKeySize(): Dropping key ${key} as maximum key length (${EventSpecContstants_1.MAX_CUSTOM_EVENT_KEY_LENGTH}) is reached!`);
62
+ return false;
63
+ }
64
+ }
65
+ isNotObject([, val]) {
66
+ return typeof val !== 'object' || val === null;
67
+ }
68
+ }
69
+ exports.EventLimitation = EventLimitation;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.containEventPropertiesInArray = exports.containEventProperties = exports.containSessionProperties = exports.trimStringValuesInObject = exports.trimString = exports.isObject = exports.flattenAdditionalData = void 0;
4
+ const MAX_STRING_LENGTH_FOR_VALUES = 5000;
5
+ const flattenAdditionalData = (obj, parent, res = {}) => {
6
+ for (const key in obj) {
7
+ const propName = parent != null ? parent + '.' + key : key;
8
+ const valueOfObject = obj[key];
9
+ if ((0, exports.isObject)(valueOfObject)) {
10
+ (0, exports.flattenAdditionalData)(valueOfObject, propName, res);
11
+ }
12
+ else {
13
+ res[propName] = obj[key];
14
+ }
15
+ }
16
+ return res;
17
+ };
18
+ exports.flattenAdditionalData = flattenAdditionalData;
19
+ const isObject = (obj) => {
20
+ if (obj === null || typeof obj !== 'object') {
21
+ return false;
22
+ }
23
+ return Object.prototype.toString.call(obj) === '[object Object]';
24
+ };
25
+ exports.isObject = isObject;
26
+ const trimString = (str, maxLength = MAX_STRING_LENGTH_FOR_VALUES) => {
27
+ const stringToTrim = str.toString();
28
+ if (stringToTrim.length <= maxLength) {
29
+ return stringToTrim;
30
+ }
31
+ else {
32
+ return stringToTrim.substring(0, maxLength);
33
+ }
34
+ };
35
+ exports.trimString = trimString;
36
+ const trimStringValuesInObject = (jsonData) => {
37
+ for (const key in jsonData) {
38
+ if (Object.prototype.hasOwnProperty.call(jsonData, key)) {
39
+ jsonData[key] = trimStringValue(jsonData[key]);
40
+ }
41
+ }
42
+ return jsonData;
43
+ };
44
+ exports.trimStringValuesInObject = trimStringValuesInObject;
45
+ const containSessionProperties = (jsonData) => {
46
+ for (const key in jsonData) {
47
+ if (key.startsWith(`${"session_properties"}.`)) {
48
+ return true;
49
+ }
50
+ }
51
+ return false;
52
+ };
53
+ exports.containSessionProperties = containSessionProperties;
54
+ const containEventProperties = (jsonData) => {
55
+ for (const key in jsonData) {
56
+ if (key.startsWith(`${"event_properties"}.`)) {
57
+ return true;
58
+ }
59
+ }
60
+ return false;
61
+ };
62
+ exports.containEventProperties = containEventProperties;
63
+ const containEventPropertiesInArray = (eventEntries) => {
64
+ for (const [key, value] of eventEntries) {
65
+ if (key.startsWith(`${"event_properties"}.`)) {
66
+ return true;
67
+ }
68
+ }
69
+ return false;
70
+ };
71
+ exports.containEventPropertiesInArray = containEventPropertiesInArray;
72
+ const trimStringValuesInArray = (arrayData) => {
73
+ arrayData.forEach((value, index, array) => {
74
+ array[index] = trimStringValue(value);
75
+ });
76
+ return arrayData;
77
+ };
78
+ const trimStringValue = (data) => {
79
+ if (typeof data === 'string') {
80
+ return (0, exports.trimString)(data);
81
+ }
82
+ else if (Array.isArray(data)) {
83
+ return trimStringValuesInArray(data);
84
+ }
85
+ else if ((0, exports.isObject)(data)) {
86
+ return (0, exports.trimStringValuesInObject)(data);
87
+ }
88
+ return data;
89
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ModifyEventValidation = void 0;
4
+ const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger");
5
+ const EventSpecContstants_1 = require("../spec/EventSpecContstants");
6
+ const EventLimitation_1 = require("./EventLimitation");
7
+ const EventModifierUtil_1 = require("./EventModifierUtil");
8
+ class ModifyEventValidation {
9
+ constructor() {
10
+ this.customEventModifierChain = [];
11
+ this.logger = new ConsoleLogger_1.ConsoleLogger('ModifyEventValidation');
12
+ }
13
+ addEventModifier(eventModifier) {
14
+ this.customEventModifierChain.push(eventModifier);
15
+ return eventModifier;
16
+ }
17
+ removeEventModifier(eventModifier) {
18
+ const index = this.customEventModifierChain.indexOf(eventModifier);
19
+ if (index !== -1) {
20
+ this.customEventModifierChain.splice(index, 1);
21
+ return true;
22
+ }
23
+ return false;
24
+ }
25
+ modifyEvent(event) {
26
+ if (this.customEventModifierChain.length > 0) {
27
+ const eventCopy = Object.assign({}, event);
28
+ let exceptionOccured = false;
29
+ this.customEventModifierChain.forEach((modifier) => {
30
+ try {
31
+ event = modifier.modifyEvent(event);
32
+ }
33
+ catch (error) {
34
+ if (event != null) {
35
+ exceptionOccured = true;
36
+ }
37
+ }
38
+ });
39
+ event = this.sanitizeUserEnrichedEvent(eventCopy, event, exceptionOccured);
40
+ }
41
+ return event;
42
+ }
43
+ isPropertiesAllowed(key, hasSessionPropertyCharacteristics) {
44
+ if (hasSessionPropertyCharacteristics) {
45
+ if (key.startsWith(`${"event_properties"}.`)) {
46
+ this.logger.debug(`isPropertiesAllowed(): Filtering key ${key} as usage of event properties is not allowed!`);
47
+ return true;
48
+ }
49
+ }
50
+ else {
51
+ if (key.startsWith(`${"session_properties"}.`)) {
52
+ this.logger.debug(`isPropertiesAllowed(): Filtering key ${key} as usage of session properties is not allowed!`);
53
+ return true;
54
+ }
55
+ }
56
+ return false;
57
+ }
58
+ isKeyNameForbidden(key) {
59
+ for (const namespace of EventSpecContstants_1.MODIFY_EVENT_WHITELIST_NAMESPACE) {
60
+ if (key.startsWith(`${namespace}.`)) {
61
+ return false;
62
+ }
63
+ }
64
+ if (EventSpecContstants_1.MODIFY_EVENT_WHITELIST_FIELDS.includes(key)) {
65
+ return false;
66
+ }
67
+ this.logger.debug(`isKeyNameForbidden(): Filtering key ${key} as this field is reserved and must not be overridden!`);
68
+ return true;
69
+ }
70
+ sanitizeUserEnrichedEvent(originalEvent, userEnrichedEvent, externalException) {
71
+ if (!(0, EventModifierUtil_1.isObject)(userEnrichedEvent)) {
72
+ this.logger.debug(`sanitizeUserEnrichedEvent(${originalEvent}, ${userEnrichedEvent}): Enriched event is not an object`);
73
+ return originalEvent;
74
+ }
75
+ if (userEnrichedEvent === originalEvent) {
76
+ this.logger.debug(`sanitizeUserEnrichedEvent(${originalEvent}, ${userEnrichedEvent}): Event has not been changed`);
77
+ return originalEvent;
78
+ }
79
+ let overriddenKeys = originalEvent["dt.rum.overridden_keys"];
80
+ if (overriddenKeys == null) {
81
+ overriddenKeys = [];
82
+ }
83
+ const userEnrichedEventEntries = Object.entries(userEnrichedEvent);
84
+ const validEntries = this.determineValidEntries(userEnrichedEventEntries, originalEvent, overriddenKeys);
85
+ const restoredEntries = this.restoreRemovedEntries(Object.entries(originalEvent), userEnrichedEvent, overriddenKeys);
86
+ const validAndRestoredEntries = validEntries.concat(restoredEntries);
87
+ const { baseEntries, addedEntries } = this.determineAddedEntries(originalEvent, validAndRestoredEntries);
88
+ const limitedEntries = new EventLimitation_1.EventLimitation().limitEventEntries(addedEntries);
89
+ if (originalEvent["characteristics.has_event_properties"] === undefined &&
90
+ (0, EventModifierUtil_1.containEventPropertiesInArray)(limitedEntries)) {
91
+ limitedEntries.push([
92
+ "characteristics.has_event_properties",
93
+ true,
94
+ ]);
95
+ }
96
+ const finalEntries = baseEntries.concat(limitedEntries);
97
+ const sizedEntries = new EventLimitation_1.EventLimitation().limitEventProperties(finalEntries);
98
+ if (sizedEntries.length < userEnrichedEventEntries.length) {
99
+ sizedEntries.push([
100
+ "dt.rum.api.has_dropped_fields",
101
+ true,
102
+ ]);
103
+ }
104
+ if (Array.isArray(overriddenKeys) && overriddenKeys.length > 0) {
105
+ sizedEntries.push([
106
+ "dt.rum.overridden_keys",
107
+ overriddenKeys,
108
+ ]);
109
+ }
110
+ if (externalException) {
111
+ sizedEntries.push([
112
+ "dt.rum.api.has_enrich_exception",
113
+ true,
114
+ ]);
115
+ }
116
+ return Object.fromEntries(sizedEntries);
117
+ }
118
+ determineValidEntries(userEnrichedEntries, originalJSONEvent, overriddenKeys) {
119
+ const newEntries = [];
120
+ for (const [prop, value] of userEnrichedEntries) {
121
+ const originalValue = originalJSONEvent[prop];
122
+ if (!this.isModified(originalValue, value)) {
123
+ newEntries.push([prop, value]);
124
+ continue;
125
+ }
126
+ if (this.isPropertiesAllowed(prop, originalJSONEvent["characteristics.has_session_properties"] === true)) {
127
+ continue;
128
+ }
129
+ const isNewlyAdded = typeof originalValue === 'undefined';
130
+ const isForbiddenKey = this.isKeyNameForbidden(prop);
131
+ if (isForbiddenKey) {
132
+ if (!isNewlyAdded) {
133
+ newEntries.push([prop, originalValue]);
134
+ }
135
+ continue;
136
+ }
137
+ if (!isNewlyAdded && !overriddenKeys.includes(prop)) {
138
+ overriddenKeys.push(prop);
139
+ }
140
+ newEntries.push([prop, value]);
141
+ }
142
+ return newEntries;
143
+ }
144
+ isModified(oldValue, newValue) {
145
+ if (Array.isArray(oldValue)) {
146
+ return (!Array.isArray(newValue) ||
147
+ oldValue.length !== newValue.length ||
148
+ !oldValue.every((item, index) => !this.isModified(item, newValue[index])));
149
+ }
150
+ if ((0, EventModifierUtil_1.isObject)(oldValue)) {
151
+ const oldEntries = Object.entries(oldValue);
152
+ return (!(0, EventModifierUtil_1.isObject)(newValue) ||
153
+ Object.entries(newValue).length !== oldEntries.length ||
154
+ !oldEntries.every(([prop, value]) => !this.isModified(value, newValue[prop])));
155
+ }
156
+ return oldValue !== newValue;
157
+ }
158
+ restoreRemovedEntries(originalEntries, userEnrichedEvent, overriddenKeys) {
159
+ const restoredEntries = [];
160
+ for (const [prop, value] of originalEntries) {
161
+ if (typeof userEnrichedEvent[prop] !== 'undefined') {
162
+ continue;
163
+ }
164
+ if (this.isKeyNameForbidden(prop)) {
165
+ restoredEntries.push([prop, value]);
166
+ }
167
+ else if (!overriddenKeys.includes(prop)) {
168
+ overriddenKeys.push(prop);
169
+ }
170
+ }
171
+ return restoredEntries;
172
+ }
173
+ determineAddedEntries(originalJSONEvent, userEnrichedEntries) {
174
+ const resultEntries = {
175
+ baseEntries: [],
176
+ addedEntries: [],
177
+ };
178
+ return userEnrichedEntries.reduce((entries, entry) => {
179
+ if (Object.prototype.hasOwnProperty.call(originalJSONEvent, entry[0])) {
180
+ entries.baseEntries.push(entry);
181
+ }
182
+ else {
183
+ entries.addedEntries.push(entry);
184
+ }
185
+ return entries;
186
+ }, resultEntries);
187
+ }
188
+ }
189
+ exports.ModifyEventValidation = ModifyEventValidation;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SendSessionPropertyEventValidation = exports.SendEventValidation = void 0;
4
+ const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger");
5
+ const TimestampProvider_1 = require("../../provider/TimestampProvider");
6
+ const EventTimestamp_1 = require("../EventTimestamp");
7
+ const EventSpecContstants_1 = require("../spec/EventSpecContstants");
8
+ const EventLimitation_1 = require("./EventLimitation");
9
+ class SendEventValidationImpl {
10
+ constructor(timestampProvider, namespaceWhitelist, fieldWhitelist, loggerName) {
11
+ this.logger = new ConsoleLogger_1.ConsoleLogger(loggerName);
12
+ this.timestampProvider = timestampProvider;
13
+ this.fieldWhitelist = fieldWhitelist;
14
+ this.namespaceWhitelist = namespaceWhitelist;
15
+ }
16
+ modifyEvent(event) {
17
+ this.logger.debug(`modifyEvent(${JSON.stringify(event)})`);
18
+ if (event == null) {
19
+ return null;
20
+ }
21
+ else if (Object.keys(event).length === 0) {
22
+ return Object.assign({}, new EventTimestamp_1.EventTimestamp(this.timestampProvider).getEventTimeInfo());
23
+ }
24
+ const timeNow = this.timestampProvider.getCurrentTimestamp();
25
+ const eventCopy = Object.entries(event).slice();
26
+ const filteredEvent = eventCopy
27
+ .filter(this.isKeyNameAllowed, this)
28
+ .filter(this.isFieldTypeAllowed, this);
29
+ const limitedEntries = new EventLimitation_1.EventLimitation().limitEventEntries(filteredEvent);
30
+ const sizedEntries = new EventLimitation_1.EventLimitation().limitEventProperties(limitedEntries);
31
+ this.applyOverriddenKeys(sizedEntries);
32
+ if (sizedEntries.length < eventCopy.length) {
33
+ sizedEntries.push([
34
+ "dt.rum.api.has_dropped_fields",
35
+ true,
36
+ ]);
37
+ }
38
+ const jsonObject = Object.fromEntries(sizedEntries);
39
+ if (jsonObject["duration"] !== undefined) {
40
+ jsonObject["start_time"] =
41
+ timeNow - jsonObject["duration"];
42
+ }
43
+ else {
44
+ jsonObject["start_time"] = timeNow;
45
+ jsonObject["duration"] = 0;
46
+ }
47
+ return jsonObject;
48
+ }
49
+ applyOverriddenKeys(eventEntries) {
50
+ const overriddenKeys = [];
51
+ for (const [key, value] of eventEntries) {
52
+ if (this.fieldWhitelist.includes(key)) {
53
+ overriddenKeys.push(key);
54
+ }
55
+ }
56
+ if (overriddenKeys.length > 0) {
57
+ eventEntries.push([
58
+ "dt.rum.overridden_keys",
59
+ overriddenKeys,
60
+ ]);
61
+ }
62
+ }
63
+ isFieldTypeAllowed(entry) {
64
+ const [key, value] = entry;
65
+ if (key === "duration" ||
66
+ key === "start_time") {
67
+ return typeof value === 'number' && isFinite(value) && value >= 0;
68
+ }
69
+ return true;
70
+ }
71
+ isKeyNameAllowed(entry) {
72
+ const [key] = entry;
73
+ for (const namespace of this.namespaceWhitelist) {
74
+ if (key.startsWith(`${namespace}.`)) {
75
+ return true;
76
+ }
77
+ }
78
+ if (this.fieldWhitelist.includes(key)) {
79
+ return true;
80
+ }
81
+ this.logger.debug(`isKeyNameAllowed(): Filtering key ${key} as this field or namespace is reserved!`);
82
+ return false;
83
+ }
84
+ }
85
+ exports.SendEventValidation = new SendEventValidationImpl(TimestampProvider_1.defaultTimestampProvider, EventSpecContstants_1.SEND_EVENT_WHITELIST_NAMESPACES, EventSpecContstants_1.SEND_EVENT_WHITELIST_FIELDS, 'SendEventValidation');
86
+ exports.SendSessionPropertyEventValidation = new SendEventValidationImpl(TimestampProvider_1.defaultTimestampProvider, EventSpecContstants_1.SEND_SESSION_PROPERTY_EVENT_WHITELIST_NAMESPACES, EventSpecContstants_1.SEND_SESSION_PROPERTY_EVENT_WHITELIST_FIELDS, 'SendSessionPropertyEventValidation');