@dynatrace/react-native-plugin 2.327.1 → 2.327.2

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 CHANGED
@@ -26,16 +26,16 @@ If you want to start using this plugin and are not a Dynatrace customer yet, hea
26
26
  * Gradle version 7.0+ ([How to update?](#updating-to-gradle-7))
27
27
  * Android Gradle plugin version 7.0+
28
28
  * Java 11
29
- * Kotlin 2.0.21 see [Kotlin Compatibility Note](#⚠️-kotlin-compatibility-note)
30
- * Jetpack Compose 1.4 - 1.9 - see [Compose Compatibility Note](#⚠️-compose-compatibility-note)
29
+ * Kotlin 2.0.21 - see [Kotlin Compatibility Note](#kotlin-compatibility-note)
30
+ * Jetpack Compose 1.4 - 1.9 - see [Compose Compatibility Note](#compose-compatibility-note)
31
31
  * For iOS users: Minimum iOS 12
32
32
  * NodeJS 16.0.0+ since our dependencies require NodeJS 16.0.0
33
33
 
34
34
  ## Agent Versions
35
35
  This agent versions are configured in this plugin:
36
36
 
37
- * Android Agent: 8.327.2.1004
38
- * iOS Agent: 8.327.1.1020
37
+ * Android Agent: 8.327.3.1006
38
+ * iOS Agent: 8.327.2.1022
39
39
 
40
40
  ## Quick Setup
41
41
 
@@ -89,8 +89,8 @@ This agent versions are configured in this plugin:
89
89
  * [React Automatic Runtime](#react-automatic-runtime)
90
90
  * [Using a second transformer besides the dynatrace transformer](#using-a-second-transformer-besides-the-dynatrace-transformer)
91
91
  * [Upgrading project to Gradle 7](#updating-to-gradle-7)
92
- * [Kotlin Compatibility Note](#⚠️-kotlin-compatibility-note)
93
- * [Compose Compatibility Note](#⚠️-compose-compatibility-note)
92
+ * [Kotlin Compatibility Note](#kotlin-compatibility-note)
93
+ * [Compose Compatibility Note](#compose-compatibility-note)
94
94
  * [Maven Central in top-level gradle file](#maven-central-in-top-level-gradle-file)
95
95
  * [Configuration of standalone React Native project](#configuration-of-standalone-react-native-project)
96
96
  * [Instrumentation Overhead](#instrumentation-overhead)
@@ -705,7 +705,7 @@ This example shows two *TouchableHighlight*, which will fire the *onPress()* fun
705
705
 
706
706
  ## New RUM experience preview
707
707
 
708
- > **⚠️ Preview Feature**: The New RUM Experience APIs are currently in preview and may be subject to changes. These APIs provide enhanced event tracking capabilities with the new Dynatrace RUM on Grail feature.
708
+ > **⚠️ Preview Feature**: The New RUM Experience APIs are currently in preview and may be subject to changes. These APIs provide enhanced event tracking capabilities with the new Dynatrace RUM on Grail feature.
709
709
 
710
710
  The New RUM Experience introduces a set of advanced APIs that allow you to send custom events, modify event data, track exceptions, monitor HTTP requests, and manage view contexts in your React Native application. These APIs provide more granular control over the data captured by Dynatrace and are designed for the next generation RUM capabilities.
711
711
 
@@ -960,7 +960,7 @@ pod 'react-native-dynatrace', :path => '../node_modules/@dynatrace/react-native-
960
960
  5. Under Build Phases expand the Link Binary With Libraries header.
961
961
  6. Scroll down and click + to add a library.
962
962
  7. Find and add `libRNDynatrace.a` under the Workspace group.
963
- 8. ⌘+B
963
+ 8. ⌘+B
964
964
 
965
965
  ## Setup for tvOS
966
966
 
@@ -1583,7 +1583,7 @@ dependencies {
1583
1583
 
1584
1584
  ```
1585
1585
 
1586
- ## ⚠️ Kotlin Compatibility Note
1586
+ ## Kotlin Compatibility Note
1587
1587
 
1588
1588
  Our Android Agent currently requires **Kotlin 2.0.21**. However, it should be noted that using this version may cause compatibility issues with older versions of React Native and the corresponding `react-native-gradle-plugin` due to, for instance, differences in Kotlin metadata:
1589
1589
 
@@ -1595,7 +1595,7 @@ Kotlin embeds language-specific features that Java doesn't natively support (lik
1595
1595
 
1596
1596
  In summary, ensure your build fulfills our Kotlin 2.0.21 requirement while simultaneously fulfilling the requirements of your React Native version and its `react-native-gradle-plugin`.
1597
1597
 
1598
- ## ⚠️ Compose Compatibility Note
1598
+ ## Compose Compatibility Note
1599
1599
 
1600
1600
  Our Android Agent currently supports **Jetpack Compose 1.4 - 1.9**. If you are using an incompatible version of Jetpack Compose, you may encounter the following error message during build:
1601
1601
 
@@ -1728,8 +1728,14 @@ If you are struggling with a problem, submit a support ticket to Dynatrace (supp
1728
1728
  <br/><br/>
1729
1729
  ## Changelog
1730
1730
 
1731
+ 2.327.2
1732
+ * Fixed iOS startup time calculation issues for React Native 0.72 and lower
1733
+ * Fixed static properties during auto instrumentation of Touchables
1734
+ * Updated Android (8.327.3.1006) & iOS Agent (8.327.2.1022)
1735
+
1736
+
1731
1737
  2.327.1
1732
- * Added [Compose Compatibility Note](#⚠️-compose-compatibility-note)
1738
+ * Added [Compose Compatibility Note](#compose-compatibility-note)
1733
1739
  * Added [New RUM experience preview](#new-rum-experience-preview) documentation
1734
1740
  * Fixed iOS crash reporting by delaying the crash by 200ms on iOS to give the Agent enough time to report it
1735
1741
  * Updated Android (8.327.2.1004) & iOS Agent (8.327.1.1020)
@@ -2044,4 +2050,4 @@ If you are struggling with a problem, submit a support ticket to Dynatrace (supp
2044
2050
  * Added auto instrumentation for React classes
2045
2051
 
2046
2052
  0.168.0
2047
- * Initial Beta Release
2053
+ * Initial Beta Release
@@ -72,7 +72,7 @@ repositories {
72
72
  }
73
73
 
74
74
  dependencies {
75
- implementation 'com.dynatrace.agent:agent-android:8.327.2.1004'
75
+ implementation 'com.dynatrace.agent:agent-android:8.327.3.1006'
76
76
  implementation "com.facebook.react:react-native:${safeExtGet('reactNative', '+')}"
77
77
  }
78
78
 
@@ -1,4 +1,4 @@
1
1
  // TEMPLATE: plugin-gradle.template
2
2
  dependencies {
3
- classpath 'com.dynatrace.tools.android:gradle-plugin:8.327.2.1004'
3
+ classpath 'com.dynatrace.tools.android:gradle-plugin:8.327.3.1006'
4
4
  }
@@ -7,6 +7,15 @@ exports.Button = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.
7
7
  exports.TouchableOpacity = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.TouchableOpacity, 'Touchable');
8
8
  exports.TouchableHighlight = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.TouchableHighlight, 'Touchable');
9
9
  exports.TouchableNativeFeedback = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.TouchableNativeFeedback, 'Touchable');
10
+ [
11
+ 'Ripple',
12
+ 'SelectableBackground',
13
+ 'SelectableBackgroundBorderless',
14
+ 'canUseNativeForeground',
15
+ ].forEach((prop) => {
16
+ exports.TouchableNativeFeedback[prop] =
17
+ ReactNative.TouchableNativeFeedback[prop];
18
+ });
10
19
  exports.TouchableWithoutFeedback = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.TouchableWithoutFeedback, 'Touchable');
11
20
  exports.Text = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.Text, 'Text');
12
21
  exports.Pressable = (0, withOnPressMonitoring_1.withOnPressMonitoring)(ReactNative.Pressable, 'Pressable');
@@ -14,8 +14,10 @@
14
14
  #import <React/RCTPerformanceLogger.h>
15
15
  #import <React/RCTRootView.h>
16
16
  #import <cxxreact/ReactMarker.h>
17
+ #import <cxxreact/ReactNativeVersion.h>
17
18
 
18
19
  #include <chrono>
20
+ #include <type_traits>
19
21
 
20
22
  @implementation DynatraceRNBridge
21
23
 
@@ -59,6 +61,16 @@ bool didEmit;
59
61
  */
60
62
  int64_t contentAppeared;
61
63
 
64
+ /**
65
+ * When the JavaScript bundle started running
66
+ */
67
+ int64_t runJSBundleStartTime;
68
+
69
+ /**
70
+ * When the JavaScript bundle stopped running
71
+ */
72
+ int64_t runJSBundleEndTime;
73
+
62
74
  RCT_EXPORT_MODULE(DynatraceBridge);
63
75
 
64
76
  - (instancetype) init
@@ -69,10 +81,51 @@ RCT_EXPORT_MODULE(DynatraceBridge);
69
81
  hasListeners = NO;
70
82
  didEmit = NO;
71
83
  contentAppeared = -1;
84
+ runJSBundleStartTime = -1;
85
+ runJSBundleEndTime = -1;
86
+ registerLogTaggedMarkerCallbacks();
72
87
  }
73
88
  return self;
74
89
  }
75
90
 
91
+ // We have to make sure facebook::react::ReactMarker::StartupLogger::getInstance().getRunJSBundleEndTime() is always available even for the RN < 72s cases.
92
+ // Relying on the if constexpr else does not work since namespaces get resolved before the if branch in the if constexpr gets discarded.
93
+ // SFINAE does not work for top level symbols in namespaces (because it actually is an error).
94
+ // We cannot use preprocessor directives since we don't have the React Native version as preprocessor macro.
95
+ // We cannot use C++ concepts since C++20 is not available.
96
+ // Thus we provide a fallback definition for StartupLogger.
97
+ // 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.
98
+ namespace fallback {
99
+ class StartupLogger {
100
+ public:
101
+ static StartupLogger& getInstance();
102
+ double getRunJSBundleStartTime();
103
+ double getRunJSBundleEndTime();
104
+ };
105
+ }
106
+
107
+ namespace facebook::react::ReactMarker {
108
+ using namespace fallback;
109
+ }
110
+
111
+ int64_t getRunJSBundleStartTime() {
112
+ if constexpr(facebook::react::ReactNativeVersion.Minor >= 72) {
113
+ auto time = facebook::react::ReactMarker::StartupLogger::getInstance().getRunJSBundleStartTime();
114
+ return std::isnan(time) ? -1 : time;
115
+ } else {
116
+ return runJSBundleStartTime;
117
+ }
118
+ }
119
+
120
+ int64_t getRunJSBundleEndTime() {
121
+ if constexpr(facebook::react::ReactNativeVersion.Minor >= 72) {
122
+ auto time = facebook::react::ReactMarker::StartupLogger::getInstance().getRunJSBundleEndTime();
123
+ return std::isnan(time) ? -1 : time;
124
+ } else {
125
+ return runJSBundleEndTime;
126
+ }
127
+ }
128
+
76
129
  - (NSArray<NSString *> *)supportedEvents {
77
130
  return @[EmitAppMeasurementsIdentifier];
78
131
  }
@@ -83,21 +136,53 @@ int64_t GetTimestampUnix()
83
136
  return millisecondsUTC;
84
137
  }
85
138
 
139
+ /*
140
+ In RN < 72, logTaggedMarker and logTaggedMarkerBridgeless are lambdas. In RN >= 72, these symbols are functions.
141
+ Relying on an if constexpr else does not work since types get checked before one branch in an if constexpr else gets discarded.
142
+ We cannot use a fallback declaration since since the symbol is declared as a function in RN >=72.
143
+ We cannot use preprocessor directives since we don't have the React Native version as preprocessor macro.
144
+ We cannot use C++ concepts since C++20 is not available.
145
+ Thus we use SFINAE. This works since types only get checked after template resolution.
146
+ */
147
+ template<typename T = void> std::enable_if_t<(facebook::react::ReactNativeVersion.Minor < 72), T> registerLogTaggedMarkerCallbacks() {
148
+ using namespace facebook::react::ReactMarker;
149
+ auto logTaggedMarkerCommon = [](const ReactMarkerId markerId, const char* tag, auto previousLogTaggedMarker) {
150
+ if (previousLogTaggedMarker) {
151
+ previousLogTaggedMarker(markerId, tag);
152
+ }
153
+
154
+ if (markerId == RUN_JS_BUNDLE_START) {
155
+ runJSBundleStartTime = GetTimestampUnix();
156
+ } else if (markerId == RUN_JS_BUNDLE_STOP) {
157
+ runJSBundleEndTime = GetTimestampUnix();
158
+ }
159
+ };
160
+
161
+ auto previousLogTaggedMarker = logTaggedMarker;
162
+ logTaggedMarker = [=](const ReactMarkerId markerId, const char* tag) {
163
+ logTaggedMarkerCommon(markerId, tag, previousLogTaggedMarker);
164
+ };
165
+
166
+ auto previousLogTaggedMarkerBridgeless = logTaggedMarkerBridgeless;
167
+ logTaggedMarkerBridgeless = [=](const ReactMarkerId markerId, const char* tag) {
168
+ logTaggedMarkerCommon(markerId, tag, previousLogTaggedMarkerBridgeless);
169
+ };
170
+ }
171
+
172
+ template<typename T = void> std::enable_if_t<(facebook::react::ReactNativeVersion.Minor >= 72), T> registerLogTaggedMarkerCallbacks() {}
173
+
86
174
  /**
87
175
  * When bridge is starting we will add an observer for content did appear so we can emit our app start measurements
88
176
  */
89
177
  - (void)setBridge:(RCTBridge *)bridge
90
178
  {
91
179
  [super setBridge:bridge];
92
- [[NSNotificationCenter defaultCenter] addObserver:self
93
- selector:@selector(contentAppeared)
94
- name:RCTContentDidAppearNotification
95
- object:nil];
180
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentAppeared) name:RCTContentDidAppearNotification object:nil];
96
181
  }
97
182
 
98
183
  - (BOOL)isReady
99
184
  {
100
- return contentAppeared != -1 && !std::isnan(facebook::react::ReactMarker::StartupLogger::getInstance().getRunJSBundleEndTime());
185
+ return contentAppeared != -1 && getRunJSBundleEndTime() != -1;
101
186
  }
102
187
 
103
188
  - (void) contentAppeared
@@ -116,8 +201,8 @@ int64_t GetTimestampUnix()
116
201
 
117
202
  NSMutableDictionary<NSString*, NSNumber*> *appStartMeasurements = [[NSMutableDictionary alloc] init];
118
203
 
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];
204
+ [appStartMeasurements setObject:[self correctionOfTimestamp:getRunJSBundleStartTime()] forKey:RunJSBundleStart];
205
+ [appStartMeasurements setObject:[self correctionOfTimestamp:getRunJSBundleEndTime()] forKey:RunJSBundleEnd];
121
206
  [appStartMeasurements setObject:[NSNumber numberWithLongLong:contentAppeared] forKey:ContentAppeared];
122
207
 
123
208
  if (hasListeners) {
@@ -128,7 +213,13 @@ int64_t GetTimestampUnix()
128
213
 
129
214
  - (NSNumber* )correctionOfTimestamp:(int64_t) timestamp
130
215
  {
131
- return [NSNumber numberWithLongLong:timestamp + GetTimestampUnix() - (CACurrentMediaTime() * 1000)];
216
+ if constexpr (facebook::react::ReactNativeVersion.Minor < 72) {
217
+ // In RN < 72, timestamps are unix timestamps
218
+ return [NSNumber numberWithLongLong:timestamp];
219
+ } else {
220
+ // IN RN >= 72, timestamps are relative to the system start, which is we we add the unix timestamp of the system start
221
+ return [NSNumber numberWithLongLong:timestamp + GetTimestampUnix() - (CACurrentMediaTime() * 1000)];
222
+ }
132
223
  }
133
224
 
134
225
  /**
@@ -15,20 +15,17 @@ class AppStartObserverImpl {
15
15
  call() {
16
16
  }
17
17
  setupNativeEventEmitter() {
18
- if (react_native_1.Platform.OS === 'android' ||
19
- Object.keys(DynatraceBridge_1.DynatraceNative).length !== 0) {
20
- const emitter = new react_native_1.NativeEventEmitter(DynatraceBridge_1.DynatraceNative);
21
- emitter.addListener(this.EMIT_APP_START, (data) => {
22
- this.logger.debug(`emitter(${JSON.stringify(data)}})`);
23
- const appStartEvent = (0, EventCreator_1.createAppStartEvent)(data);
24
- if (appStartEvent != null) {
25
- EventPipeline_1.EventPipeline.insertEvent(Object.assign({}, appStartEvent));
26
- }
27
- else {
28
- this.logger.debug(`emitter(${JSON.stringify(data)}}): App Start event ignored!`);
29
- }
30
- });
31
- }
18
+ const emitter = new react_native_1.NativeEventEmitter(DynatraceBridge_1.DynatraceNative);
19
+ emitter.addListener(this.EMIT_APP_START, (data) => {
20
+ this.logger.debug(`emitter(${JSON.stringify(data)}})`);
21
+ const appStartEvent = (0, EventCreator_1.createAppStartEvent)(data);
22
+ if (appStartEvent != null) {
23
+ EventPipeline_1.EventPipeline.insertEvent(Object.assign({}, appStartEvent));
24
+ }
25
+ else {
26
+ this.logger.debug(`emitter(${JSON.stringify(data)}}): App Start event ignored!`);
27
+ }
28
+ });
32
29
  }
33
30
  }
34
31
  exports.AppStartObserver = new AppStartObserverImpl();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynatrace/react-native-plugin",
3
- "version": "2.327.1",
3
+ "version": "2.327.2",
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",
@@ -111,7 +111,7 @@ Pod::Spec.new do |s|
111
111
  #
112
112
 
113
113
  s.dependency "React"
114
- s.dependency 'Dynatrace', '~> 8.327.1.1020'
114
+ s.dependency 'Dynatrace', '~> 8.327.2.1022'
115
115
 
116
116
  # Allows for better compatibility for older and newer versions
117
117
  if defined?(install_modules_dependencies)