@dynatrace/react-native-plugin 2.323.1 → 2.325.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 +33 -9
- package/android/build.gradle +3 -3
- package/files/plugin-runtime.gradle +8 -1
- package/files/plugin.gradle +1 -1
- package/index.js +18 -10
- package/instrumentation/DynatraceInstrumentation.js +1 -1
- package/instrumentation/jsx/CreateElement.js +10 -7
- package/instrumentation/jsx/ElementHelper.js +0 -5
- package/instrumentation/libs/react-native/Switch.js +55 -12
- package/instrumentation/libs/withOnPressMonitoring.js +1 -1
- package/instrumentation/model/Types.js +0 -1
- package/internal.js +7 -0
- package/lib/core/Dynatrace.js +4 -1
- package/lib/core/DynatraceAction.js +3 -2
- package/lib/core/DynatraceWebRequestTiming.js +5 -5
- package/lib/core/ErrorHandler.js +18 -34
- package/lib/core/NullWebRequestTiming.js +1 -0
- package/lib/core/configuration/Configuration.js +2 -2
- package/lib/core/configuration/ConfigurationBuilder.js +3 -2
- package/lib/core/configuration/ManualStartupConfiguration.js +6 -3
- package/lib/core/interface/IWebRequestTiming.js +1 -0
- package/lib/core/logging/LogLevel.js +1 -10
- package/lib/core/logging/LogLevelUtil.js +13 -0
- package/lib/next/Dynatrace.js +29 -19
- package/lib/next/appstart/AppStartObserver.js +1 -1
- package/lib/next/events/EventCreator.js +2 -1
- package/lib/next/events/EventPipeline.js +14 -6
- package/lib/next/events/HttpRequestEventBuilder.js +196 -0
- package/lib/next/events/IHttpRequestEventBuilder.js +2 -0
- package/lib/next/events/ViewInfoCreator.js +1 -1
- package/lib/next/events/modifier/BaseDataEventModifier.js +6 -0
- package/lib/next/events/modifier/EventModifierUtil.js +34 -1
- package/lib/next/events/modifier/ModifyEventValidation.js +18 -5
- package/lib/next/events/modifier/SendEventValidation.js +23 -10
- package/lib/next/events/spec/EventSpecContstants.js +2 -1
- package/package.json +12 -6
- package/public.js +22 -0
- package/react-augmentation.js +3 -0
- package/react-native-dynatrace.podspec +1 -1
- package/scripts/core/LineOffsetAnalyzeCall.js +3 -3
- package/types.d.ts +1969 -0
- package/instrumentation/jsx/components/Switch.js +0 -57
- package/instrumentation/model/TypesUtil.js +0 -21
- package/src/instrumentation/jsx/IDynatraceProperties.ts +0 -15
- package/typings/react-native-dynatrace.d.ts +0 -1729
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ManualStartupConfiguration = void 0;
|
|
4
|
-
const
|
|
4
|
+
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) {
|
|
8
|
+
constructor(beaconUrl, applicationId, reportCrash, logLevel, lifecycleUpdate, userOptIn, actionNamePrivacy, 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) {
|
|
@@ -38,11 +38,14 @@ class ManualStartupConfiguration {
|
|
|
38
38
|
if (bundleName != null) {
|
|
39
39
|
this.bundleName = bundleName;
|
|
40
40
|
}
|
|
41
|
+
if (bundleVersion != null) {
|
|
42
|
+
this.bundleVersion = bundleVersion;
|
|
43
|
+
}
|
|
41
44
|
}
|
|
42
45
|
toString() {
|
|
43
46
|
let configurationString = `{Startup: Manual Start, applicationId: ${this.applicationId}, beaconUrl: ${this.beaconUrl},` +
|
|
44
47
|
` reportCrash: ${this.reportCrash}, errorHandler: ${this.errorHandler}, reportFatalErrorAsCrash: ${this.reportFatalErrorAsCrash},` +
|
|
45
|
-
` lifecycleUpdate: ${this.lifecycleUpdate}, userOptIn: ${this.userOptIn}, actionNamePrivacy: ${this.actionNamePrivacy}, logLevel: ${(0,
|
|
48
|
+
` lifecycleUpdate: ${this.lifecycleUpdate}, userOptIn: ${this.userOptIn}, actionNamePrivacy: ${this.actionNamePrivacy}, logLevel: ${(0, LogLevelUtil_1.LogLevelToString)(this.logLevel)}`;
|
|
46
49
|
if (this.bundleName !== undefined) {
|
|
47
50
|
configurationString += `, bundleName: ${this.bundleName}`;
|
|
48
51
|
}
|
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.LogLevel = void 0;
|
|
4
4
|
var LogLevel;
|
|
5
5
|
(function (LogLevel) {
|
|
6
6
|
LogLevel[LogLevel["Debug"] = 0] = "Debug";
|
|
7
7
|
LogLevel[LogLevel["Info"] = 1] = "Info";
|
|
8
8
|
})(LogLevel = exports.LogLevel || (exports.LogLevel = {}));
|
|
9
|
-
const LogLevelToString = (level) => {
|
|
10
|
-
if (level === LogLevel.Debug) {
|
|
11
|
-
return 'Debug';
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
return 'Info';
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
exports.LogLevelToString = LogLevelToString;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LogLevelToString = void 0;
|
|
4
|
+
const LogLevel_1 = require("./LogLevel");
|
|
5
|
+
const LogLevelToString = (level) => {
|
|
6
|
+
if (level === LogLevel_1.LogLevel.Debug) {
|
|
7
|
+
return 'Debug';
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
return 'Info';
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
exports.LogLevelToString = LogLevelToString;
|
package/lib/next/Dynatrace.js
CHANGED
|
@@ -42,8 +42,7 @@ class DynatraceImpl {
|
|
|
42
42
|
const eventTimestamp = new EventTimestamp_1.EventTimestamp(this.timestampProvider);
|
|
43
43
|
const event = Object.assign(Object.assign({}, (0, EventCreator_1.createCrashEvent)(crash.name, crash.message, crash.stack, isFatal)), eventTimestamp.getEventTimeInfo());
|
|
44
44
|
if (isApiReported) {
|
|
45
|
-
event
|
|
46
|
-
true;
|
|
45
|
+
(0, EventModifierUtil_1.addIsApiReported)(event);
|
|
47
46
|
event["dt.support.is_legacy_api_reported"] = true;
|
|
48
47
|
}
|
|
49
48
|
EventPipeline_1.EventPipeline.insertEvent(event);
|
|
@@ -53,8 +52,7 @@ class DynatraceImpl {
|
|
|
53
52
|
const eventTimestamp = new EventTimestamp_1.EventTimestamp(this.timestampProvider);
|
|
54
53
|
const event = Object.assign(Object.assign({}, (0, EventCreator_1.createErrorCodeEvent)(errorName, errorCode)), eventTimestamp.getEventTimeInfo());
|
|
55
54
|
if (isApiReported) {
|
|
56
|
-
event
|
|
57
|
-
true;
|
|
55
|
+
(0, EventModifierUtil_1.addIsApiReported)(event);
|
|
58
56
|
event["dt.support.is_legacy_api_reported"] = true;
|
|
59
57
|
}
|
|
60
58
|
EventPipeline_1.EventPipeline.insertEvent(event);
|
|
@@ -64,37 +62,49 @@ class DynatraceImpl {
|
|
|
64
62
|
const eventTimestamp = new EventTimestamp_1.EventTimestamp(this.timestampProvider);
|
|
65
63
|
const event = Object.assign(Object.assign({}, (0, EventCreator_1.createErrorEvent)(error.name, error.message, error.stack)), eventTimestamp.getEventTimeInfo());
|
|
66
64
|
if (isApiReported) {
|
|
67
|
-
event
|
|
68
|
-
true;
|
|
65
|
+
(0, EventModifierUtil_1.addIsApiReported)(event);
|
|
69
66
|
event["dt.support.is_legacy_api_reported"] = true;
|
|
70
67
|
}
|
|
71
68
|
EventPipeline_1.EventPipeline.insertEvent(event);
|
|
72
69
|
}
|
|
73
70
|
sendExceptionEvent(error, fields) {
|
|
74
|
-
|
|
75
|
-
this.logger.debug(`sendExceptionEvent(${JSON.stringify(error)}, ${JSON.stringify(fieldsCheck)})`);
|
|
71
|
+
this.logger.debug(`sendExceptionEvent(${JSON.stringify(error)}, ${JSON.stringify(fields)})`);
|
|
76
72
|
const event = Object.assign({}, (0, EventCreator_1.createErrorEvent)(error.name, error.message, error.stack));
|
|
77
|
-
let eventValidated =
|
|
73
|
+
let eventValidated = null;
|
|
74
|
+
if (fields) {
|
|
75
|
+
eventValidated = Object.assign({}, SendEventValidation_1.SendEventValidation.modifyEvent(fields));
|
|
76
|
+
}
|
|
78
77
|
eventValidated = Object.assign(Object.assign({}, event), eventValidated);
|
|
79
|
-
eventValidated
|
|
78
|
+
(0, EventModifierUtil_1.addIsApiReported)(eventValidated);
|
|
80
79
|
EventPipeline_1.EventPipeline.insertEvent(eventValidated);
|
|
81
80
|
}
|
|
82
|
-
sendEvent(properties
|
|
83
|
-
this.logger.debug(`sendEvent(${JSON.stringify(properties
|
|
81
|
+
sendEvent(properties) {
|
|
82
|
+
this.logger.debug(`sendEvent(${JSON.stringify(properties)})`);
|
|
84
83
|
const eventValidated = SendEventValidation_1.SendEventValidation.modifyEvent(properties);
|
|
85
|
-
if (eventValidated
|
|
86
|
-
eventValidated
|
|
84
|
+
if (eventValidated !== null) {
|
|
85
|
+
(0, EventModifierUtil_1.flagEventProperties)(eventValidated);
|
|
86
|
+
(0, EventModifierUtil_1.addIsApiReported)(eventValidated);
|
|
87
|
+
EventPipeline_1.EventPipeline.insertEvent(eventValidated);
|
|
87
88
|
}
|
|
88
|
-
EventPipeline_1.EventPipeline.insertEvent(eventValidated, context);
|
|
89
89
|
}
|
|
90
90
|
sendSessionPropertyEvent(properties) {
|
|
91
91
|
this.logger.debug(`sendSessionPropertyEvent(${JSON.stringify(properties)})`);
|
|
92
92
|
const eventValidated = SendEventValidation_1.SendSessionPropertyEventValidation.modifyEvent(properties);
|
|
93
|
-
if (eventValidated
|
|
94
|
-
(0, EventModifierUtil_1.containSessionProperties)(eventValidated)) {
|
|
95
|
-
|
|
93
|
+
if (eventValidated !== null) {
|
|
94
|
+
if ((0, EventModifierUtil_1.containSessionProperties)(eventValidated)) {
|
|
95
|
+
eventValidated["characteristics.has_session_properties"] = true;
|
|
96
|
+
}
|
|
97
|
+
(0, EventModifierUtil_1.addIsApiReported)(eventValidated);
|
|
98
|
+
EventPipeline_1.EventPipeline.insertEvent(eventValidated);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
sendHttpRequestEvent(httpRequestEventBuilder) {
|
|
102
|
+
const sanitizedEvent = httpRequestEventBuilder.build();
|
|
103
|
+
this.logger.debug(`sendHttpRequestEvent(${JSON.stringify(sanitizedEvent)})`);
|
|
104
|
+
if (sanitizedEvent !== null) {
|
|
105
|
+
(0, EventModifierUtil_1.flagEventProperties)(sanitizedEvent);
|
|
106
|
+
EventPipeline_1.EventPipeline.insertEvent(sanitizedEvent);
|
|
96
107
|
}
|
|
97
|
-
EventPipeline_1.EventPipeline.insertEvent(eventValidated);
|
|
98
108
|
}
|
|
99
109
|
}
|
|
100
110
|
exports.Dynatrace = new DynatraceImpl(TimestampProvider_1.defaultTimestampProvider);
|
|
@@ -22,7 +22,7 @@ class AppStartObserverImpl {
|
|
|
22
22
|
this.logger.debug(`emitter(${JSON.stringify(data)}})`);
|
|
23
23
|
const appStartEvent = (0, EventCreator_1.createAppStartEvent)(data);
|
|
24
24
|
if (appStartEvent != null) {
|
|
25
|
-
EventPipeline_1.EventPipeline.insertEvent(Object.assign({}, appStartEvent)
|
|
25
|
+
EventPipeline_1.EventPipeline.insertEvent(Object.assign({}, appStartEvent));
|
|
26
26
|
}
|
|
27
27
|
else {
|
|
28
28
|
this.logger.debug(`emitter(${JSON.stringify(data)}}): App Start event ignored!`);
|
|
@@ -26,7 +26,8 @@ const createErrorCodeEvent = (errorName, errorCode) => {
|
|
|
26
26
|
'error.is_fatal': false,
|
|
27
27
|
};
|
|
28
28
|
if (errorName != null) {
|
|
29
|
-
event["name"] = errorName;
|
|
29
|
+
event["error.name"] = errorName;
|
|
30
|
+
event["error.has_custom_name"] = true;
|
|
30
31
|
}
|
|
31
32
|
if (errorCode != null) {
|
|
32
33
|
event["error.code"] = errorCode;
|
|
@@ -20,19 +20,27 @@ class EventPipelineImpl {
|
|
|
20
20
|
ValueRestrictionModifier_1.ValueRestrictionModifier,
|
|
21
21
|
];
|
|
22
22
|
}
|
|
23
|
-
insertEvent(event
|
|
23
|
+
insertEvent(event) {
|
|
24
24
|
this.logger.debug(`insertEvent(${JSON.stringify(event)})`);
|
|
25
|
-
|
|
25
|
+
let isDiscarded = false;
|
|
26
|
+
for (const modifier of this.getEventModifierChain()) {
|
|
26
27
|
try {
|
|
27
|
-
|
|
28
|
+
const eventRv = modifier.modifyEvent(event);
|
|
29
|
+
if (eventRv == null) {
|
|
30
|
+
isDiscarded = true;
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
event = eventRv;
|
|
35
|
+
}
|
|
28
36
|
}
|
|
29
|
-
catch (
|
|
37
|
+
catch (_a) {
|
|
30
38
|
if (event != null) {
|
|
31
39
|
event["dt.support.api.has_enrich_exception"] = true;
|
|
32
40
|
}
|
|
33
41
|
}
|
|
34
|
-
}
|
|
35
|
-
if (event != null) {
|
|
42
|
+
}
|
|
43
|
+
if (event != null && !isDiscarded) {
|
|
36
44
|
this.logger.debug(`forwardEvent(${JSON.stringify(event)})`);
|
|
37
45
|
if (event["characteristics.has_app_start"] === true) {
|
|
38
46
|
DynatraceBridge_1.DynatraceNative.forwardAppStartEvent(event, EventSpecContstants_1.ALL_APP_START_KEYS);
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const ConsoleLogger_1 = require("../../core/logging/ConsoleLogger");
|
|
4
|
+
const SendEventValidation_1 = require("./modifier/SendEventValidation");
|
|
5
|
+
const TimestampProvider_1 = require("../provider/TimestampProvider");
|
|
6
|
+
const logger = new ConsoleLogger_1.ConsoleLogger('Dynatrace');
|
|
7
|
+
class HttpRequestEventBuilder {
|
|
8
|
+
constructor(url, requestMethod) {
|
|
9
|
+
this.url = url;
|
|
10
|
+
this.requestMethod = requestMethod;
|
|
11
|
+
this.duration = 0;
|
|
12
|
+
this.rawEventProperties = {};
|
|
13
|
+
this.hasDroppedTraceparent = false;
|
|
14
|
+
this.hasDroppedCustomProperties = false;
|
|
15
|
+
this.hasNfnValues = false;
|
|
16
|
+
this.triedToOverwriteDuration = false;
|
|
17
|
+
this.requestMethod =
|
|
18
|
+
requestMethod.toUpperCase();
|
|
19
|
+
}
|
|
20
|
+
withDuration(duration) {
|
|
21
|
+
this.duration = duration;
|
|
22
|
+
this.triedToOverwriteDuration = true;
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
withStatusCode(statusCode) {
|
|
26
|
+
this.statusCode = statusCode;
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
withReasonPhrase(reasonPhrase) {
|
|
30
|
+
this.reasonPhrase = reasonPhrase;
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
withError(error) {
|
|
34
|
+
this.error = error;
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
withBytesSent(bytesSent) {
|
|
38
|
+
this.bytesSent = bytesSent;
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
withBytesReceived(bytesReceived) {
|
|
42
|
+
this.bytesReceived = bytesReceived;
|
|
43
|
+
return this;
|
|
44
|
+
}
|
|
45
|
+
withTraceparentHeader(traceparentHeader) {
|
|
46
|
+
this.traceparentHeader = traceparentHeader;
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
addEventProperty(key, value) {
|
|
50
|
+
this.rawEventProperties[key] = value;
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
build() {
|
|
54
|
+
if (!this.hasValidMandatoryAttriutes()) {
|
|
55
|
+
logger.debug('HttpRequestEventBuilder dropped invalid event');
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
this.sanitizeDuration();
|
|
59
|
+
this.sanitizeStatusCode();
|
|
60
|
+
this.sanitizeReasonPhrase();
|
|
61
|
+
this.sanitizeBytesReceived();
|
|
62
|
+
this.sanitizeBytesSent();
|
|
63
|
+
const parsedTraceparentHeader = this.traceparentHeader &&
|
|
64
|
+
this.parseTraceparent(this.traceparentHeader);
|
|
65
|
+
this.hasDroppedTraceparent =
|
|
66
|
+
!!this.traceparentHeader && !parsedTraceparentHeader;
|
|
67
|
+
const hasFailedRequest = this.isStatusCodeError() || !!this.error;
|
|
68
|
+
const filteredEventProperties = Object.fromEntries(Object.entries(this.rawEventProperties).filter(this.isEventPropertyKey, this));
|
|
69
|
+
const sanitizedEventProperties = SendEventValidation_1.SendEventValidation.modifyEvent(filteredEventProperties);
|
|
70
|
+
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, sanitizedEventProperties), { ["url.full"]: this.url, ["network.protocol.name"]: 'http', ["http.request.method"]: this.requestMethod, ["duration"]: this.duration, ["start_time"]: TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp() - this.duration }), (this.triedToOverwriteDuration && {
|
|
71
|
+
["dt.support.api.overridden_fields"]: [
|
|
72
|
+
'duration',
|
|
73
|
+
],
|
|
74
|
+
})), this.includeIfDefined("http.response.status_code", this.statusCode)), this.includeIfDefined("http.response.reason_phrase", this.reasonPhrase)), this.includeIfDefined("request.bytes_sent", this.bytesSent)), this.includeIfDefined("request.bytes_received", this.bytesReceived)), { ["characteristics.has_request"]: true, ["characteristics.is_api_reported"]: true }), this.includeIfTrue("characteristics.has_failed_request", hasFailedRequest)), this.includeIfTrue("characteristics.has_error", hasFailedRequest)), (this.error !== undefined && Object.assign({ ["characteristics.has_exception"]: true, ["exception.type"]: this.error.name, ["exception.message"]: this.error.message }, this.includeIfDefined("exception.stack_trace", this.error.stack)))), (parsedTraceparentHeader && {
|
|
75
|
+
["trace.id"]: parsedTraceparentHeader.traceId,
|
|
76
|
+
["span.id"]: parsedTraceparentHeader.spanId,
|
|
77
|
+
})), (this.hasDroppedTraceparent && {
|
|
78
|
+
["request.trace_context_hint"]: 'invalid_header',
|
|
79
|
+
})), this.includeIfTrue("dt.support.api.has_dropped_custom_properties", this.hasDroppedCustomProperties)), this.includeIfTrue("dt.support.has_nfn_values", this.hasNfnValues));
|
|
80
|
+
}
|
|
81
|
+
hasValidMandatoryAttriutes() {
|
|
82
|
+
let isValid = true;
|
|
83
|
+
if (this.isInvalidUrl(this.url)) {
|
|
84
|
+
logger.debug(`HttpRequestEventBuilder: dropped event since given URL is malformed: ${this.url}`);
|
|
85
|
+
isValid = false;
|
|
86
|
+
}
|
|
87
|
+
if (!HttpRequestEventBuilder.allowedRequestMethods.includes(this.requestMethod)) {
|
|
88
|
+
logger.debug(`HttpRequestEventBuilder: dropped event since given Request Method is invalid: ${this.requestMethod}`);
|
|
89
|
+
isValid = false;
|
|
90
|
+
}
|
|
91
|
+
return isValid;
|
|
92
|
+
}
|
|
93
|
+
isInvalidUrl(url) {
|
|
94
|
+
try {
|
|
95
|
+
if (!url.match(/^(https?):\/\/[^\s/$.?#-][^\s]*$/i)) {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
new URL(url);
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
catch (_a) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
sanitizeStatusCode() {
|
|
106
|
+
if (this.statusCode == undefined && this.error === undefined) {
|
|
107
|
+
this.statusCode = 0;
|
|
108
|
+
}
|
|
109
|
+
if (this.statusCode && this.statusCode < 0) {
|
|
110
|
+
logger.debug('HttpRequestEventBuilder: overriding invalid Status Code with 0');
|
|
111
|
+
this.statusCode = 0;
|
|
112
|
+
this.hasDroppedCustomProperties = true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
sanitizeReasonPhrase() {
|
|
116
|
+
if (this.reasonPhrase &&
|
|
117
|
+
this.reasonPhrase.length >
|
|
118
|
+
HttpRequestEventBuilder.maxReasonPhraseLength) {
|
|
119
|
+
logger.debug(`HttpRequestEventBuilder: trimming too long Reason Phrase to a length of ${HttpRequestEventBuilder.maxReasonPhraseLength}`);
|
|
120
|
+
this.reasonPhrase = this.reasonPhrase.slice(0, HttpRequestEventBuilder.maxReasonPhraseLength);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
sanitizeDuration() {
|
|
124
|
+
this.hasNfnValues || (this.hasNfnValues = !Number.isFinite(this.duration));
|
|
125
|
+
if (!Number.isFinite(this.duration) || this.duration < 0) {
|
|
126
|
+
logger.debug('HttpRequestEventBuilder: overriding invalid Duration with 0');
|
|
127
|
+
this.duration = 0;
|
|
128
|
+
this.hasDroppedCustomProperties = true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
sanitizeBytesSent() {
|
|
132
|
+
if (this.bytesSent && this.bytesSent < 0) {
|
|
133
|
+
logger.debug(`HttpRequestEventBuilder: dropping invalid value for Bytes Sent: ${this.bytesSent}`);
|
|
134
|
+
this.bytesSent = undefined;
|
|
135
|
+
this.hasDroppedCustomProperties = true;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
sanitizeBytesReceived() {
|
|
139
|
+
if (this.bytesReceived && this.bytesReceived < 0) {
|
|
140
|
+
logger.debug(`HttpRequestEventBuilder: dropping invalid value for Bytes Received: ${this.bytesReceived}`);
|
|
141
|
+
this.bytesReceived = undefined;
|
|
142
|
+
this.hasDroppedCustomProperties = true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
isStatusCodeError() {
|
|
146
|
+
return (this.statusCode && 400 <= this.statusCode && this.statusCode <= 599);
|
|
147
|
+
}
|
|
148
|
+
isEventPropertyKey([key, _]) {
|
|
149
|
+
if (key.startsWith("event_properties")) {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
logger.debug(`HttpRequestEventBuilder: dropped event property '$key' as it did not start with prefix ${"event_properties"}`);
|
|
153
|
+
this.hasDroppedCustomProperties = true;
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
includeIfDefined(key, value) {
|
|
157
|
+
return value !== undefined ? { [key]: value } : {};
|
|
158
|
+
}
|
|
159
|
+
includeIfTrue(key, value) {
|
|
160
|
+
return value === true ? { [key]: value } : {};
|
|
161
|
+
}
|
|
162
|
+
parseTraceparent(header) {
|
|
163
|
+
const traceparentRegex = /^00-([0-9a-f]{32})-([0-9a-f]{16})-0[01]$/;
|
|
164
|
+
const match = header.match(traceparentRegex);
|
|
165
|
+
if (!match) {
|
|
166
|
+
logger.debug("The provided traceparent header does not match the format: '00-<trace-id-32-HEXDIG>-<parent-id-16-HEXDIG>-<trace-flags-2-HEXDIG>'");
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const [, traceId, spanId] = match;
|
|
170
|
+
if (this.allZeros(traceId)) {
|
|
171
|
+
logger.debug('Trace ID in traceparent header must not be all zeros');
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
if (this.allZeros(spanId)) {
|
|
175
|
+
logger.debug('Parent ID in traceparent header must not be all zeros');
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
return { traceId, spanId };
|
|
179
|
+
}
|
|
180
|
+
allZeros(str) {
|
|
181
|
+
return /^0*$/.test(str);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
exports.default = HttpRequestEventBuilder;
|
|
185
|
+
HttpRequestEventBuilder.allowedRequestMethods = [
|
|
186
|
+
'GET',
|
|
187
|
+
'HEAD',
|
|
188
|
+
'POST',
|
|
189
|
+
'PUT',
|
|
190
|
+
'DELETE',
|
|
191
|
+
'CONNECT',
|
|
192
|
+
'OPTIONS',
|
|
193
|
+
'TRACE',
|
|
194
|
+
'PATCH',
|
|
195
|
+
];
|
|
196
|
+
HttpRequestEventBuilder.maxReasonPhraseLength = 5000;
|
|
@@ -8,7 +8,7 @@ const ASCII_CODE_A = 65;
|
|
|
8
8
|
const NUMERICAL_CHARACTER_COUNT = 10;
|
|
9
9
|
const OFFSET_A = ASCII_CODE_A - NUMERICAL_CHARACTER_COUNT;
|
|
10
10
|
const createViewInfo = (name) => ({
|
|
11
|
-
["view.
|
|
11
|
+
["view.instance_id"]: createRandomHexString(VIEW_ID_LENGTH),
|
|
12
12
|
["view.name"]: name,
|
|
13
13
|
});
|
|
14
14
|
exports.createViewInfo = createViewInfo;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.BaseDataEventModifier = void 0;
|
|
4
4
|
const ConfigurationHandler_1 = require("../../../core/configuration/ConfigurationHandler");
|
|
5
5
|
const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger");
|
|
6
|
+
const EventModifierUtil_1 = require("./EventModifierUtil");
|
|
6
7
|
class BaseDataEventModifier {
|
|
7
8
|
constructor(viewInfo) {
|
|
8
9
|
this.viewInfo = viewInfo;
|
|
@@ -25,6 +26,11 @@ class BaseDataEventModifier {
|
|
|
25
26
|
event["react_native.bundle.version"] =
|
|
26
27
|
bundleVersion;
|
|
27
28
|
}
|
|
29
|
+
const reactNativeVersion = (0, EventModifierUtil_1.getReactNativeVersion)();
|
|
30
|
+
if (reactNativeVersion) {
|
|
31
|
+
event["react_native.version"] =
|
|
32
|
+
reactNativeVersion;
|
|
33
|
+
}
|
|
28
34
|
return event;
|
|
29
35
|
}
|
|
30
36
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.containEventPropertiesInArray = exports.containEventProperties = exports.containSessionProperties = exports.trimStringValuesInObject = exports.trimString = exports.isObject = exports.flattenAdditionalData = void 0;
|
|
3
|
+
exports.getReactNativeVersion = exports.containEventPropertiesInArray = exports.addIsApiReported = exports.flagEventProperties = exports.containEventProperties = exports.containSessionProperties = exports.trimStringValuesInObject = exports.trimString = exports.isObject = exports.flattenAdditionalData = void 0;
|
|
4
|
+
const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger");
|
|
4
5
|
const MAX_STRING_LENGTH_FOR_VALUES = 5000;
|
|
6
|
+
const logger = new ConsoleLogger_1.ConsoleLogger('EventModifierUtil');
|
|
5
7
|
const flattenAdditionalData = (obj, parent, res = {}) => {
|
|
6
8
|
for (const key in obj) {
|
|
7
9
|
const propName = parent != null ? parent + '.' + key : key;
|
|
@@ -60,6 +62,19 @@ const containEventProperties = (jsonData) => {
|
|
|
60
62
|
return false;
|
|
61
63
|
};
|
|
62
64
|
exports.containEventProperties = containEventProperties;
|
|
65
|
+
const flagEventProperties = (event) => {
|
|
66
|
+
if (event !== null && (0, exports.containEventProperties)(event)) {
|
|
67
|
+
event["characteristics.has_event_properties"] =
|
|
68
|
+
true;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
exports.flagEventProperties = flagEventProperties;
|
|
72
|
+
const addIsApiReported = (event) => {
|
|
73
|
+
if (event !== null) {
|
|
74
|
+
event["characteristics.is_api_reported"] = true;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
exports.addIsApiReported = addIsApiReported;
|
|
63
78
|
const containEventPropertiesInArray = (eventEntries) => {
|
|
64
79
|
for (const [key, value] of eventEntries) {
|
|
65
80
|
if (key.startsWith(`${"event_properties"}.`)) {
|
|
@@ -69,6 +84,24 @@ const containEventPropertiesInArray = (eventEntries) => {
|
|
|
69
84
|
return false;
|
|
70
85
|
};
|
|
71
86
|
exports.containEventPropertiesInArray = containEventPropertiesInArray;
|
|
87
|
+
const getReactNativeVersion = () => {
|
|
88
|
+
const candidates = [
|
|
89
|
+
() => require('react-native').ReactNativeVersion,
|
|
90
|
+
() => require('react-native/Libraries/Core/ReactNativeVersion').version,
|
|
91
|
+
];
|
|
92
|
+
for (const get of candidates) {
|
|
93
|
+
try {
|
|
94
|
+
const v = get();
|
|
95
|
+
if (v)
|
|
96
|
+
return toVersionString(v);
|
|
97
|
+
}
|
|
98
|
+
catch (_a) { }
|
|
99
|
+
}
|
|
100
|
+
logger.debug('Unable to determine React Native version');
|
|
101
|
+
return undefined;
|
|
102
|
+
};
|
|
103
|
+
exports.getReactNativeVersion = getReactNativeVersion;
|
|
104
|
+
const toVersionString = (v) => `${v.major}.${v.minor}.${v.patch}${v.prerelease ? `-${v.prerelease}` : ''}`;
|
|
72
105
|
const trimStringValuesInArray = (arrayData) => {
|
|
73
106
|
arrayData.forEach((value, index, array) => {
|
|
74
107
|
array[index] = trimStringValue(value);
|
|
@@ -26,17 +26,30 @@ class ModifyEventValidation {
|
|
|
26
26
|
if (this.customEventModifierChain.length > 0) {
|
|
27
27
|
const eventCopy = Object.assign({}, event);
|
|
28
28
|
let exceptionOccured = false;
|
|
29
|
-
|
|
29
|
+
let isDiscarded = false;
|
|
30
|
+
for (const modifier of this.customEventModifierChain) {
|
|
30
31
|
try {
|
|
31
|
-
|
|
32
|
+
const eventRv = modifier.modifyEvent(event);
|
|
33
|
+
if (eventRv === null) {
|
|
34
|
+
isDiscarded = true;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
event = eventRv;
|
|
39
|
+
}
|
|
32
40
|
}
|
|
33
|
-
catch (
|
|
41
|
+
catch (_a) {
|
|
34
42
|
if (event != null) {
|
|
35
43
|
exceptionOccured = true;
|
|
36
44
|
}
|
|
37
45
|
}
|
|
38
|
-
}
|
|
39
|
-
|
|
46
|
+
}
|
|
47
|
+
if (!isDiscarded) {
|
|
48
|
+
event = this.sanitizeUserEnrichedEvent(eventCopy, event, exceptionOccured);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
40
53
|
}
|
|
41
54
|
return event;
|
|
42
55
|
}
|
|
@@ -23,18 +23,17 @@ class SendEventValidationImpl {
|
|
|
23
23
|
}
|
|
24
24
|
const timeNow = this.timestampProvider.getCurrentTimestamp();
|
|
25
25
|
const eventCopy = Object.entries(event).slice();
|
|
26
|
-
const filteredEvent = eventCopy
|
|
27
|
-
.filter(this.isKeyNameAllowed, this)
|
|
28
|
-
.filter(this.isFieldTypeAllowed, this);
|
|
26
|
+
const filteredEvent = eventCopy.filter(this.isKeyNameAllowed, this);
|
|
29
27
|
const limitedEntries = new EventLimitation_1.EventLimitation().limitEventEntries(filteredEvent);
|
|
30
28
|
const sizedEntries = new EventLimitation_1.EventLimitation().limitEventProperties(limitedEntries);
|
|
31
|
-
this.applyOverriddenKeys(sizedEntries);
|
|
32
29
|
if (sizedEntries.length < eventCopy.length) {
|
|
33
30
|
sizedEntries.push([
|
|
34
31
|
"dt.support.api.has_dropped_custom_properties",
|
|
35
32
|
true,
|
|
36
33
|
]);
|
|
37
34
|
}
|
|
35
|
+
this.sanitizeDuration(sizedEntries);
|
|
36
|
+
this.applyOverriddenKeys(sizedEntries);
|
|
38
37
|
const jsonObject = Object.fromEntries(sizedEntries);
|
|
39
38
|
if (jsonObject["duration"] !== undefined) {
|
|
40
39
|
jsonObject["start_time"] =
|
|
@@ -60,13 +59,27 @@ class SendEventValidationImpl {
|
|
|
60
59
|
]);
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
key === "
|
|
67
|
-
|
|
62
|
+
sanitizeDuration(event) {
|
|
63
|
+
for (const entry of event) {
|
|
64
|
+
const [key, value] = entry;
|
|
65
|
+
if (key === "duration") {
|
|
66
|
+
if (typeof value !== 'number' ||
|
|
67
|
+
!isFinite(value) ||
|
|
68
|
+
value < 0) {
|
|
69
|
+
entry[1] = 0;
|
|
70
|
+
event.push([
|
|
71
|
+
"dt.support.api.has_dropped_custom_properties",
|
|
72
|
+
true,
|
|
73
|
+
]);
|
|
74
|
+
}
|
|
75
|
+
if (typeof value === 'number' && !isFinite(value)) {
|
|
76
|
+
event.push([
|
|
77
|
+
"dt.support.has_nfn_values",
|
|
78
|
+
true,
|
|
79
|
+
]);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
68
82
|
}
|
|
69
|
-
return true;
|
|
70
83
|
}
|
|
71
84
|
isKeyNameAllowed(entry) {
|
|
72
85
|
const [key] = entry;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ALL_APP_START_KEYS = exports.MODIFY_EVENT_WHITELIST_NAMESPACE = exports.MODIFY_EVENT_WHITELIST_FIELDS = exports.SEND_SESSION_PROPERTY_EVENT_WHITELIST_FIELDS = exports.SEND_EVENT_WHITELIST_FIELDS = exports.SEND_SESSION_PROPERTY_EVENT_WHITELIST_NAMESPACES = exports.SEND_EVENT_WHITELIST_NAMESPACES = exports.AllCharacteristicsKeys = exports.KEY_NAME_REGEX = exports.MAX_CUSTOM_EVENT_VALUE_LENGTH = exports.MAX_CUSTOM_EVENT_KEY_LENGTH = exports.MAX_CUSTOM_EVENT_FIELDS = void 0;
|
|
4
|
-
const SPECIFICATION_VERSION = '0.
|
|
4
|
+
const SPECIFICATION_VERSION = '0.22';
|
|
5
5
|
exports.MAX_CUSTOM_EVENT_FIELDS = 50;
|
|
6
6
|
exports.MAX_CUSTOM_EVENT_KEY_LENGTH = 100;
|
|
7
7
|
exports.MAX_CUSTOM_EVENT_VALUE_LENGTH = 5000;
|
|
@@ -41,6 +41,7 @@ exports.SEND_EVENT_WHITELIST_FIELDS = [
|
|
|
41
41
|
exports.SEND_SESSION_PROPERTY_EVENT_WHITELIST_FIELDS = exports.SEND_EVENT_WHITELIST_FIELDS;
|
|
42
42
|
exports.MODIFY_EVENT_WHITELIST_FIELDS = [
|
|
43
43
|
"exception.stack_trace",
|
|
44
|
+
"url.full",
|
|
44
45
|
];
|
|
45
46
|
exports.MODIFY_EVENT_WHITELIST_NAMESPACE = [
|
|
46
47
|
"session_properties",
|