@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.
Files changed (53) hide show
  1. package/README.md +426 -169
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/com/dynatrace/android/agent/DynatraceConfigurationModule.kt +48 -0
  4. package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +41 -8
  5. package/android/src/main/java/com/dynatrace/android/agent/DynatraceReactPackage.kt +3 -0
  6. package/android/src/main/java/com/dynatrace/android/agent/DynatraceRuntimeConfigurationStore.kt +14 -0
  7. package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.kt +103 -47
  8. package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +12 -4
  9. package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +15 -5
  10. package/files/default.config.js +7 -0
  11. package/files/plugin-runtime.gradle +7 -17
  12. package/files/plugin.gradle +1 -1
  13. package/instrumentation/DynatraceInstrumentation.js +1 -1
  14. package/instrumentation/libs/react-native/Touchables.js +9 -0
  15. package/instrumentation/libs/react-navigation/ReactNavigation.js +53 -18
  16. package/ios/ConfigurationSubscriber.h +15 -0
  17. package/ios/DynatraceRNBridge.h +4 -0
  18. package/ios/DynatraceRNBridge.mm +220 -33
  19. package/lib/core/Dynatrace.js +8 -11
  20. package/lib/core/configuration/ConfigurationHandler.js +3 -0
  21. package/lib/next/Dynatrace.js +14 -32
  22. package/lib/next/DynatraceEventBus.js +35 -0
  23. package/lib/next/appstart/AppStartObserver.js +12 -16
  24. package/lib/next/configuration/INativeRuntimeConfiguration.js +7 -0
  25. package/lib/next/configuration/RuntimeConfigurationObserver.js +40 -0
  26. package/lib/next/events/EventBuilderUtil.js +7 -0
  27. package/lib/next/events/EventData.js +28 -0
  28. package/lib/next/events/EventPipeline.js +5 -11
  29. package/lib/next/events/ExceptionEventData.js +26 -0
  30. package/lib/next/events/{HttpRequestEventBuilder.js → HttpRequestEventData.js} +28 -52
  31. package/lib/next/events/SessionPropertyEventData.js +22 -0
  32. package/lib/next/events/interface/IBaseEvent.js +2 -0
  33. package/lib/next/events/interface/IEventData.js +2 -0
  34. package/lib/next/events/interface/IExceptionEventData.js +2 -0
  35. package/lib/next/events/interface/IHttpRequestEventData.js +2 -0
  36. package/lib/next/events/interface/ISessionPropertyEventData.js +2 -0
  37. package/lib/next/events/modifier/BaseDataEventModifier.js +1 -3
  38. package/lib/next/events/modifier/EventModifierUtil.js +34 -41
  39. package/lib/next/events/modifier/ModifyEventValidation.js +118 -26
  40. package/lib/next/events/modifier/SendEventValidation.js +53 -22
  41. package/lib/next/events/modifier/StringLengthEventModifier.js +53 -0
  42. package/lib/next/events/spec/EventSpecContstants.js +9 -2
  43. package/package.json +8 -3
  44. package/public.js +9 -3
  45. package/react-native-dynatrace.podspec +1 -1
  46. package/scripts/Config.js +6 -2
  47. package/scripts/LineOffsetAnalyze.js +1 -4
  48. package/scripts/core/LineOffsetAnalyzeCall.js +39 -46
  49. package/src/lib/core/interface/NativeDynatraceBridge.ts +6 -2
  50. package/types.d.ts +388 -158
  51. package/lib/next/events/ViewInfoCreator.js +0 -27
  52. package/lib/next/events/modifier/EventLimitation.js +0 -69
  53. /package/lib/next/events/{IHttpRequestEventBuilder.js → interface/EventProperty.js} +0 -0
@@ -0,0 +1,15 @@
1
+ //
2
+ // ConfigurationSubscriber.h
3
+ // DynatraceUEM
4
+ //
5
+ // Created by Schnalzenberger, Ralph on 07.07.25.
6
+ // Copyright © 2025 Dynatrace LLC. All rights reserved.
7
+ //
8
+
9
+ #import <Foundation/Foundation.h>
10
+
11
+ @protocol ConfigurationSubscriber <NSObject>
12
+
13
+ - (void)notifyWithConfiguration:(NSDictionary<NSString*, id>*)configuration;
14
+
15
+ @end
@@ -8,6 +8,7 @@
8
8
  #import <Dynatrace/Dynatrace.h>
9
9
  #import <React/RCTBridgeModule.h>
10
10
  #import <React/RCTEventEmitter.h>
11
+ #import "ConfigurationSubscriber.h"
11
12
 
12
13
  @interface DynatraceRNBridge : RCTEventEmitter <RCTBridgeModule>
