@dynatrace/react-native-plugin 2.305.1 → 2.309.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.
- package/README.md +21 -10
- package/android/build.gradle +3 -1
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceAppStartModule.kt +128 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceInternalModule.kt +22 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +411 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceReactPackage.kt +54 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.kt +86 -0
- package/android/src/main/java/com/dynatrace/android/agent/model/AppStartMeasurement.kt +15 -0
- package/android/src/main/java/com/dynatrace/android/agent/model/AppStartMeasurementType.kt +18 -0
- package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +228 -0
- package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +258 -0
- package/files/plugin.gradle +1 -1
- package/index.js +10 -10
- package/instrumentation/DynatraceInstrumentation.js +1 -0
- package/{lib → instrumentation/jsx}/CreateElement.js +6 -5
- package/{lib/instrumentor/base → instrumentation/jsx}/ElementHelper.js +14 -12
- package/{lib/jsx-dev-runtime.js → instrumentation/jsx/JsxDevRuntime.js} +10 -19
- package/instrumentation/jsx/JsxRuntime.js +63 -0
- package/instrumentation/jsx/JsxRuntimeUtil.js +31 -0
- package/instrumentation/jsx/components/ClassComponent.js +49 -0
- package/instrumentation/jsx/components/ComponentUtil.js +33 -0
- package/instrumentation/jsx/components/FunctionalComponent.js +20 -0
- package/{lib/instrumentor/base → instrumentation/jsx/components}/Picker.js +1 -1
- package/{lib/instrumentor/base → instrumentation/jsx/components}/RefreshControl.js +1 -1
- package/{lib/instrumentor/base → instrumentation/jsx/components}/Switch.js +1 -1
- package/{lib/instrumentor/base → instrumentation/jsx/components}/Touchable.js +5 -5
- package/instrumentation/libs/community/Picker.InstrInfo.js +20 -0
- package/{lib → instrumentation/libs}/community/Picker.js +1 -1
- package/instrumentation/libs/community/gesture-handler/Touchables.InstrInfo.js +23 -0
- package/{lib → instrumentation/libs}/community/gesture-handler/Touchables.js +1 -1
- package/{lib → instrumentation/libs}/react-native/RefreshControl.InstrInfo.js +2 -2
- package/{lib → instrumentation/libs}/react-native/RefreshControl.js +5 -5
- package/{lib → instrumentation/libs}/react-native/Switch.InstrInfo.js +2 -2
- package/{lib → instrumentation/libs}/react-native/Switch.js +5 -5
- package/instrumentation/libs/react-native/Touchables.InstrInfo.js +25 -0
- package/{lib → instrumentation/libs}/react-native/Touchables.js +1 -1
- package/{lib → instrumentation/libs}/react-navigation/ReactNavigation.js +6 -5
- package/{lib/instrumentor → instrumentation}/model/Types.js +1 -14
- package/instrumentation/model/TypesUtil.js +17 -0
- package/ios/DynatraceRNBridge.h +10 -1
- package/ios/DynatraceRNBridge.mm +152 -0
- package/jsx-dev-runtime.js +1 -1
- package/jsx-runtime.js +1 -1
- package/lib/core/Application.js +20 -0
- package/lib/{instrumentor/base → core}/Dynatrace.js +57 -48
- package/lib/{instrumentor/base → core}/DynatraceAction.js +23 -22
- package/lib/core/DynatraceInternal.js +46 -0
- package/lib/{instrumentor/base → core}/DynatraceRootAction.js +5 -4
- package/lib/{instrumentor/base → core}/DynatraceWebRequestTiming.js +6 -5
- package/lib/{instrumentor/base → core}/ErrorHandler.js +6 -5
- package/lib/{instrumentor/base → core}/configuration/Configuration.js +1 -1
- package/lib/{instrumentor/base → core}/configuration/ConfigurationDefaults.js +1 -2
- package/lib/{instrumentor/base → core}/configuration/ConfigurationHandler.js +2 -2
- package/lib/{instrumentor/base → core}/configuration/ManualStartupConfiguration.js +1 -1
- package/lib/core/logging/ConsoleLogger.js +27 -0
- package/lib/core/logging/LogLevel.js +12 -0
- package/lib/dynatrace-transformer.js +1 -1
- package/lib/next/Dynatrace.js +86 -0
- package/lib/next/DynatraceSecondGenForwarder.js +17 -0
- package/lib/next/IDynatrace.js +2 -0
- package/lib/next/IDynatraceForwarder.js +2 -0
- package/lib/next/appstart/AppStartObserver.js +32 -0
- package/lib/next/appstart/AppStartType.js +38 -0
- package/lib/next/events/EventCreator.js +77 -0
- package/lib/next/events/EventPipeline.js +57 -0
- package/lib/next/events/EventTimestamp.js +24 -0
- package/lib/next/events/ViewInfoCreator.js +27 -0
- package/lib/next/events/modifier/BaseDataEventModifier.js +31 -0
- package/lib/next/events/modifier/EventLimitation.js +69 -0
- package/lib/next/events/modifier/EventModifierUtil.js +88 -0
- package/lib/next/events/modifier/IEventModifier.js +2 -0
- package/lib/next/events/modifier/ModifyEventValidation.js +187 -0
- package/lib/next/events/modifier/NonFiniteNumbersModifier.js +50 -0
- package/lib/next/events/modifier/SendEventValidation.js +84 -0
- package/lib/next/events/spec/EventFieldKeysEnum.js +2 -0
- package/lib/next/events/spec/EventSpecContstants.js +46 -0
- package/lib/next/events/spec/IAppStartEvent.js +2 -0
- package/lib/next/events/spec/ICrashEvent.js +2 -0
- package/lib/next/events/spec/IErrorCodeEvent.js +2 -0
- package/lib/next/events/spec/IErrorExceptionEvent.js +2 -0
- package/lib/next/events/spec/IReactNativeEvent.js +2 -0
- package/lib/next/events/spec/IRumEvent.js +2 -0
- package/lib/next/provider/ITimestampProvider.js +2 -0
- package/lib/next/provider/TimestampProvider.js +10 -0
- package/package.json +51 -40
- package/react-native-dynatrace.podspec +1 -1
- package/src/lib/{instrumentor/base → core}/interface/NativeDynatraceBridge.ts +10 -0
- package/typings/react-native-dynatrace.d.ts +0 -1
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.java +0 -362
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceReactPackage.java +0 -67
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.java +0 -76
- package/android/src/main/java/com/dynatrace/android/agent/PrivateDTBridge.java +0 -28
- package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.java +0 -187
- package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.java +0 -189
- package/lib/community/Picker.InstrInfo.js +0 -20
- package/lib/community/gesture-handler/Touchables.InstrInfo.js +0 -56
- package/lib/instrumentor/DynatraceInstrumentation.js +0 -1
- package/lib/instrumentor/base/Application.js +0 -16
- package/lib/instrumentor/base/DynatraceInternal.js +0 -34
- package/lib/instrumentor/base/Logger.js +0 -16
- package/lib/instrumentor/base/model/LogLevel.js +0 -17
- package/lib/jsx-runtime.js +0 -69
- package/lib/react/Component.js +0 -90
- package/lib/react-native/Touchables.InstrInfo.js +0 -60
- /package/{lib/instrumentor/base/interface → instrumentation/jsx}/IDynatraceProperties.js +0 -0
- /package/{lib → instrumentation/libs}/community/gesture-handler/index.js +0 -0
- /package/{lib → instrumentation/libs}/gesture-handler.js +0 -0
- /package/{lib → instrumentation/libs}/react-native/index.js +0 -0
- /package/{lib → instrumentation/libs}/react-native.js +0 -0
- /package/{lib/instrumentor → instrumentation}/model/Reference.js +0 -0
- /package/{lib/instrumentor → instrumentation}/parser/Babel.js +0 -0
- /package/lib/{instrumentor/base → core}/DynatraceBridge.js +0 -0
- /package/lib/{instrumentor/base → core}/NullAction.js +0 -0
- /package/lib/{instrumentor/base → core}/NullRootAction.js +0 -0
- /package/lib/{instrumentor/base → core}/NullWebRequestTiming.js +0 -0
- /package/lib/{instrumentor/base → core}/UserPrivacyOptions.js +0 -0
- /package/lib/{instrumentor/base → core}/configuration/ConfigurationBuilder.js +0 -0
- /package/lib/{instrumentor/base → core}/configuration/ConfigurationPreset.js +0 -0
- /package/lib/{instrumentor/base → core}/configuration/IConfiguration.js +0 -0
- /package/lib/{instrumentor/base → core}/interface/IDynatrace.js +0 -0
- /package/lib/{instrumentor/base → core}/interface/IDynatraceAction.js +0 -0
- /package/lib/{instrumentor/base → core}/interface/IDynatraceInternal.js +0 -0
- /package/lib/{instrumentor/base → core}/interface/IDynatraceRootAction.js +0 -0
- /package/lib/{instrumentor/base → core}/interface/IWebRequestTiming.js +0 -0
- /package/lib/{instrumentor/base → core}/interface/NativeDynatraceBridge.js +0 -0
- /package/lib/{instrumentor/base/interface → core/logging}/ILogger.js +0 -0
- /package/lib/{instrumentor/base → core}/model/DataCollectionLevel.js +0 -0
- /package/lib/{instrumentor/base → core}/model/Json.js +0 -0
- /package/lib/{instrumentor/base → core}/model/Platform.js +0 -0
- /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,57 @@
|
|
|
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 NonFiniteNumbersModifier_1 = require("./modifier/NonFiniteNumbersModifier");
|
|
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(additionalData) {
|
|
16
|
+
return [
|
|
17
|
+
new BaseDataEventModifier_1.BaseDataEventModifier(this.viewInfo),
|
|
18
|
+
this.customEventModifierChain,
|
|
19
|
+
NonFiniteNumbersModifier_1.NonFiniteNumbersModifier,
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
insertEvent(event, additionalData) {
|
|
23
|
+
this.logger.debug(`insertEvent(${JSON.stringify(event)}, ${JSON.stringify(additionalData)})`);
|
|
24
|
+
this.getEventModifierChain(additionalData).forEach((modifier) => {
|
|
25
|
+
try {
|
|
26
|
+
event = modifier.modifyEvent(event);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (event != null) {
|
|
30
|
+
event["dt.rum.api.has_enrich_exception"] = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
if (event != null) {
|
|
35
|
+
this.logger.debug(`forwardEvent(${JSON.stringify(event)})`);
|
|
36
|
+
DynatraceBridge_1.DynatraceNative.forwardEvent(event);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
addEventModifier(eventModifier) {
|
|
40
|
+
this.logger.debug('addEventModifier()');
|
|
41
|
+
return this.customEventModifierChain.addEventModifier(eventModifier);
|
|
42
|
+
}
|
|
43
|
+
removeEventModifier(eventModifier) {
|
|
44
|
+
this.logger.debug('removeEventModifier()');
|
|
45
|
+
return this.customEventModifierChain.removeEventModifier(eventModifier);
|
|
46
|
+
}
|
|
47
|
+
generateViewData(name) {
|
|
48
|
+
this.logger.debug(`generateViewData(${name})`);
|
|
49
|
+
if (name != null) {
|
|
50
|
+
this.viewInfo = (0, ViewInfoCreator_1.createViewInfo)(name);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
releaseViewData() {
|
|
54
|
+
this.viewInfo = undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.EventPipeline = new EventPipelineImpl();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventTimestamp = void 0;
|
|
4
|
+
class EventTimestamp {
|
|
5
|
+
constructor(timestampProvider) {
|
|
6
|
+
this.duration = 0;
|
|
7
|
+
this.timestampProvider = timestampProvider;
|
|
8
|
+
this.startTimestamp = timestampProvider.getCurrentTimestamp();
|
|
9
|
+
}
|
|
10
|
+
getEventTimeInfo() {
|
|
11
|
+
return {
|
|
12
|
+
duration: this.duration,
|
|
13
|
+
start_time: this.startTimestamp,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
setEndTimestamp(endTimestamp = this.timestampProvider.getCurrentTimestamp()) {
|
|
17
|
+
if (endTimestamp > this.startTimestamp) {
|
|
18
|
+
this.duration = endTimestamp - this.startTimestamp;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
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,88 @@
|
|
|
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
|
+
if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
|
|
9
|
+
(0, exports.flattenAdditionalData)(obj[key], propName, res);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
res[propName] = obj[key];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return res;
|
|
16
|
+
};
|
|
17
|
+
exports.flattenAdditionalData = flattenAdditionalData;
|
|
18
|
+
const isObject = (obj) => {
|
|
19
|
+
if (obj === null || typeof obj !== 'object') {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
return Object.prototype.toString.call(obj) === '[object Object]';
|
|
23
|
+
};
|
|
24
|
+
exports.isObject = isObject;
|
|
25
|
+
const trimString = (str, maxLength = MAX_STRING_LENGTH_FOR_VALUES) => {
|
|
26
|
+
const stringToTrim = str.toString();
|
|
27
|
+
if (stringToTrim.length <= maxLength) {
|
|
28
|
+
return stringToTrim;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
return stringToTrim.substring(0, maxLength);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
exports.trimString = trimString;
|
|
35
|
+
const trimStringValuesInObject = (jsonData) => {
|
|
36
|
+
for (const key in jsonData) {
|
|
37
|
+
if (Object.prototype.hasOwnProperty.call(jsonData, key)) {
|
|
38
|
+
jsonData[key] = trimStringValue(jsonData[key]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return jsonData;
|
|
42
|
+
};
|
|
43
|
+
exports.trimStringValuesInObject = trimStringValuesInObject;
|
|
44
|
+
const containSessionProperties = (jsonData) => {
|
|
45
|
+
for (const key in jsonData) {
|
|
46
|
+
if (key.startsWith(`${"session_properties"}.`)) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
};
|
|
52
|
+
exports.containSessionProperties = containSessionProperties;
|
|
53
|
+
const containEventProperties = (jsonData) => {
|
|
54
|
+
for (const key in jsonData) {
|
|
55
|
+
if (key.startsWith(`${"event_properties"}.`)) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
};
|
|
61
|
+
exports.containEventProperties = containEventProperties;
|
|
62
|
+
const containEventPropertiesInArray = (eventEntries) => {
|
|
63
|
+
for (const [key, value] of eventEntries) {
|
|
64
|
+
if (key.startsWith(`${"event_properties"}.`)) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
};
|
|
70
|
+
exports.containEventPropertiesInArray = containEventPropertiesInArray;
|
|
71
|
+
const trimStringValuesInArray = (arrayData) => {
|
|
72
|
+
arrayData.forEach((value, index, array) => {
|
|
73
|
+
array[index] = trimStringValue(value);
|
|
74
|
+
});
|
|
75
|
+
return arrayData;
|
|
76
|
+
};
|
|
77
|
+
const trimStringValue = (data) => {
|
|
78
|
+
if (typeof data === 'string') {
|
|
79
|
+
return (0, exports.trimString)(data);
|
|
80
|
+
}
|
|
81
|
+
else if (Array.isArray(data)) {
|
|
82
|
+
return trimStringValuesInArray(data);
|
|
83
|
+
}
|
|
84
|
+
else if ((0, exports.isObject)(data)) {
|
|
85
|
+
return (0, exports.trimStringValuesInObject)(data);
|
|
86
|
+
}
|
|
87
|
+
return data;
|
|
88
|
+
};
|
|
@@ -0,0 +1,187 @@
|
|
|
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
|
+
sizedEntries.push([
|
|
99
|
+
"dt.rum.api.has_dropped_fields",
|
|
100
|
+
sizedEntries.length < userEnrichedEventEntries.length,
|
|
101
|
+
]);
|
|
102
|
+
if (Array.isArray(overriddenKeys) && overriddenKeys.length > 0) {
|
|
103
|
+
sizedEntries.push([
|
|
104
|
+
"dt.rum.overridden_keys",
|
|
105
|
+
overriddenKeys,
|
|
106
|
+
]);
|
|
107
|
+
}
|
|
108
|
+
if (externalException) {
|
|
109
|
+
sizedEntries.push([
|
|
110
|
+
"dt.rum.api.has_enrich_exception",
|
|
111
|
+
true,
|
|
112
|
+
]);
|
|
113
|
+
}
|
|
114
|
+
return Object.fromEntries(sizedEntries);
|
|
115
|
+
}
|
|
116
|
+
determineValidEntries(userEnrichedEntries, originalJSONEvent, overriddenKeys) {
|
|
117
|
+
const newEntries = [];
|
|
118
|
+
for (const [prop, value] of userEnrichedEntries) {
|
|
119
|
+
const originalValue = originalJSONEvent[prop];
|
|
120
|
+
if (!this.isModified(originalValue, value)) {
|
|
121
|
+
newEntries.push([prop, value]);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (this.isPropertiesAllowed(prop, originalJSONEvent["characteristics.has_session_properties"] === true)) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const isNewlyAdded = typeof originalValue === 'undefined';
|
|
128
|
+
const isForbiddenKey = this.isKeyNameForbidden(prop);
|
|
129
|
+
if (isForbiddenKey) {
|
|
130
|
+
if (!isNewlyAdded) {
|
|
131
|
+
newEntries.push([prop, originalValue]);
|
|
132
|
+
}
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (!isNewlyAdded && !overriddenKeys.includes(prop)) {
|
|
136
|
+
overriddenKeys.push(prop);
|
|
137
|
+
}
|
|
138
|
+
newEntries.push([prop, value]);
|
|
139
|
+
}
|
|
140
|
+
return newEntries;
|
|
141
|
+
}
|
|
142
|
+
isModified(oldValue, newValue) {
|
|
143
|
+
if (Array.isArray(oldValue)) {
|
|
144
|
+
return (!Array.isArray(newValue) ||
|
|
145
|
+
oldValue.length !== newValue.length ||
|
|
146
|
+
!oldValue.every((item, index) => !this.isModified(item, newValue[index])));
|
|
147
|
+
}
|
|
148
|
+
if ((0, EventModifierUtil_1.isObject)(oldValue)) {
|
|
149
|
+
const oldEntries = Object.entries(oldValue);
|
|
150
|
+
return (!(0, EventModifierUtil_1.isObject)(newValue) ||
|
|
151
|
+
Object.entries(newValue).length !== oldEntries.length ||
|
|
152
|
+
!oldEntries.every(([prop, value]) => !this.isModified(value, newValue[prop])));
|
|
153
|
+
}
|
|
154
|
+
return oldValue !== newValue;
|
|
155
|
+
}
|
|
156
|
+
restoreRemovedEntries(originalEntries, userEnrichedEvent, overriddenKeys) {
|
|
157
|
+
const restoredEntries = [];
|
|
158
|
+
for (const [prop, value] of originalEntries) {
|
|
159
|
+
if (typeof userEnrichedEvent[prop] !== 'undefined') {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (this.isKeyNameForbidden(prop)) {
|
|
163
|
+
restoredEntries.push([prop, value]);
|
|
164
|
+
}
|
|
165
|
+
else if (!overriddenKeys.includes(prop)) {
|
|
166
|
+
overriddenKeys.push(prop);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return restoredEntries;
|
|
170
|
+
}
|
|
171
|
+
determineAddedEntries(originalJSONEvent, userEnrichedEntries) {
|
|
172
|
+
const resultEntries = {
|
|
173
|
+
baseEntries: [],
|
|
174
|
+
addedEntries: [],
|
|
175
|
+
};
|
|
176
|
+
return userEnrichedEntries.reduce((entries, entry) => {
|
|
177
|
+
if (Object.prototype.hasOwnProperty.call(originalJSONEvent, entry[0])) {
|
|
178
|
+
entries.baseEntries.push(entry);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
entries.addedEntries.push(entry);
|
|
182
|
+
}
|
|
183
|
+
return entries;
|
|
184
|
+
}, resultEntries);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
exports.ModifyEventValidation = ModifyEventValidation;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NonFiniteNumbersModifier = void 0;
|
|
4
|
+
const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger");
|
|
5
|
+
const EventModifierUtil_1 = require("./EventModifierUtil");
|
|
6
|
+
class NonFiniteNumbersModifierImpl {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.logger = new ConsoleLogger_1.ConsoleLogger('NonFiniteNumbersModifier');
|
|
9
|
+
}
|
|
10
|
+
modifyEvent(event) {
|
|
11
|
+
if (event != null && this.eventHasNonFiniteNumbers(event)) {
|
|
12
|
+
event["dt.rum.has_nfn_values"] = true;
|
|
13
|
+
}
|
|
14
|
+
return event;
|
|
15
|
+
}
|
|
16
|
+
eventHasNonFiniteNumbers(obj) {
|
|
17
|
+
for (const key in obj) {
|
|
18
|
+
if (Object.prototype.hasOwnProperty.call(obj, key) &&
|
|
19
|
+
this.valueHasNonFiniteNumber(obj[key])) {
|
|
20
|
+
this.logger.debug(`eventHasNonFiniteNumbers() - ${key} contains non-finite numbers: ${obj[key]} changed to null!`);
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
valueHasNonFiniteNumber(val) {
|
|
27
|
+
if (typeof val === 'function') {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
if (Array.isArray(val)) {
|
|
31
|
+
return this.arrayHasNonFiniteNumbers(val);
|
|
32
|
+
}
|
|
33
|
+
if ((0, EventModifierUtil_1.isObject)(val)) {
|
|
34
|
+
return this.eventHasNonFiniteNumbers(val);
|
|
35
|
+
}
|
|
36
|
+
return !this.isFinitePrimitive(val);
|
|
37
|
+
}
|
|
38
|
+
arrayHasNonFiniteNumbers(arr) {
|
|
39
|
+
for (const val of arr) {
|
|
40
|
+
if (this.valueHasNonFiniteNumber(val)) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
isFinitePrimitive(value) {
|
|
47
|
+
return typeof value !== 'number' || isFinite(value);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.NonFiniteNumbersModifier = new NonFiniteNumbersModifierImpl();
|