@dynatrace/react-native-plugin 2.327.1 → 2.329.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 +426 -169
- 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-native/Touchables.js +9 -0
- 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 +220 -33
- package/lib/core/Dynatrace.js +8 -11
- package/lib/core/configuration/ConfigurationHandler.js +3 -0
- package/lib/next/Dynatrace.js +14 -32
- package/lib/next/DynatraceEventBus.js +35 -0
- package/lib/next/appstart/AppStartObserver.js +12 -16
- 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/{HttpRequestEventBuilder.js → HttpRequestEventData.js} +28 -52
- 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 +118 -26
- 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 +8 -3
- 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 +388 -158
- 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
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ModifyEventValidation = void 0;
|
|
4
4
|
const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger");
|
|
5
5
|
const EventSpecContstants_1 = require("../spec/EventSpecContstants");
|
|
6
|
-
const EventLimitation_1 = require("./EventLimitation");
|
|
7
6
|
const EventModifierUtil_1 = require("./EventModifierUtil");
|
|
8
7
|
class ModifyEventValidation {
|
|
9
8
|
constructor() {
|
|
@@ -53,29 +52,31 @@ class ModifyEventValidation {
|
|
|
53
52
|
}
|
|
54
53
|
return event;
|
|
55
54
|
}
|
|
56
|
-
|
|
55
|
+
isCustomPropertiesAllowed(key, hasSessionPropertyCharacteristics) {
|
|
57
56
|
if (hasSessionPropertyCharacteristics) {
|
|
58
57
|
if (key.startsWith(`${"event_properties"}.`)) {
|
|
59
58
|
this.logger.debug(`isPropertiesAllowed(): Filtering key ${key} as usage of event properties is not allowed!`);
|
|
60
|
-
return
|
|
59
|
+
return false;
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
62
|
else {
|
|
64
63
|
if (key.startsWith(`${"session_properties"}.`)) {
|
|
65
64
|
this.logger.debug(`isPropertiesAllowed(): Filtering key ${key} as usage of session properties is not allowed!`);
|
|
66
|
-
return
|
|
65
|
+
return false;
|
|
67
66
|
}
|
|
68
67
|
}
|
|
69
|
-
return
|
|
68
|
+
return true;
|
|
70
69
|
}
|
|
71
|
-
isKeyNameForbidden(key) {
|
|
70
|
+
isKeyNameForbidden(key, isAdded = false) {
|
|
72
71
|
for (const namespace of EventSpecContstants_1.MODIFY_EVENT_WHITELIST_NAMESPACE) {
|
|
73
72
|
if (key.startsWith(`${namespace}.`)) {
|
|
74
73
|
return false;
|
|
75
74
|
}
|
|
76
75
|
}
|
|
77
|
-
if (
|
|
78
|
-
|
|
76
|
+
if (!isAdded) {
|
|
77
|
+
if (EventSpecContstants_1.MODIFY_EVENT_WHITELIST_FIELDS.includes(key)) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
79
80
|
}
|
|
80
81
|
this.logger.debug(`isKeyNameForbidden(): Filtering key ${key} as this field is reserved and must not be overridden!`);
|
|
81
82
|
return true;
|
|
@@ -98,22 +99,16 @@ class ModifyEventValidation {
|
|
|
98
99
|
const restoredEntries = this.restoreRemovedEntries(Object.entries(originalEvent), userEnrichedEvent, overriddenKeys);
|
|
99
100
|
const validAndRestoredEntries = validEntries.concat(restoredEntries);
|
|
100
101
|
const { baseEntries, addedEntries } = this.determineAddedEntries(originalEvent, validAndRestoredEntries);
|
|
101
|
-
const
|
|
102
|
+
const limitedAddedEntries = this.validateAddedEntries(addedEntries);
|
|
102
103
|
if (originalEvent["characteristics.has_event_properties"] === undefined &&
|
|
103
|
-
(0, EventModifierUtil_1.containEventPropertiesInArray)(
|
|
104
|
-
|
|
104
|
+
(0, EventModifierUtil_1.containEventPropertiesInArray)(limitedAddedEntries)) {
|
|
105
|
+
limitedAddedEntries.push([
|
|
105
106
|
"characteristics.has_event_properties",
|
|
106
107
|
true,
|
|
107
108
|
]);
|
|
108
109
|
}
|
|
109
|
-
const finalEntries = baseEntries.concat(
|
|
110
|
-
const sizedEntries =
|
|
111
|
-
if (sizedEntries.length < userEnrichedEventEntries.length) {
|
|
112
|
-
sizedEntries.push([
|
|
113
|
-
"dt.support.api.has_dropped_custom_properties",
|
|
114
|
-
true,
|
|
115
|
-
]);
|
|
116
|
-
}
|
|
110
|
+
const finalEntries = baseEntries.concat(limitedAddedEntries);
|
|
111
|
+
const sizedEntries = this.enforcePropertyLimit(finalEntries);
|
|
117
112
|
if (Array.isArray(overriddenKeys) && overriddenKeys.length > 0) {
|
|
118
113
|
sizedEntries.push([
|
|
119
114
|
"dt.support.api.overridden_fields",
|
|
@@ -128,31 +123,70 @@ class ModifyEventValidation {
|
|
|
128
123
|
}
|
|
129
124
|
return Object.fromEntries(sizedEntries);
|
|
130
125
|
}
|
|
126
|
+
determineChangedContent(modifiedJSONEventEntries, originalJSONEvent) {
|
|
127
|
+
const changedEntries = [];
|
|
128
|
+
for (const [prop, value] of modifiedJSONEventEntries) {
|
|
129
|
+
const originalValue = originalJSONEvent[prop];
|
|
130
|
+
if (this.isModified(originalValue, value)) {
|
|
131
|
+
changedEntries.push([prop, value]);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return changedEntries;
|
|
136
|
+
}
|
|
131
137
|
determineValidEntries(userEnrichedEntries, originalJSONEvent, overriddenKeys) {
|
|
132
|
-
const
|
|
138
|
+
const validEntries = [];
|
|
139
|
+
let droppedCustomProperties = false;
|
|
140
|
+
let droppedProperties = false;
|
|
133
141
|
for (const [prop, value] of userEnrichedEntries) {
|
|
134
142
|
const originalValue = originalJSONEvent[prop];
|
|
135
143
|
if (!this.isModified(originalValue, value)) {
|
|
136
|
-
|
|
144
|
+
validEntries.push([prop, value]);
|
|
137
145
|
continue;
|
|
138
146
|
}
|
|
139
|
-
if (this.
|
|
147
|
+
if (!this.isCustomPropertiesAllowed(prop, originalJSONEvent["characteristics.has_session_properties"] === true)) {
|
|
148
|
+
droppedCustomProperties = true;
|
|
140
149
|
continue;
|
|
141
150
|
}
|
|
142
151
|
const isNewlyAdded = typeof originalValue === 'undefined';
|
|
143
|
-
const isForbiddenKey = this.isKeyNameForbidden(prop);
|
|
152
|
+
const isForbiddenKey = this.isKeyNameForbidden(prop, isNewlyAdded);
|
|
144
153
|
if (isForbiddenKey) {
|
|
145
154
|
if (!isNewlyAdded) {
|
|
146
|
-
|
|
155
|
+
validEntries.push([prop, originalValue]);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
droppedProperties = true;
|
|
147
159
|
}
|
|
148
160
|
continue;
|
|
149
161
|
}
|
|
150
162
|
if (!isNewlyAdded && !overriddenKeys.includes(prop)) {
|
|
151
163
|
overriddenKeys.push(prop);
|
|
152
164
|
}
|
|
153
|
-
|
|
165
|
+
if (!isNewlyAdded &&
|
|
166
|
+
EventSpecContstants_1.MODIFY_EVENT_WHITELIST_STRING_FIELDS.includes(prop)) {
|
|
167
|
+
const maximumLength = Math.max(originalJSONEvent[prop].toString().length, EventSpecContstants_1.MAX_CUSTOM_EVENT_VALUE_LENGTH);
|
|
168
|
+
validEntries.push([
|
|
169
|
+
prop,
|
|
170
|
+
(0, EventModifierUtil_1.trimString)(prop, value.toString(), maximumLength),
|
|
171
|
+
]);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
validEntries.push([prop, value]);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (droppedCustomProperties) {
|
|
178
|
+
validEntries.push([
|
|
179
|
+
"dt.support.api.has_dropped_custom_properties",
|
|
180
|
+
true,
|
|
181
|
+
]);
|
|
154
182
|
}
|
|
155
|
-
|
|
183
|
+
if (droppedProperties) {
|
|
184
|
+
validEntries.push([
|
|
185
|
+
"dt.support.api.has_dropped_properties",
|
|
186
|
+
true,
|
|
187
|
+
]);
|
|
188
|
+
}
|
|
189
|
+
return validEntries;
|
|
156
190
|
}
|
|
157
191
|
isModified(oldValue, newValue) {
|
|
158
192
|
if (Array.isArray(oldValue)) {
|
|
@@ -198,5 +232,63 @@ class ModifyEventValidation {
|
|
|
198
232
|
return entries;
|
|
199
233
|
}, resultEntries);
|
|
200
234
|
}
|
|
235
|
+
validateAddedEntries(addedEntries) {
|
|
236
|
+
const validEntries = [];
|
|
237
|
+
let droppedProperties = false;
|
|
238
|
+
let droppedCustomProperties = false;
|
|
239
|
+
for (const entry of addedEntries) {
|
|
240
|
+
if (!(0, EventModifierUtil_1.isNotObject)(entry) ||
|
|
241
|
+
!(0, EventModifierUtil_1.doesNotExceedKeySize)(entry) ||
|
|
242
|
+
!(0, EventModifierUtil_1.isKeySyntaxAllowed)(entry)) {
|
|
243
|
+
if ((0, EventModifierUtil_1.isKeyCustomProperty)(entry[0])) {
|
|
244
|
+
droppedCustomProperties = true;
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
droppedProperties = true;
|
|
248
|
+
}
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
(0, EventModifierUtil_1.restrictingValueSize)(entry);
|
|
252
|
+
validEntries.push(entry);
|
|
253
|
+
}
|
|
254
|
+
if (droppedCustomProperties) {
|
|
255
|
+
validEntries.push([
|
|
256
|
+
"dt.support.api.has_dropped_custom_properties",
|
|
257
|
+
true,
|
|
258
|
+
]);
|
|
259
|
+
}
|
|
260
|
+
if (droppedProperties) {
|
|
261
|
+
validEntries.push([
|
|
262
|
+
"dt.support.api.has_dropped_properties",
|
|
263
|
+
true,
|
|
264
|
+
]);
|
|
265
|
+
}
|
|
266
|
+
return validEntries;
|
|
267
|
+
}
|
|
268
|
+
enforcePropertyLimit(entries) {
|
|
269
|
+
const result = [];
|
|
270
|
+
let propertyCount = 0;
|
|
271
|
+
let droppedCustomProperties = false;
|
|
272
|
+
entries.sort((a, b) => a[0].localeCompare(b[0]));
|
|
273
|
+
for (const [key, value] of entries) {
|
|
274
|
+
if ((0, EventModifierUtil_1.isKeyCustomProperty)(key)) {
|
|
275
|
+
propertyCount++;
|
|
276
|
+
if (propertyCount > EventSpecContstants_1.MAX_CUSTOM_EVENT_FIELDS) {
|
|
277
|
+
this.logger.debug(`enforcePropertyLimit(): Dropped ${key} because overall ` +
|
|
278
|
+
`property limit (${EventSpecContstants_1.MAX_CUSTOM_EVENT_FIELDS}) is reached!`);
|
|
279
|
+
droppedCustomProperties = true;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
result.push([key, value]);
|
|
284
|
+
}
|
|
285
|
+
if (droppedCustomProperties) {
|
|
286
|
+
result.push([
|
|
287
|
+
"dt.support.api.has_dropped_custom_properties",
|
|
288
|
+
true,
|
|
289
|
+
]);
|
|
290
|
+
}
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
201
293
|
}
|
|
202
294
|
exports.ModifyEventValidation = ModifyEventValidation;
|
|
@@ -5,13 +5,13 @@ const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger");
|
|
|
5
5
|
const TimestampProvider_1 = require("../../provider/TimestampProvider");
|
|
6
6
|
const EventTimestamp_1 = require("../EventTimestamp");
|
|
7
7
|
const EventSpecContstants_1 = require("../spec/EventSpecContstants");
|
|
8
|
-
const
|
|
8
|
+
const EventModifierUtil_1 = require("./EventModifierUtil");
|
|
9
9
|
class SendEventValidationImpl {
|
|
10
10
|
constructor(timestampProvider, namespaceWhitelist, fieldWhitelist, loggerName) {
|
|
11
11
|
this.logger = new ConsoleLogger_1.ConsoleLogger(loggerName);
|
|
12
12
|
this.timestampProvider = timestampProvider;
|
|
13
|
-
this.fieldWhitelist = fieldWhitelist;
|
|
14
13
|
this.namespaceWhitelist = namespaceWhitelist;
|
|
14
|
+
this.fieldWhitelist = fieldWhitelist;
|
|
15
15
|
}
|
|
16
16
|
modifyEvent(event) {
|
|
17
17
|
this.logger.debug(`modifyEvent(${JSON.stringify(event)})`);
|
|
@@ -22,19 +22,10 @@ class SendEventValidationImpl {
|
|
|
22
22
|
return Object.assign({}, new EventTimestamp_1.EventTimestamp(this.timestampProvider).getEventTimeInfo());
|
|
23
23
|
}
|
|
24
24
|
const timeNow = this.timestampProvider.getCurrentTimestamp();
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
if (sizedEntries.length < eventCopy.length) {
|
|
30
|
-
sizedEntries.push([
|
|
31
|
-
"dt.support.api.has_dropped_custom_properties",
|
|
32
|
-
true,
|
|
33
|
-
]);
|
|
34
|
-
}
|
|
35
|
-
this.sanitizeDuration(sizedEntries);
|
|
36
|
-
this.applyOverriddenKeys(sizedEntries);
|
|
37
|
-
const jsonObject = Object.fromEntries(sizedEntries);
|
|
25
|
+
const filteredEvent = this.checkEventEntries(Object.entries(event).slice());
|
|
26
|
+
this.sanitizeDuration(filteredEvent);
|
|
27
|
+
this.applyOverriddenKeys(filteredEvent);
|
|
28
|
+
const jsonObject = Object.fromEntries(filteredEvent);
|
|
38
29
|
if (jsonObject["duration"] !== undefined) {
|
|
39
30
|
jsonObject["start_time"] =
|
|
40
31
|
timeNow - jsonObject["duration"];
|
|
@@ -47,7 +38,7 @@ class SendEventValidationImpl {
|
|
|
47
38
|
}
|
|
48
39
|
applyOverriddenKeys(eventEntries) {
|
|
49
40
|
const overriddenKeys = [];
|
|
50
|
-
for (const [key
|
|
41
|
+
for (const [key] of eventEntries) {
|
|
51
42
|
if (this.fieldWhitelist.includes(key)) {
|
|
52
43
|
overriddenKeys.push(key);
|
|
53
44
|
}
|
|
@@ -68,18 +59,58 @@ class SendEventValidationImpl {
|
|
|
68
59
|
value < 0) {
|
|
69
60
|
entry[1] = 0;
|
|
70
61
|
event.push([
|
|
71
|
-
"dt.support.api.
|
|
62
|
+
"dt.support.api.has_dropped_properties",
|
|
72
63
|
true,
|
|
73
64
|
]);
|
|
65
|
+
break;
|
|
74
66
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
checkEventEntries(allEntries) {
|
|
71
|
+
const fieldEntries = allEntries.slice();
|
|
72
|
+
fieldEntries.sort((a, b) => a[0].localeCompare(b[0]));
|
|
73
|
+
const validEntries = [];
|
|
74
|
+
let droppedProperties = false;
|
|
75
|
+
let droppedCustomProperties = false;
|
|
76
|
+
let amountOfCustomProperties = 0;
|
|
77
|
+
fieldEntries.forEach((entry) => {
|
|
78
|
+
if (!this.isKeyNameAllowed(entry) ||
|
|
79
|
+
!(0, EventModifierUtil_1.isNotObject)(entry) ||
|
|
80
|
+
!(0, EventModifierUtil_1.doesNotExceedKeySize)(entry) ||
|
|
81
|
+
!(0, EventModifierUtil_1.isKeySyntaxAllowed)(entry)) {
|
|
82
|
+
if ((0, EventModifierUtil_1.isKeyCustomProperty)(entry[0])) {
|
|
83
|
+
droppedCustomProperties = true;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
droppedProperties = true;
|
|
80
87
|
}
|
|
88
|
+
return;
|
|
81
89
|
}
|
|
90
|
+
if ((0, EventModifierUtil_1.isKeyCustomProperty)(entry[0])) {
|
|
91
|
+
amountOfCustomProperties++;
|
|
92
|
+
if (amountOfCustomProperties > EventSpecContstants_1.MAX_CUSTOM_EVENT_FIELDS) {
|
|
93
|
+
this.logger.debug(`limitEventProperties(): Dropped ${entry[0]} because overall property limit is reached!`);
|
|
94
|
+
droppedCustomProperties = true;
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
(0, EventModifierUtil_1.restrictingValueSize)(entry);
|
|
99
|
+
validEntries.push(entry);
|
|
100
|
+
});
|
|
101
|
+
if (droppedCustomProperties) {
|
|
102
|
+
validEntries.push([
|
|
103
|
+
"dt.support.api.has_dropped_custom_properties",
|
|
104
|
+
true,
|
|
105
|
+
]);
|
|
106
|
+
}
|
|
107
|
+
if (droppedProperties) {
|
|
108
|
+
validEntries.push([
|
|
109
|
+
"dt.support.api.has_dropped_properties",
|
|
110
|
+
true,
|
|
111
|
+
]);
|
|
82
112
|
}
|
|
113
|
+
return validEntries;
|
|
83
114
|
}
|
|
84
115
|
isKeyNameAllowed(entry) {
|
|
85
116
|
const [key] = entry;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StringLengthEventModifier = void 0;
|
|
4
|
+
const ConsoleLogger_1 = require("../../../core/logging/ConsoleLogger");
|
|
5
|
+
const EventSpecContstants_1 = require("../spec/EventSpecContstants");
|
|
6
|
+
const EventModifierUtil_1 = require("./EventModifierUtil");
|
|
7
|
+
class StringLengthEventModifier {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.logger = new ConsoleLogger_1.ConsoleLogger('StringLengthEventModifier');
|
|
10
|
+
}
|
|
11
|
+
modifyEvent(event) {
|
|
12
|
+
if (event == null) {
|
|
13
|
+
this.logger.debug(`modifyEvent(${JSON.stringify(event)}): Event is null!`);
|
|
14
|
+
return event;
|
|
15
|
+
}
|
|
16
|
+
if (event["characteristics.is_api_reported"] ===
|
|
17
|
+
true) {
|
|
18
|
+
this.trimStringValuesInObject(event);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this.trimStringValuesInObject(event, EventSpecContstants_1.EVENT_WHITELIST_SIZE);
|
|
22
|
+
}
|
|
23
|
+
return event;
|
|
24
|
+
}
|
|
25
|
+
trimStringValuesInObject(jsonData, keyWhitelist = []) {
|
|
26
|
+
for (const key in jsonData) {
|
|
27
|
+
if (!keyWhitelist.includes(key) &&
|
|
28
|
+
Object.prototype.hasOwnProperty.call(jsonData, key)) {
|
|
29
|
+
jsonData[key] = this.trimStringValue(key, jsonData[key]);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return jsonData;
|
|
33
|
+
}
|
|
34
|
+
trimStringValuesInArray(key, arrayData) {
|
|
35
|
+
arrayData.forEach((value, index, array) => {
|
|
36
|
+
array[index] = this.trimStringValue(key, value);
|
|
37
|
+
});
|
|
38
|
+
return arrayData;
|
|
39
|
+
}
|
|
40
|
+
trimStringValue(key, data) {
|
|
41
|
+
if (typeof data === 'string') {
|
|
42
|
+
return (0, EventModifierUtil_1.trimString)(key, data, EventSpecContstants_1.MAX_CUSTOM_EVENT_VALUE_LENGTH);
|
|
43
|
+
}
|
|
44
|
+
else if (Array.isArray(data)) {
|
|
45
|
+
return this.trimStringValuesInArray(key, data);
|
|
46
|
+
}
|
|
47
|
+
else if ((0, EventModifierUtil_1.isObject)(data)) {
|
|
48
|
+
return this.trimStringValuesInObject(data);
|
|
49
|
+
}
|
|
50
|
+
return data;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.StringLengthEventModifier = StringLengthEventModifier;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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.
|
|
3
|
+
exports.ALL_APP_START_KEYS = exports.EVENT_WHITELIST_SIZE = exports.MODIFY_EVENT_WHITELIST_NAMESPACE = exports.MODIFY_EVENT_WHITELIST_STRING_FIELDS = 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.23';
|
|
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;
|
|
@@ -43,10 +43,17 @@ exports.MODIFY_EVENT_WHITELIST_FIELDS = [
|
|
|
43
43
|
"exception.stack_trace",
|
|
44
44
|
"url.full",
|
|
45
45
|
];
|
|
46
|
+
exports.MODIFY_EVENT_WHITELIST_STRING_FIELDS = [
|
|
47
|
+
"exception.stack_trace",
|
|
48
|
+
"url.full",
|
|
49
|
+
];
|
|
46
50
|
exports.MODIFY_EVENT_WHITELIST_NAMESPACE = [
|
|
47
51
|
"session_properties",
|
|
48
52
|
"event_properties",
|
|
49
53
|
];
|
|
54
|
+
exports.EVENT_WHITELIST_SIZE = [
|
|
55
|
+
"exception.stack_trace",
|
|
56
|
+
];
|
|
50
57
|
const appStartKeyMap = {
|
|
51
58
|
["app_start.react_native.content_appeared"]: null,
|
|
52
59
|
["app_start.react_native.download.end_time"]: null,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynatrace/react-native-plugin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.329.1",
|
|
4
4
|
"description": "This plugin gives you the ability to use the Dynatrace Mobile agent in your react native application.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "types.d.ts",
|
|
@@ -26,8 +26,9 @@
|
|
|
26
26
|
"test": "jest --runInBand",
|
|
27
27
|
"test:debug": "node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand",
|
|
28
28
|
"test:local": "npm run lint && node runner.js test",
|
|
29
|
+
"test:examples": "node tests/jsdoc_examples/RunJestTest.js",
|
|
29
30
|
"tsc:local": "tsc -p tsconfig.local.json",
|
|
30
|
-
"tsc:types": "tsc -p tsconfig.types.json && rollup -c rollup.config.types.
|
|
31
|
+
"tsc:types": "tsc -p tsconfig.types.json && rollup -c rollup.config.types.mjs",
|
|
31
32
|
"tsc": "tsc",
|
|
32
33
|
"tsc:prod": "tsc -p tsconfig.release.json",
|
|
33
34
|
"lint": "eslint --cache src/**/*.ts --ignore-pattern .gitignore",
|
|
@@ -47,7 +48,7 @@
|
|
|
47
48
|
"author": "Dynatrace",
|
|
48
49
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
49
50
|
"dependencies": {
|
|
50
|
-
"@babel/runtime": "^7.28.
|
|
51
|
+
"@babel/runtime": "^7.28.6",
|
|
51
52
|
"jscodeshift": "^17.3.0",
|
|
52
53
|
"plist": "^3.1.0",
|
|
53
54
|
"proxy-polyfill": "^0.3.2",
|
|
@@ -76,6 +77,8 @@
|
|
|
76
77
|
"@babel/preset-env": "^7.27.2",
|
|
77
78
|
"@babel/preset-react": "^7.27.1",
|
|
78
79
|
"@react-native/babel-preset": "^0.80.1",
|
|
80
|
+
"@react-navigation/core": "^7.13.0",
|
|
81
|
+
"@react-navigation/drawer": "^7.7.2",
|
|
79
82
|
"@testing-library/react-native": "^13.2.0",
|
|
80
83
|
"@types/jest": "^30.0.0",
|
|
81
84
|
"@types/jscodeshift": "^17.3.0",
|
|
@@ -157,7 +160,9 @@
|
|
|
157
160
|
"lib/metro/*.js",
|
|
158
161
|
"lib/next/*.js",
|
|
159
162
|
"lib/next/appstart/*.js",
|
|
163
|
+
"lib/next/configuration/*.js",
|
|
160
164
|
"lib/next/events/*.js",
|
|
165
|
+
"lib/next/events/interface/*.js",
|
|
161
166
|
"lib/next/events/modifier/*.js",
|
|
162
167
|
"lib/next/events/spec/*.js",
|
|
163
168
|
"lib/next/provider/*.js",
|
package/public.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ExceptionEventData = exports.SessionPropertyEventData = exports.EventData = exports.HttpRequestEventData = exports.DynatraceWebRequestTiming = exports.UserPrivacyOptions = exports.LogLevel = exports.Platform = exports.ConfigurationBuilder = exports.ManualStartupConfiguration = exports.DataCollectionLevel = exports.Dynatrace = void 0;
|
|
4
4
|
var Dynatrace_1 = require("./lib/core/Dynatrace");
|
|
5
5
|
Object.defineProperty(exports, "Dynatrace", { enumerable: true, get: function () { return Dynatrace_1.Dynatrace; } });
|
|
6
6
|
var DataCollectionLevel_1 = require("./lib/core/model/DataCollectionLevel");
|
|
@@ -17,6 +17,12 @@ var UserPrivacyOptions_1 = require("./lib/core/UserPrivacyOptions");
|
|
|
17
17
|
Object.defineProperty(exports, "UserPrivacyOptions", { enumerable: true, get: function () { return UserPrivacyOptions_1.UserPrivacyOptions; } });
|
|
18
18
|
var DynatraceWebRequestTiming_1 = require("./lib/core/DynatraceWebRequestTiming");
|
|
19
19
|
Object.defineProperty(exports, "DynatraceWebRequestTiming", { enumerable: true, get: function () { return DynatraceWebRequestTiming_1.DynatraceWebRequestTiming; } });
|
|
20
|
-
var
|
|
21
|
-
Object.defineProperty(exports, "
|
|
20
|
+
var HttpRequestEventData_1 = require("./lib/next/events/HttpRequestEventData");
|
|
21
|
+
Object.defineProperty(exports, "HttpRequestEventData", { enumerable: true, get: function () { return HttpRequestEventData_1.default; } });
|
|
22
|
+
var EventData_1 = require("./lib/next/events/EventData");
|
|
23
|
+
Object.defineProperty(exports, "EventData", { enumerable: true, get: function () { return EventData_1.default; } });
|
|
24
|
+
var SessionPropertyEventData_1 = require("./lib/next/events/SessionPropertyEventData");
|
|
25
|
+
Object.defineProperty(exports, "SessionPropertyEventData", { enumerable: true, get: function () { return SessionPropertyEventData_1.default; } });
|
|
26
|
+
var ExceptionEventData_1 = require("./lib/next/events/ExceptionEventData");
|
|
27
|
+
Object.defineProperty(exports, "ExceptionEventData", { enumerable: true, get: function () { return ExceptionEventData_1.default; } });
|
|
22
28
|
require("./react-augmentation");
|
|
@@ -111,7 +111,7 @@ Pod::Spec.new do |s|
|
|
|
111
111
|
#
|
|
112
112
|
|
|
113
113
|
s.dependency "React"
|
|
114
|
-
s.dependency 'Dynatrace', '~> 8.
|
|
114
|
+
s.dependency 'Dynatrace', '~> 8.329.1.1017'
|
|
115
115
|
|
|
116
116
|
# Allows for better compatibility for older and newer versions
|
|
117
117
|
if defined?(install_modules_dependencies)
|
package/scripts/Config.js
CHANGED
|
@@ -31,8 +31,12 @@ exports.defaultConfig = {
|
|
|
31
31
|
instrument: (filename) => true,
|
|
32
32
|
actionNamePrivacy: false,
|
|
33
33
|
},
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
navigation: {
|
|
35
|
+
enabled: true,
|
|
36
|
+
},
|
|
37
|
+
sourcemap: {
|
|
38
|
+
enabled: true,
|
|
39
|
+
androidSourcemapLocation: 'app/build/generated/sourcemaps/react/release/index.android.bundle.map',
|
|
36
40
|
},
|
|
37
41
|
},
|
|
38
42
|
};
|
|
@@ -14,13 +14,10 @@ module.exports = (() => {
|
|
|
14
14
|
}
|
|
15
15
|
return acc;
|
|
16
16
|
}, {});
|
|
17
|
-
const isProd = parsedArgs.env === 'prod';
|
|
18
17
|
const options = {
|
|
19
|
-
isProd,
|
|
20
18
|
projectRoot: parsedArgs.projectRoot || PathsConstants_1.default.getApplicationPath(),
|
|
21
19
|
buildPath: parsedArgs.buildPath || PathsConstants_1.default.getBuildPath(),
|
|
22
|
-
|
|
23
|
-
iosSourcemapPath: parsedArgs.iosSourcemapPath || '',
|
|
20
|
+
sourcemapPath: parsedArgs.sourcemapPath,
|
|
24
21
|
appBundleInfo: Object.assign(Object.assign({}, (0, GetValuesFromPackage_1.getHostAppBundleInfo)(PathsConstants_1.default.getPackageJsonFile())), { pluginVersion: (_b = (_a = (0, GetValuesFromPackage_1.getHostAppBundleInfo)(PathsConstants_1.default.getInternalPackageJsonFile(), true)) === null || _a === void 0 ? void 0 : _a.version) !== null && _b !== void 0 ? _b : '0' }),
|
|
25
22
|
};
|
|
26
23
|
const analyzer = new LineOffsetAnalyzeCall_1.LineOffsetAnalyzer(options);
|
|
@@ -17,6 +17,10 @@ const Logger_1 = require("../Logger");
|
|
|
17
17
|
const InstrumentUtil_1 = require("../util/InstrumentUtil");
|
|
18
18
|
const FileOperationHelper_1 = require("../../scripts/FileOperationHelper");
|
|
19
19
|
const ReactOptions_1 = require("../util/ReactOptions");
|
|
20
|
+
const config = require("../../scripts/Config");
|
|
21
|
+
const CustomArgumentUtil_1 = require("../../scripts/util/CustomArgumentUtil");
|
|
22
|
+
const PathsConstants_1 = require("../../scripts/PathsConstants");
|
|
23
|
+
const customArguments = (0, CustomArgumentUtil_1.readCustomArguments)();
|
|
20
24
|
class LineOffsetAnalyzer {
|
|
21
25
|
constructor(options) {
|
|
22
26
|
this.rootDir = (0, path_1.resolve)(options.projectRoot);
|
|
@@ -24,11 +28,10 @@ class LineOffsetAnalyzer {
|
|
|
24
28
|
this.outputFile = (0, path_1.resolve)(this.instrumentedDir, 'line-offsets.json');
|
|
25
29
|
this.logFile = (0, path_1.resolve)(this.instrumentedDir, 'debug.log');
|
|
26
30
|
this.appBundleInfo = options.appBundleInfo;
|
|
27
|
-
this.
|
|
28
|
-
this.androidSourcemapPath = options.androidSourcemapPath;
|
|
29
|
-
this.iosSourcemapPath = options.iosSourcemapPath;
|
|
31
|
+
this.sourcemapPath = options.sourcemapPath;
|
|
30
32
|
}
|
|
31
33
|
run() {
|
|
34
|
+
var _a;
|
|
32
35
|
return __awaiter(this, void 0, void 0, function* () {
|
|
33
36
|
try {
|
|
34
37
|
const buildExists = yield FileOperationHelper_1.default.checkIfFileExists(this.instrumentedDir);
|
|
@@ -76,23 +79,30 @@ class LineOffsetAnalyzer {
|
|
|
76
79
|
};
|
|
77
80
|
yield fs.writeFile(this.outputFile, JSON.stringify(finalOutput, null, 2));
|
|
78
81
|
yield this.log(`✅ Line offsets written to ${this.outputFile}`, true);
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
82
|
+
let reactOptions;
|
|
83
|
+
if (customArguments.isCustomConfigurationPathSet()) {
|
|
84
|
+
reactOptions = config.readConfig((0, path_1.join)(PathsConstants_1.default.getApplicationPath(), customArguments.getCustomConfigurationPath()));
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
reactOptions = config.readConfig((0, path_1.join)(PathsConstants_1.default.getConfigFilePath()));
|
|
88
|
+
}
|
|
89
|
+
if (!this.sourcemapPath && !reactOptions.react.sourcemap.enabled) {
|
|
90
|
+
const message = 'ℹ️ Automatic sourcemap patching disabled. Skipping sourcemap patching.';
|
|
91
|
+
yield this.log(message);
|
|
92
|
+
console.info(message);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const loadedMap = yield this.loadSourceMap((_a = this.sourcemapPath) !== null && _a !== void 0 ? _a : reactOptions.react.sourcemap.androidSourcemapLocation);
|
|
96
|
+
if (loadedMap) {
|
|
97
|
+
const { map, path: originalMapPath } = loadedMap;
|
|
98
|
+
map.x_dynatrace_offset = mappings;
|
|
99
|
+
const backupPath = originalMapPath + '.bak';
|
|
100
|
+
const serilalisedPath = originalMapPath + '.serialised';
|
|
101
|
+
yield fs.copyFile(originalMapPath, backupPath);
|
|
102
|
+
yield this.log(`💾 Backup created: ${backupPath}`);
|
|
103
|
+
yield fs.writeFile(originalMapPath, JSON.stringify(map));
|
|
104
|
+
yield fs.writeFile(serilalisedPath, JSON.stringify(map, null, 2));
|
|
105
|
+
yield this.log(`📝 Patched source map written to: ${originalMapPath}`);
|
|
96
106
|
}
|
|
97
107
|
}
|
|
98
108
|
catch (err) {
|
|
@@ -100,35 +110,18 @@ class LineOffsetAnalyzer {
|
|
|
100
110
|
}
|
|
101
111
|
});
|
|
102
112
|
}
|
|
103
|
-
loadSourceMap() {
|
|
113
|
+
loadSourceMap(mapPath) {
|
|
104
114
|
return __awaiter(this, void 0, void 0, function* () {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
];
|
|
111
|
-
let foundAny = false;
|
|
112
|
-
for (const mapPath of possiblePaths) {
|
|
113
|
-
try {
|
|
114
|
-
const exists = yield FileOperationHelper_1.default.checkIfFileExists(mapPath);
|
|
115
|
-
if (!exists) {
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
foundAny = true;
|
|
119
|
-
const content = yield fs.readFile(mapPath, 'utf-8');
|
|
120
|
-
const parsed = JSON.parse(content);
|
|
121
|
-
yield this.log(`🗺️ Found and parsed source map at: ${mapPath}`, true);
|
|
122
|
-
return { map: parsed, path: mapPath };
|
|
123
|
-
}
|
|
124
|
-
catch (err) {
|
|
125
|
-
yield this.log(`⚠️ Failed to load or parse source map at ${mapPath}: ${err.message}`, true);
|
|
126
|
-
}
|
|
115
|
+
try {
|
|
116
|
+
const content = yield fs.readFile(mapPath, 'utf-8');
|
|
117
|
+
const parsed = JSON.parse(content);
|
|
118
|
+
yield this.log(`🗺️ Found and parsed source map at: ${mapPath}`, true);
|
|
119
|
+
return { map: parsed, path: mapPath };
|
|
127
120
|
}
|
|
128
|
-
|
|
129
|
-
yield this.log(
|
|
121
|
+
catch (err) {
|
|
122
|
+
yield this.log(`⚠️ Failed to load or parse source map at ${mapPath}: ${err.message} - skipping patching step`, true);
|
|
123
|
+
return null;
|
|
130
124
|
}
|
|
131
|
-
return null;
|
|
132
125
|
});
|
|
133
126
|
}
|
|
134
127
|
log(msg, logOnScreen = false) {
|