13
14
  - (void) newAction:(NSString *)name key:(NSString *)key parentAction:(DTXAction *)parentAction;
@@ -18,6 +19,9 @@
18
19
  @interface HybridBridge : NSObject
19
20
  + (void)forwardEvent:(NSDictionary<NSString*,id>* _Nullable)fields NS_SWIFT_NAME(forwardEvent(fields:));
20
21
  + (void)forwardAppStartEvent:(NSDictionary<NSString*,id>* _Nullable)fields keys:(NSArray<NSString*>* _Nullable)keys NS_SWIFT_NAME(forwardEvent(fields:keys:));
22
+ + (void)startView:(NSDictionary<NSString*,id>* _Nullable)fields NS_SWIFT_NAME(startView(fields:));
23
+ + (void)stopView;
24
+ + (void)addConfigurationSubscriber:(id<ConfigurationSubscriber>)subscriber;
21
25
  @end
22
26
 
23
27
  typedef enum : NSUInteger {
@@ -13,9 +13,45 @@
13
13
  #import <CoreLocation/CoreLocation.h>
14
14
  #import <React/RCTPerformanceLogger.h>
15
15
  #import <React/RCTRootView.h>
16
+ #import <React/RCTBridge+Private.h>
16
17
  #import <cxxreact/ReactMarker.h>
18
+ #import <cxxreact/ReactNativeVersion.h>
17
19
 
18
20
  #include <chrono>
21
+ #include <type_traits>
22
+
23
+ @interface DynatraceRNBridge ()
24
+ - (void)handleRuntimeConfiguration:(NSDictionary<NSString*, id>*)configuration;
25
+ - (void)setupRuntimeConfigurationListenerIfNeeded;
26
+ - (void)emitToJS:(NSString*)event body:(id)body;
27
+ @end
28
+
29
+ @interface RNConfigurationSubscriber : NSObject <ConfigurationSubscriber>
30
+ @property (nonatomic, weak) DynatraceRNBridge* bridge;
31
+ - (instancetype)initWithBridge:(DynatraceRNBridge*)bridge;
32
+ @end
33
+
34
+ @implementation RNConfigurationSubscriber
35
+
36
+ - (instancetype)initWithBridge:(DynatraceRNBridge*)bridge
37
+ {
38
+ self = [super init];
39
+ if (self) {
40
+ _bridge = bridge;
41
+ }
42
+ return self;
43
+ }
44
+
45
+ - (void)notifyWithConfiguration:(NSDictionary<NSString*, id>*)configuration
46
+ {
47
+ DynatraceRNBridge* bridge = self.bridge;
48
+ if (bridge == nil) {
49
+ return;
50
+ }
51
+ [bridge handleRuntimeConfiguration:configuration];
52
+ }
53
+
54
+ @end
19
55
 
20
56
  @implementation DynatraceRNBridge
21
57
 
@@ -35,6 +71,7 @@ NSString *const DataCollectionUserBehavior = @"USER_BEHAVIOR";
35
71
  * Emitting app start event with this identifier
36
72
  */
37
73
  NSString *const EmitAppMeasurementsIdentifier = @"dynatraceAppStartMeasurements";
74
+ NSString *const EmitDynatraceConfiguration = @"dynatraceConfiguration";
38
75
 
39
76
  // All types which are interesting for us
40
77
  NSString *const DownloadStart = @"downloadStart";
@@ -59,6 +96,21 @@ bool didEmit;
59
96
  */
60
97
  int64_t contentAppeared;
61
98
 
99
+ /**
100
+ * When the JavaScript bundle started running
101
+ */
102
+ int64_t runJSBundleStartTime;
103
+
104
+ /**
105
+ * When the JavaScript bundle stopped running
106
+ */
107
+ int64_t runJSBundleEndTime;
108
+
109
+ // Runtime configuration (remote config)
110
+ static bool remoteConfigSubscribed;
111
+ static NSDictionary<NSString*, id>* lastRuntimeConfiguration;
112
+ static RNConfigurationSubscriber* configurationSubscriber;
113
+
62
114
  RCT_EXPORT_MODULE(DynatraceBridge);
63
115
 
64
116
  - (instancetype) init
@@ -69,12 +121,58 @@ RCT_EXPORT_MODULE(DynatraceBridge);
69
121
  hasListeners = NO;
70
122
  didEmit = NO;
71
123
  contentAppeared = -1;
124
+ runJSBundleStartTime = -1;
125
+ runJSBundleEndTime = -1;
126
+
127
+ remoteConfigSubscribed = NO;
128
+ lastRuntimeConfiguration = nil;
129
+ configurationSubscriber = [[RNConfigurationSubscriber alloc] initWithBridge:self];
130
+
131
+ registerLogTaggedMarkerCallbacks();
72
132
  }
