@dynatrace/react-native-plugin 2.327.2 → 2.331.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 +419 -164
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceConfigurationModule.kt +48 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +41 -8
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceReactPackage.kt +3 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceRuntimeConfigurationStore.kt +14 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.kt +103 -47
- package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +12 -4
- package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +15 -5
- package/files/default.config.js +7 -0
- package/files/plugin-runtime.gradle +7 -17
- package/files/plugin.gradle +1 -1
- package/instrumentation/DynatraceInstrumentation.js +1 -1
- package/instrumentation/libs/react-navigation/ReactNavigation.js +53 -18
- package/ios/ConfigurationSubscriber.h +15 -0
- package/ios/DynatraceRNBridge.h +4 -0
- package/ios/DynatraceRNBridge.mm +125 -29
- package/lib/core/Dynatrace.js +8 -11
- package/lib/core/configuration/ConfigurationHandler.js +3 -0
- package/lib/next/Dynatrace.js +50 -33
- package/lib/next/DynatraceArgValidators.js +10 -0
- package/lib/next/DynatraceEventBus.js +35 -0
- package/lib/next/appstart/AppStartObserver.js +2 -3
- package/lib/next/configuration/INativeRuntimeConfiguration.js +7 -0
- package/lib/next/configuration/RuntimeConfigurationObserver.js +40 -0
- package/lib/next/events/EventBuilderUtil.js +7 -0
- package/lib/next/events/EventData.js +28 -0
- package/lib/next/events/EventPipeline.js +5 -11
- package/lib/next/events/ExceptionEventData.js +26 -0
- package/lib/next/events/HttpRequestEventData.js +174 -0
- package/lib/next/events/SessionPropertyEventData.js +22 -0
- package/lib/next/events/interface/IBaseEvent.js +2 -0
- package/lib/next/events/interface/IEventData.js +2 -0
- package/lib/next/events/interface/IExceptionEventData.js +2 -0
- package/lib/next/events/interface/IHttpRequestEventData.js +2 -0
- package/lib/next/events/interface/ISessionPropertyEventData.js +2 -0
- package/lib/next/events/modifier/BaseDataEventModifier.js +1 -3
- package/lib/next/events/modifier/EventModifierUtil.js +34 -41
- package/lib/next/events/modifier/ModifyEventValidation.js +117 -27
- package/lib/next/events/modifier/SendEventValidation.js +53 -22
- package/lib/next/events/modifier/StringLengthEventModifier.js +53 -0
- package/lib/next/events/spec/EventSpecContstants.js +9 -2
- package/package.json +11 -5
- package/public.js +9 -3
- package/react-native-dynatrace.podspec +1 -1
- package/scripts/Config.js +6 -2
- package/scripts/LineOffsetAnalyze.js +1 -4
- package/scripts/core/LineOffsetAnalyzeCall.js +39 -46
- package/src/lib/core/interface/NativeDynatraceBridge.ts +6 -2
- package/types.d.ts +408 -177
- package/lib/next/events/HttpRequestEventBuilder.js +0 -196
- package/lib/next/events/ViewInfoCreator.js +0 -27
- package/lib/next/events/modifier/EventLimitation.js +0 -69
- /package/lib/next/events/{IHttpRequestEventBuilder.js → interface/EventProperty.js} +0 -0
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const ConsoleLogger_1 = require("../../core/logging/ConsoleLogger");
|
|
4
|
-
const TimestampProvider_1 = require("../provider/TimestampProvider");
|
|
5
|
-
const SendEventValidation_1 = require("./modifier/SendEventValidation");
|
|
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.traceContextHint = "api_unused";
|
|
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
|
-
this.traceContextHint = "api_set";
|
|
48
|
-
return this;
|
|
49
|
-
}
|
|
50
|
-
addEventProperty(key, value) {
|
|
51
|
-
this.rawEventProperties[key] = value;
|
|
52
|
-
return this;
|
|
53
|
-
}
|
|
54
|
-
build() {
|
|
55
|
-
if (!this.hasValidMandatoryAttriutes()) {
|
|
56
|
-
logger.debug('HttpRequestEventBuilder dropped invalid event');
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
this.sanitizeDuration();
|
|
60
|
-
this.sanitizeStatusCode();
|
|
61
|
-
this.sanitizeReasonPhrase();
|
|
62
|
-
this.sanitizeBytesReceived();
|
|
63
|
-
this.sanitizeBytesSent();
|
|
64
|
-
const parsedTraceparentHeader = this.traceparentHeader &&
|
|
65
|
-
this.parseTraceparent(this.traceparentHeader);
|
|
66
|
-
if (!!this.traceparentHeader && !parsedTraceparentHeader) {
|
|
67
|
-
this.traceContextHint = "invalid";
|
|
68
|
-
}
|
|
69
|
-
const hasFailedRequest = this.isStatusCodeError() || !!this.error;
|
|
70
|
-
const filteredEventProperties = Object.fromEntries(Object.entries(this.rawEventProperties).filter(this.isEventPropertyKey, this));
|
|
71
|
-
const sanitizedEventProperties = SendEventValidation_1.SendEventValidation.modifyEvent(filteredEventProperties);
|
|
72
|
-
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({}, sanitizedEventProperties), { ["url.full"]: this.url, ["network.protocol.name"]: 'http', ["http.request.method"]: this.requestMethod, ["request.trace_context_hint"]: this.traceContextHint, ["duration"]: this.duration, ["start_time"]: TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp() - this.duration }), (this.triedToOverwriteDuration && {
|
|
73
|
-
["dt.support.api.overridden_fields"]: [
|
|
74
|
-
'duration',
|
|
75
|
-
],
|
|
76
|
-
})), 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 && {
|
|
77
|
-
["trace.id"]: parsedTraceparentHeader.traceId,
|
|
78
|
-
["span.id"]: parsedTraceparentHeader.spanId,
|
|
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;
|
|
@@ -1,27 +0,0 @@
|
|
|
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.instance_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
|
-
};
|
|
@@ -1,69 +0,0 @@
|
|
|
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;
|
|
File without changes
|