73
133
  return self;
74
134
  }
75
135
 
136
+ // We have to make sure facebook::react::ReactMarker::StartupLogger::getInstance().getRunJSBundleEndTime() is always available even for the RN < 72s cases.
137
+ // Relying on the if constexpr else does not work since namespaces get resolved before the if branch in the if constexpr gets discarded.
138
+ // SFINAE does not work for top level symbols in namespaces (because it actually is an error).
139
+ // We cannot use preprocessor directives since we don't have the React Native version as preprocessor macro.
140
+ // We cannot use C++ concepts since C++20 is not available.
141
+ // Thus we provide a fallback definition for StartupLogger.
142
+ // Calling the class methods without a definition cannot happen and won't result in a linker error since the if branch in the if constexpr does not get compiled.
143
+ namespace fallback {
144
+ class StartupLogger {
145
+ public:
146
+ static StartupLogger& getInstance();
147
+ double getRunJSBundleStartTime();
148
+ double getRunJSBundleEndTime();
149
+ };
150
+ }
151
+
152
+ namespace facebook::react::ReactMarker {
153
+ using namespace fallback;
154
+ }
155
+
156
+ int64_t getRunJSBundleStartTime() {
157
+ if constexpr(facebook::react::ReactNativeVersion.Minor >= 72) {
158
+ auto time = facebook::react::ReactMarker::StartupLogger::getInstance().getRunJSBundleStartTime();
159
+ return std::isnan(time) ? -1 : time;
160
+ } else {
161
+ return runJSBundleStartTime;
162
+ }
163
+ }
164
+
165
+ int64_t getRunJSBundleEndTime() {
166
+ if constexpr(facebook::react::ReactNativeVersion.Minor >= 72) {
167
+ auto time = facebook::react::ReactMarker::StartupLogger::getInstance().getRunJSBundleEndTime();
168
+ return std::isnan(time) ? -1 : time;
169
+ } else {
170
+ return runJSBundleEndTime;
171
+ }
172
+ }
173
+
76
174
  - (NSArray<NSString *> *)supportedEvents {
77
- return @[EmitAppMeasurementsIdentifier];
175
+ return @[EmitAppMeasurementsIdentifier, EmitDynatraceConfiguration];
78
176
  }
79
177
 
80
178
  int64_t GetTimestampUnix()
@@ -83,21 +181,53 @@ int64_t GetTimestampUnix()
83
181
  return millisecondsUTC;
84
182
  }
85
183
 
184
+ /*
185
+ In RN < 72, logTaggedMarker and logTaggedMarkerBridgeless are lambdas. In RN >= 72, these symbols are functions.
186
+ Relying on an if constexpr else does not work since types get checked before one branch in an if constexpr else gets discarded.
187
+ We cannot use a fallback declaration since since the symbol is declared as a function in RN >=72.
188
+ We cannot use preprocessor directives since we don't have the React Native version as preprocessor macro.
189
+ We cannot use C++ concepts since C++20 is not available.
190
+ Thus we use SFINAE. This works since types only get checked after template resolution.
191
+ */
192
+ template<typename T = void> std::enable_if_t<(facebook::react::ReactNativeVersion.Minor < 72), T> registerLogTaggedMarkerCallbacks() {
193
+ using namespace facebook::react::ReactMarker;
194
+ auto logTaggedMarkerCommon = [](const ReactMarkerId markerId, const char* tag, auto previousLogTaggedMarker) {
195
+ if (previousLogTaggedMarker) {
196
+ previousLogTaggedMarker(markerId, tag);
197
+ }
198
+
199
+ if (markerId == RUN_JS_BUNDLE_START) {
200
+ runJSBundleStartTime = GetTimestampUnix();
201
+ } else if (markerId == RUN_JS_BUNDLE_STOP) {
202
+ runJSBundleEndTime = GetTimestampUnix();
203
+ }
204
+ };
205
+
206
+ auto previousLogTaggedMarker = logTaggedMarker;
207
+ logTaggedMarker = [=](const ReactMarkerId markerId, const char* tag) {
208
+ logTaggedMarkerCommon(markerId, tag, previousLogTaggedMarker);
209
+ };
210
+
211
+ auto previousLogTaggedMarkerBridgeless = logTaggedMarkerBridgeless;
212
+ logTaggedMarkerBridgeless = [=](const ReactMarkerId markerId, const char* tag) {
213
+ logTaggedMarkerCommon(markerId, tag, previousLogTaggedMarkerBridgeless);
214
+ };
215
+ }
216
+
217
+ template<typename T = void> std::enable_if_t<(facebook::react::ReactNativeVersion.Minor >= 72), T> registerLogTaggedMarkerCallbacks() {}
218
+
86
219
  /**
87
220
  * When bridge is starting we will add an observer for content did appear so we can emit our app start measurements
88
221
  */
89
222
  - (void)setBridge:(RCTBridge *)bridge
90
223
  {
91
224
  [super setBridge:bridge];
92
- [[NSNotificationCenter defaultCenter] addObserver:self
93
- selector:@selector(contentAppeared)
94
- name:RCTContentDidAppearNotification
95
- object:nil];
225
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentAppeared) name:RCTContentDidAppearNotification object:nil];
96
226
  }
97
227
 
98
228
  - (BOOL)isReady
99
229
  {
100
- return contentAppeared != -1 && !std::isnan(facebook::react::ReactMarker::StartupLogger::getInstance().getRunJSBundleEndTime());
230
+ return contentAppeared != -1 && getRunJSBundleEndTime() != -1;
101
231
  }
102
232
 
103
233
  - (void) contentAppeared
@@ -113,13 +243,13 @@ int64_t GetTimestampUnix()
113
243
  {
114
244
  if (!didEmit && hasListeners && [self isReady]) {
115
245
  didEmit = YES;
116
-
246
+
117
247
  NSMutableDictionary<NSString*, NSNumber*> *appStartMeasurements = [[NSMutableDictionary alloc] init];
118
-
119
- [appStartMeasurements setObject:[self correctionOfTimestamp:facebook::react::ReactMarker::StartupLogger::getInstance().getRunJSBundleStartTime()] forKey:RunJSBundleStart];
120
- [appStartMeasurements setObject:[self correctionOfTimestamp:facebook::react::ReactMarker::StartupLogger::getInstance().getRunJSBundleEndTime()] forKey:RunJSBundleEnd];
248
+
249
+ [appStartMeasurements setObject:[self correctionOfTimestamp:getRunJSBundleStartTime()] forKey:RunJSBundleStart];
250
+ [appStartMeasurements setObject:[self correctionOfTimestamp:getRunJSBundleEndTime()] forKey:RunJSBundleEnd];
121
251
  [appStartMeasurements setObject:[NSNumber numberWithLongLong:contentAppeared] forKey:ContentAppeared];
122
-
252
+
123
253
  if (hasListeners) {
124
254
  [self sendEventWithName:EmitAppMeasurementsIdentifier body:appStartMeasurements];
125
255
  }
@@ -128,7 +258,13 @@ int64_t GetTimestampUnix()
128
258
 
129
259
  - (NSNumber* )correctionOfTimestamp:(int64_t) timestamp
130
260
  {
131
- return [NSNumber numberWithLongLong:timestamp + GetTimestampUnix() - (CACurrentMediaTime() * 1000)];
261
+ if constexpr (facebook::react::ReactNativeVersion.Minor < 72) {
262
+ // In RN < 72, timestamps are unix timestamps
263
+ return [NSNumber numberWithLongLong:timestamp];
264
+ } else {
265
+ // IN RN >= 72, timestamps are relative to the system start, which is we we add the unix timestamp of the system start
266
+ return [NSNumber numberWithLongLong:timestamp + GetTimestampUnix() - (CACurrentMediaTime() * 1000)];
267
+ }
132
268
  }
133
269
 
134
270
  /**
@@ -147,6 +283,12 @@ int64_t GetTimestampUnix()
147
283
  {
148
284
  hasListeners = YES;
149
285
  [self emitMeasurements];
286
+
287
+ [self setupRuntimeConfigurationListenerIfNeeded];
288
+
289
+ if (lastRuntimeConfiguration != nil) {
290
+ [self emitToJS:EmitDynatraceConfiguration body:lastRuntimeConfiguration];
291
+ }
150
292
  }
151
293
 
152
294
  /**
@@ -157,6 +299,39 @@ int64_t GetTimestampUnix()
157
299
  hasListeners = NO;
158
300
  }
159
301
 
302
+ - (void)setupRuntimeConfigurationListenerIfNeeded
303
+ {
304
+ if (remoteConfigSubscribed) {
305
+ return;
306
+ }
307
+ remoteConfigSubscribed = YES;
308
+ [HybridBridge addConfigurationSubscriber:(id)configurationSubscriber];
309
+ }
310
+
311
+ - (void)emitToJS:(NSString*)event body:(id)body
312
+ {
313
+ if (self.bridge == nil) {
314
+ return;
315
+ }
316
+
317
+ id payload = body == nil ? [NSNull null] : body;
318
+
319
+ dispatch_async(dispatch_get_main_queue(), ^{
320
+ [self.bridge.eventDispatcher sendDeviceEventWithName:event body:payload];
321
+ });
322
+ }
323
+
324
+ - (void)handleRuntimeConfiguration:(NSDictionary<NSString*, id>*)configuration
325
+ {
326
+ lastRuntimeConfiguration = configuration;
327
+
328
+ if (!hasListeners) {
329
+ return;
330
+ }
331
+
332
+ [self emitToJS:EmitDynatraceConfiguration body:configuration];
333
+ }
334
+
160
335
  /**
161
336
  * Constants which are exported to the JS part
162
337
  */
@@ -174,9 +349,9 @@ RCT_EXPORT_METHOD(start:(NSDictionary *) options)
174
349
  if (options == nil) {
175
350
  return;
176
351
  }
177
-
352
+
178
353
  NSMutableDictionary<NSString*, id> *properties = [[NSMutableDictionary alloc] init];
179
-
354
+
180
355
  if (options[@"applicationId"] != NULL) {
181
356
  properties[@"DTXApplicationID"] = options[@"applicationId"];
182
357
  }
@@ -188,11 +363,11 @@ RCT_EXPORT_METHOD(start:(NSDictionary *) options)
188
363
  if (options[@"userOptIn"] != NULL && [[options valueForKey:@"userOptIn"] isEqual: @(YES)]) {
189
364
  properties[@"DTXUserOptIn"] = @YES;
190
365
  }
191
-
366
+
192
367
  if (options[@"reportCrash"] != NULL && [[options valueForKey:@"reportCrash"] isEqual: @(NO)]) {
193
368
  properties[@"DTXCrashReportingEnabled"] = @NO;
194
369
  }
195
-
370
+
196
371
  if (options[@"logLevel"] != NULL && [((NSNumber *) options[@"logLevel"]) intValue] == 0){
197
372
  properties[@"DTXLogLevel"] = @"ALL";
198
373
  }
@@ -218,7 +393,7 @@ RCT_EXPORT_METHOD(enterManualAction:(NSString *)name key:(nonnull NSString *)key
218
393
  if ([self shouldWorkOnIosWithPlatform: platform])
219
394
  {
220
395
  DTXAction *action = [DTXAction enterActionWithName:name];
221
-
396
+
222
397
  if (action)
223
398
  {
224
399
  [actionDict setObject:action forKey:key];
@@ -235,7 +410,7 @@ RCT_EXPORT_METHOD(enterManualActionWithParent:(NSString *)name key:(nonnull NSSt
235
410
  if (parentAction != nil)
236
411
  {
237
412
  DTXAction *childAction = [DTXAction enterActionWithName:name parentAction:parentAction];
238
-
413
+
239
414
  if (childAction)
240
415
  {
241
416
  [actionDict setObject:childAction forKey:key];
@@ -287,11 +462,6 @@ RCT_EXPORT_METHOD(startView: (NSString *) name)
287
462
  [Dynatrace startViewWithName:name];
288
463
  }
289
464
 
290
- RCT_EXPORT_METHOD(stopView)
291
- {
292
- [Dynatrace stopView];
293
- }
294
-
295
465
  RCT_EXPORT_METHOD(reportErrorWithoutStacktrace:(NSString *)errorName errorCode:(nonnull NSNumber *)errorCode platform: (NSString *) platform)
296
466
  {
297
467
  if ([self shouldWorkOnIosWithPlatform: platform])
@@ -315,11 +485,11 @@ RCT_EXPORT_METHOD(reportCrash:(NSString *)errorName errorReason:(NSString *)erro
315
485
  if ([self shouldWorkOnIosWithPlatform: platform])
316
486
  {
317
487
  if(isRealError){
318
- [DTXAction reportExternalCrashForPlatformType:DTXActionPlatformJavaScript crashName:errorName reason:errorReason stacktrace:stacktrace];
488
+ [DTXAction reportExternalCrashForPlatformType:DTXActionPlatformJavaScript crashName:errorName reason:errorReason stacktrace:stacktrace];
319
489
  }else{
320
490
  [DTXAction reportExternalCrashForPlatformType:DTXActionPlatformCustom crashName:errorName reason:errorReason stacktrace:stacktrace];
321
491
  }
322
-
492
+
323
493
  // Always end the session as the iOS agent has no troubles with this behavior
324
494
  [Dynatrace endVisit];
325
495
  }
@@ -397,7 +567,6 @@ RCT_EXPORT_METHOD(startWebRequestTiming:(NSString*) requestTag url:(NSString*) u
397
567
  [timing startWebRequestTiming];
398
568
  }
399
569
  }
400
-
401
570
  }
402
571
 
403
572
  - (void)stopWebRequestTimingHelper:(NSString*) requestTag url:(NSString*)url responseCode:(nonnull NSNumber*) responseCode responseMessage:(NSString*)responseMessage bytesSent:(nonnull NSNumber*)bytesSent bytesReceived:(nonnull NSNumber*)bytesReceived
@@ -499,7 +668,7 @@ RCT_EXPORT_METHOD(getDataCollectionLevel:(NSString *) platform findEventsWithRes
499
668
  if ([self shouldWorkOnIosWithPlatform: platform])
500
669
  {
501
670
  int i = [Dynatrace dataCollectionLevel];
502
-
671
+
503
672
  if(i == DTX_DataCollectionUserBehavior){
504
673
  resolve(DataCollectionUserBehavior);
505
674
  }else if(i == DTX_DataCollectionPerformance){
@@ -542,7 +711,7 @@ RCT_EXPORT_METHOD(getUserPrivacyOptions:(NSString *) platform findEventsWithReso
542
711
  {
543
712
  id<DTXUserPrivacyOptions> privacyConfig = [Dynatrace userPrivacyOptions];
544
713
  NSString * level;
545
-
714
+
546
715
  if(privacyConfig.dataCollectionLevel == DTX_DataCollectionUserBehavior){
547
716
  level = DataCollectionUserBehavior;
548
717
  }else if(privacyConfig.dataCollectionLevel == DTX_DataCollectionPerformance){
@@ -562,7 +731,7 @@ RCT_EXPORT_METHOD(applyUserPrivacyOptions:(NSDictionary *) userPrivacyOptions pl
562
731
  if ([self shouldWorkOnIosWithPlatform: platform])
563
732
  {
564
733
  id<DTXUserPrivacyOptions> privacyConfig = [Dynatrace userPrivacyOptions];
565
-
734
+
566
735
  if([[userPrivacyOptions valueForKey:@"_dataCollectionLevel"] isEqualToString: DataCollectionPerformance]){
567
736
  privacyConfig.dataCollectionLevel = DTX_DataCollectionPerformance;
568
737
  }else if([[userPrivacyOptions valueForKey:@"_dataCollectionLevel"] isEqualToString: DataCollectionUserBehavior]){
@@ -572,7 +741,7 @@ RCT_EXPORT_METHOD(applyUserPrivacyOptions:(NSDictionary *) userPrivacyOptions pl
572
741
  } else {
573
742
  // do nothing and keep current value
574
743
  }
575
-
744
+
576
745
  if ([[userPrivacyOptions valueForKey:@"_crashReportingOptedIn"] isEqual: @(YES)]) {
577
746
  privacyConfig.crashReportingOptedIn = YES;
578
747
  } else if ([[userPrivacyOptions valueForKey:@"_crashReportingOptedIn"] isEqual: @(NO)]) {
@@ -587,10 +756,29 @@ RCT_EXPORT_METHOD(applyUserPrivacyOptions:(NSDictionary *) userPrivacyOptions pl
587
756
  }
588
757
  }
589
758
 
759
+ RCT_EXPORT_METHOD(getCurrentConfiguration:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
760
+ {
761
+ if (lastRuntimeConfiguration != nil) {
762
+ resolve(lastRuntimeConfiguration);
763
+ } else {
764
+ resolve([NSNull null]);
765
+ }
766
+ }
767
+
768
+ RCT_EXPORT_METHOD(startViewInternal:(NSDictionary<NSString*, id>*) fields)
769
+ {
770
+ [HybridBridge startView:fields];
771
+ }
772
+
773
+ RCT_EXPORT_METHOD(stopViewInternal)
774
+ {
775
+ [HybridBridge stopView];
776
+ }
777
+
590
778
  - (void)newAction:(NSString *)name key:(nonnull NSString *)key parentAction:(DTXAction *)parentAction
591
779
  {
592
780
  DTXAction *action = [DTXAction integrateActionWithName:name];
593
-
781
+
594
782
  if (action)
595
783
  {
596
784
  [actionDict setObject:action forKey:key];
@@ -602,7 +790,6 @@ RCT_EXPORT_METHOD(applyUserPrivacyOptions:(NSDictionary *) userPrivacyOptions pl
602
790
  return [actionDict objectForKey:key];
603
791
  }
604
792
 
605
-
606
793
  + (BOOL)requiresMainQueueSetup
607
794
  {
608
795
  return YES;
@@ -622,4 +809,4 @@ RCT_EXPORT_METHOD(applyUserPrivacyOptions:(NSDictionary *) userPrivacyOptions pl
622
809
  }
623
810
  #endif
624
811
 
625
- @end
812
+ @end
@@ -338,22 +338,19 @@ exports.Dynatrace = {
338
338
  },
339
339
  addEventModifier: (eventModifier) => Dynatrace_1.Dynatrace.addEventModifier(eventModifier),
340
340
  removeEventModifier: (eventModifier) => Dynatrace_1.Dynatrace.removeEventModifier(eventModifier),
341
- sendEvent: (properties) => {
342
- Dynatrace_1.Dynatrace.sendEvent(properties);
343
- },
344
341
  startView: (name) => {
345
342
  Dynatrace_1.Dynatrace.startView(name);
346
343
  },
347
- stopView: () => {
348
- Dynatrace_1.Dynatrace.stopView();
344
+ sendEvent: (customEvent) => {
345
+ Dynatrace_1.Dynatrace.sendEvent(customEvent);
349
346
  },
350
- sendSessionPropertyEvent: (properties) => {
351
- Dynatrace_1.Dynatrace.sendSessionPropertyEvent(properties);
347
+ sendSessionPropertyEvent: (sessionPropertyEventData) => {
348
+ Dynatrace_1.Dynatrace.sendSessionPropertyEvent(sessionPropertyEventData);
352
349
  },
353
- sendExceptionEvent: (error, fields) => {
354
- Dynatrace_1.Dynatrace.sendExceptionEvent(error, fields);
350
+ sendExceptionEvent: (exceptionEvent) => {
351
+ Dynatrace_1.Dynatrace.sendExceptionEvent(exceptionEvent);
355
352
  },
356
- sendHttpRequestEvent(httpRequestEventBuilder) {
357
- Dynatrace_1.Dynatrace.sendHttpRequestEvent(httpRequestEventBuilder);
353
+ sendHttpRequestEvent: (httpRequestEvent) => {
354
+ Dynatrace_1.Dynatrace.sendHttpRequestEvent(httpRequestEvent);
358
355
  },
359
356
  };
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ConfigurationHandler = void 0;
4
+ const RuntimeConfigurationObserver_1 = require("../../next/configuration/RuntimeConfigurationObserver");
4
5
  const LogLevel_1 = require("../logging/LogLevel");
5
6
  let _configuration;
6
7
  exports.ConfigurationHandler = {
@@ -14,6 +15,8 @@ exports.ConfigurationHandler = {
14
15
  _configuration.logLevel === LogLevel_1.LogLevel.Debug,
15
16
  isLifecycleUpdateEnabled: () => _configuration.lifecycleUpdate,
16
17
  isActionNamePrivacyEnabled: () => _configuration.actionNamePrivacy,
18
+ isGrailEnabled: () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.getCurrentRuntimeConfiguration()['3rd_gen_enabled'],
19
+ isRuntimeConfigurationInitiated: () => RuntimeConfigurationObserver_1.RuntimeConfigurationObserver.isInitiated(),
17
20
  getBundleName: () => _configuration.bundleName,
18
21
  getBundleVersion: () => _configuration.bundleVersion,
19
22
  };
@@ -7,7 +7,6 @@ const EventCreator_1 = require("./events/EventCreator");
7
7
  const EventPipeline_1 = require("./events/EventPipeline");
8
8
  const EventTimestamp_1 = require("./events/EventTimestamp");
9
9
  const EventModifierUtil_1 = require("./events/modifier/EventModifierUtil");
10
- const SendEventValidation_1 = require("./events/modifier/SendEventValidation");
11
10
  const TimestampProvider_1 = require("./provider/TimestampProvider");
12
11
  class DynatraceImpl {
13
12
  constructor(timestampProvider) {
@@ -24,7 +23,6 @@ class DynatraceImpl {
24
23
  }
25
24
  startView(name) {
26
25
  this.logger.debug(`startView(${name})`);
27
- EventPipeline_1.EventPipeline.generateViewData(name);
28
26
  if (name != null && name.length > 0) {
29
27
  DynatraceBridge_1.DynatraceNative.startView(name);
30
28
  }
@@ -32,11 +30,6 @@ class DynatraceImpl {
32
30
  this.logger.debug(`startView(${name}): Name can't be used. Either empty or null!`);
33
31
  }
34
32
  }
35
- stopView() {
36
- this.logger.debug('stopView()');
37
- EventPipeline_1.EventPipeline.releaseViewData();
38
- DynatraceBridge_1.DynatraceNative.stopView();
39
- }
40
33
  reportCrash(crash, isApiReported, isFatal = true) {
41
34
  this.logger.debug(`reportCrash(${JSON.stringify(crash)}, ${isFatal})`);
42
35
  const eventTimestamp = new EventTimestamp_1.EventTimestamp(this.timestampProvider);
@@ -67,42 +60,31 @@ class DynatraceImpl {
67
60
  }
68
61
  EventPipeline_1.EventPipeline.insertEvent(event);
69
62
  }
70
- sendExceptionEvent(error, fields) {
71
- this.logger.debug(`sendExceptionEvent(${JSON.stringify(error)}, ${JSON.stringify(fields)})`);
72
- const event = Object.assign({}, (0, EventCreator_1.createErrorEvent)(error.name, error.message, error.stack));
73
- let eventValidated = null;
74
- if (fields) {
75
- eventValidated = Object.assign({}, SendEventValidation_1.SendEventValidation.modifyEvent(fields));
63
+ sendExceptionEvent(exceptionEventData) {
64
+ this.logger.debug('sendExceptionEvent(exceptionEventData)');
65
+ const eventValidated = exceptionEventData.toJSON();
66
+ if (eventValidated !== null) {
67
+ EventPipeline_1.EventPipeline.insertEvent(eventValidated);
76
68
  }
77
- eventValidated = Object.assign(Object.assign({}, event), eventValidated);
78
- (0, EventModifierUtil_1.addIsApiReported)(eventValidated);
79
- EventPipeline_1.EventPipeline.insertEvent(eventValidated);
80
69
  }
81
- sendEvent(properties) {
82
- this.logger.debug(`sendEvent(${JSON.stringify(properties)})`);
83
- const eventValidated = SendEventValidation_1.SendEventValidation.modifyEvent(properties);
70
+ sendEvent(eventData) {
71
+ this.logger.debug('sendEvent(eventData)');
72
+ const eventValidated = eventData.toJSON();
84
73
  if (eventValidated !== null) {
85
- (0, EventModifierUtil_1.flagEventProperties)(eventValidated);
86
- (0, EventModifierUtil_1.addIsApiReported)(eventValidated);
87
74
  EventPipeline_1.EventPipeline.insertEvent(eventValidated);
88
75
  }
89
76
  }
90
- sendSessionPropertyEvent(properties) {
91
- this.logger.debug(`sendSessionPropertyEvent(${JSON.stringify(properties)})`);
92
- const eventValidated = SendEventValidation_1.SendSessionPropertyEventValidation.modifyEvent(properties);
77
+ sendSessionPropertyEvent(sessionPropertyEventData) {
78
+ this.logger.debug('sendSessionPropertyEvent(SessionPropertyEventData)');
79
+ const eventValidated = sessionPropertyEventData.toJSON();
93
80
  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
81
  EventPipeline_1.EventPipeline.insertEvent(eventValidated);
99
82
  }
100
83
  }
101
- sendHttpRequestEvent(httpRequestEventBuilder) {
102
- const sanitizedEvent = httpRequestEventBuilder.build();
103
- this.logger.debug(`sendHttpRequestEvent(${JSON.stringify(sanitizedEvent)})`);
84
+ sendHttpRequestEvent(httpRequestEvent) {
85
+ this.logger.debug('sendHttpRequestEvent(HttpRequestEventData)');
86
+ const sanitizedEvent = httpRequestEvent.toJSON();
104
87
  if (sanitizedEvent !== null) {
105
- (0, EventModifierUtil_1.flagEventProperties)(sanitizedEvent);
106
88
  EventPipeline_1.EventPipeline.insertEvent(sanitizedEvent);
107
89
  }
108
90
  }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addListenerOnce = exports.createEmitterNativeOnly = exports.createEmitterRuntimeConfig = void 0;
4
+ const react_native_1 = require("react-native");
5
+ const DynatraceBridge_1 = require("../core/DynatraceBridge");
6
+ const isEmptyObject = (value) => {
7
+ if (value == null) {
8
+ return true;
9
+ }
10
+ if (typeof value !== 'object') {
11
+ return false;
12
+ }
13
+ return Object.keys(value).length === 0;
14
+ };
15
+ const createEmitterRuntimeConfig = () => {
16
+ if (react_native_1.Platform.OS === 'ios' && isEmptyObject(DynatraceBridge_1.DynatraceNative || {})) {
17
+ return null;
18
+ }
19
+ const iosModule = react_native_1.NativeModules.DynatraceBridge;
20
+ const nativeEmitterModule = react_native_1.Platform.OS === 'android' ? DynatraceBridge_1.DynatraceNative : iosModule;
21
+ return new react_native_1.NativeEventEmitter(nativeEmitterModule);
22
+ };
23
+ exports.createEmitterRuntimeConfig = createEmitterRuntimeConfig;
24
+ const createEmitterNativeOnly = () => new react_native_1.NativeEventEmitter(DynatraceBridge_1.DynatraceNative);
25
+ exports.createEmitterNativeOnly = createEmitterNativeOnly;
26
+ const addListenerOnce = (emitter, current, eventName, handler) => {
27
+ if (current != null) {
28
+ return current;
29
+ }
30
+ if (emitter == null) {
31
+ return null;
32
+ }
33
+ return emitter.addListener(eventName, handler);
34
+ };
35
+ exports.addListenerOnce = addListenerOnce;