@dynatrace/react-native-plugin 2.307.1 → 2.311.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 +13 -4
- package/android/build.gradle +3 -1
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceAppStartModule.kt +128 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceInternalModule.kt +22 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +411 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceReactPackage.kt +54 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.kt +86 -0
- package/android/src/main/java/com/dynatrace/android/agent/model/AppStartMeasurement.kt +15 -0
- package/android/src/main/java/com/dynatrace/android/agent/model/AppStartMeasurementType.kt +18 -0
- package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +228 -0
- package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +258 -0
- package/files/plugin.gradle +1 -1
- package/index.js +10 -10
- package/instrumentation/DynatraceInstrumentation.js +1 -0
- package/{lib → instrumentation/jsx}/CreateElement.js +6 -5
- package/{lib/instrumentor/base → instrumentation/jsx}/ElementHelper.js +14 -12
- package/instrumentation/jsx/JsxDevRuntime.js +54 -0
- package/instrumentation/jsx/JsxRuntime.js +57 -0
- package/instrumentation/jsx/JsxRuntimeUtil.js +31 -0
- package/instrumentation/jsx/components/ClassComponent.js +49 -0
- package/instrumentation/jsx/components/ComponentUtil.js +33 -0
- package/instrumentation/jsx/components/FunctionalComponent.js +15 -0
- package/{lib/instrumentor/base → instrumentation/jsx/components}/Picker.js +1 -1
- package/{lib/instrumentor/base → instrumentation/jsx/components}/RefreshControl.js +1 -1
- package/{lib/instrumentor/base → instrumentation/jsx/components}/Switch.js +8 -8
- package/{lib/instrumentor/base → instrumentation/jsx/components}/Touchable.js +8 -8
- package/instrumentation/libs/community/Picker.InstrInfo.js +20 -0
- package/{lib → instrumentation/libs}/community/Picker.js +1 -1
- package/instrumentation/libs/community/gesture-handler/Touchables.InstrInfo.js +23 -0
- package/{lib → instrumentation/libs}/community/gesture-handler/Touchables.js +1 -1
- package/{lib → instrumentation/libs}/react-native/RefreshControl.InstrInfo.js +2 -2
- package/{lib → instrumentation/libs}/react-native/RefreshControl.js +5 -5
- package/{lib → instrumentation/libs}/react-native/Switch.InstrInfo.js +2 -2
- package/{lib → instrumentation/libs}/react-native/Switch.js +5 -5
- package/instrumentation/libs/react-native/Touchables.InstrInfo.js +25 -0
- package/{lib → instrumentation/libs}/react-native/Touchables.js +1 -1
- package/{lib → instrumentation/libs}/react-navigation/ReactNavigation.js +6 -5
- package/{lib/instrumentor → instrumentation}/model/Types.js +1 -14
- package/instrumentation/model/TypesUtil.js +50 -0
- package/ios/DynatraceRNBridge.h +10 -1
- package/ios/DynatraceRNBridge.mm +152 -1
- package/jsx-dev-runtime.js +1 -1
- package/jsx-runtime.js +1 -1
- package/lib/core/Application.js +20 -0
- package/lib/{instrumentor/base → core}/Dynatrace.js +72 -48
- package/lib/{instrumentor/base → core}/DynatraceAction.js +23 -22
- package/lib/core/DynatraceInternal.js +46 -0
- package/lib/{instrumentor/base → core}/DynatraceRootAction.js +5 -4
- package/lib/{instrumentor/base → core}/DynatraceWebRequestTiming.js +6 -5
- package/lib/{instrumentor/base → core}/ErrorHandler.js +6 -5
- package/lib/{instrumentor/base → core}/configuration/Configuration.js +1 -1
- package/lib/{instrumentor/base → core}/configuration/ConfigurationDefaults.js +1 -2
- package/lib/{instrumentor/base → core}/configuration/ConfigurationHandler.js +2 -2
- package/lib/{instrumentor/base → core}/configuration/ManualStartupConfiguration.js +1 -1
- package/lib/core/logging/ConsoleLogger.js +27 -0
- package/lib/core/logging/LogLevel.js +12 -0
- package/lib/dynatrace-transformer.js +1 -1
- package/lib/next/Dynatrace.js +88 -0
- package/lib/next/DynatraceSecondGenForwarder.js +35 -0
- package/lib/next/IDynatrace.js +2 -0
- package/lib/next/IDynatraceForwarder.js +2 -0
- package/lib/next/appstart/AppStartObserver.js +34 -0
- package/lib/next/appstart/AppStartType.js +38 -0
- package/lib/next/events/EventCreator.js +77 -0
- package/lib/next/events/EventPipeline.js +58 -0
- package/lib/next/events/EventTimestamp.js +27 -0
- package/lib/next/events/ViewInfoCreator.js +27 -0
- package/lib/next/events/modifier/BaseDataEventModifier.js +31 -0
- package/lib/next/events/modifier/EventLimitation.js +69 -0
- package/lib/next/events/modifier/EventModifierUtil.js +89 -0
- package/lib/next/events/modifier/IEventModifier.js +2 -0
- package/lib/next/events/modifier/ModifyEventValidation.js +189 -0
- package/lib/next/events/modifier/SendEventValidation.js +86 -0
- package/lib/next/events/modifier/ValueRestrictionModifier.js +56 -0
- package/lib/next/events/spec/EventFieldKeysEnum.js +2 -0
- package/lib/next/events/spec/EventSpecContstants.js +47 -0
- package/lib/next/events/spec/IAppStartEvent.js +2 -0
- package/lib/next/events/spec/ICrashEvent.js +2 -0
- package/lib/next/events/spec/IErrorCodeEvent.js +2 -0
- package/lib/next/events/spec/IErrorExceptionEvent.js +2 -0
- package/lib/next/events/spec/IReactNativeEvent.js +2 -0
- package/lib/next/events/spec/IRumEvent.js +2 -0
- package/lib/next/provider/ITimestampProvider.js +2 -0
- package/lib/next/provider/TimestampProvider.js +10 -0
- package/package.json +42 -33
- package/react-native-dynatrace.podspec +1 -1
- package/scripts/Android.js +10 -4
- package/scripts/PathsConstants.js +3 -1
- package/scripts/core/InstrumentCall.js +1 -0
- package/src/lib/{instrumentor/base → core}/interface/NativeDynatraceBridge.ts +8 -0
- package/typings/react-native-dynatrace.d.ts +73 -0
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.java +0 -366
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceReactPackage.java +0 -67
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.java +0 -108
- package/android/src/main/java/com/dynatrace/android/agent/PrivateDTBridge.java +0 -28
- package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.java +0 -192
- package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.java +0 -194
- package/lib/community/Picker.InstrInfo.js +0 -20
- package/lib/community/gesture-handler/Touchables.InstrInfo.js +0 -56
- package/lib/instrumentor/DynatraceInstrumentation.js +0 -1
- package/lib/instrumentor/base/Application.js +0 -16
- package/lib/instrumentor/base/DynatraceInternal.js +0 -34
- package/lib/instrumentor/base/Logger.js +0 -16
- package/lib/instrumentor/base/model/LogLevel.js +0 -17
- package/lib/jsx-dev-runtime.js +0 -70
- package/lib/jsx-runtime.js +0 -69
- package/lib/react/Component.js +0 -90
- package/lib/react-native/Touchables.InstrInfo.js +0 -60
- /package/{lib/instrumentor/base/interface → instrumentation/jsx}/IDynatraceProperties.js +0 -0
- /package/{lib → instrumentation/libs}/community/gesture-handler/index.js +0 -0
- /package/{lib → instrumentation/libs}/gesture-handler.js +0 -0
- /package/{lib → instrumentation/libs}/react-native/index.js +0 -0
- /package/{lib → instrumentation/libs}/react-native.js +0 -0
- /package/{lib/instrumentor → instrumentation}/model/Reference.js +0 -0
- /package/{lib/instrumentor → instrumentation}/parser/Babel.js +0 -0
- /package/lib/{instrumentor/base → core}/DynatraceBridge.js +0 -0
- /package/lib/{instrumentor/base → core}/NullAction.js +0 -0
- /package/lib/{instrumentor/base → core}/NullRootAction.js +0 -0
- /package/lib/{instrumentor/base → core}/NullWebRequestTiming.js +0 -0
- /package/lib/{instrumentor/base → core}/UserPrivacyOptions.js +0 -0
- /package/lib/{instrumentor/base → core}/configuration/ConfigurationBuilder.js +0 -0
- /package/lib/{instrumentor/base → core}/configuration/ConfigurationPreset.js +0 -0
- /package/lib/{instrumentor/base → core}/configuration/IConfiguration.js +0 -0
- /package/lib/{instrumentor/base → core}/interface/IDynatrace.js +0 -0
- /package/lib/{instrumentor/base → core}/interface/IDynatraceAction.js +0 -0
- /package/lib/{instrumentor/base → core}/interface/IDynatraceInternal.js +0 -0
- /package/lib/{instrumentor/base → core}/interface/IDynatraceRootAction.js +0 -0
- /package/lib/{instrumentor/base → core}/interface/IWebRequestTiming.js +0 -0
- /package/lib/{instrumentor/base → core}/interface/NativeDynatraceBridge.js +0 -0
- /package/lib/{instrumentor/base/interface → core/logging}/ILogger.js +0 -0
- /package/lib/{instrumentor/base → core}/model/DataCollectionLevel.js +0 -0
- /package/lib/{instrumentor/base → core}/model/Json.js +0 -0
- /package/lib/{instrumentor/base → core}/model/Platform.js +0 -0
- /package/lib/{instrumentor/base → core}/util/StringUtils.js +0 -0
package/README.md
CHANGED
|
@@ -32,8 +32,8 @@ If you want to start using this plugin and are not a Dynatrace customer yet, hea
|
|
|
32
32
|
## Agent Versions
|
|
33
33
|
This agent versions are configured in this plugin:
|
|
34
34
|
|
|
35
|
-
* Android Agent: 8.
|
|
36
|
-
* iOS Agent: 8.
|
|
35
|
+
* Android Agent: 8.311.1.1007
|
|
36
|
+
* iOS Agent: 8.311.1.1013
|
|
37
37
|
|
|
38
38
|
## Quick Setup
|
|
39
39
|
|
|
@@ -327,7 +327,7 @@ Combining manual and auto instrumentation should not be a problem. As they're ru
|
|
|
327
327
|
|
|
328
328
|
There are two options to create an action. Either using `enterAutoAction` (the previous `enterAction`) or `enterManualAction`:
|
|
329
329
|
|
|
330
|
-
* `enterAutoAction` - Creates an Action which will be automatically handled by the plugin (This is the type of action which is internally used by the plugin when monitoring components and touchables). This means that the plugin decides about the
|
|
330
|
+
* `enterAutoAction` - Creates an Action which will be automatically handled by the plugin (This is the type of action which is internally used by the plugin when monitoring components and touchables). This means that the plugin decides about the hierarchy of this action. If there is no open action, the following action will be a root action. All other actions created by this method, while a root action is open, will be automatically inserted as a child action. Furthermore the plugin will automatically link webrequest (if they are not tagged manually) to the open root action. Be aware that the timeout/wait time for sub actions or web requests cannot be modified on the Android side for React Native Auto actions. The timeout is fixed to a 1000ms.
|
|
331
331
|
|
|
332
332
|
```ts
|
|
333
333
|
import { Dynatrace } from '@dynatrace/react-native-plugin';
|
|
@@ -402,7 +402,7 @@ let url = 'https://www.dynatrace.com';
|
|
|
402
402
|
// You can also use enterAutoAction if desired
|
|
403
403
|
let action = Dynatrace.enterManualAction("Manual Web Request");
|
|
404
404
|
let tag = await action.getRequestTag(url);
|
|
405
|
-
let timing = new DynatraceWebRequestTiming(
|
|
405
|
+
let timing = new DynatraceWebRequestTiming(tag, url);
|
|
406
406
|
|
|
407
407
|
try {
|
|
408
408
|
timing.startWebRequestTiming();
|
|
@@ -1463,6 +1463,15 @@ If you are struggling with a problem, submit a support ticket to Dynatrace (supp
|
|
|
1463
1463
|
<br/><br/>
|
|
1464
1464
|
## Changelog
|
|
1465
1465
|
|
|
1466
|
+
2.311.1
|
|
1467
|
+
* Updated Android (8.311.1.1007) & iOS Agent (8.311.1.1013)
|
|
1468
|
+
* Configuration copied to android folder which supports cloud builds
|
|
1469
|
+
* Removed dynamic import for jsx runtime as it was causing issue
|
|
1470
|
+
|
|
1471
|
+
2.309.1
|
|
1472
|
+
* Updated Android (8.309.2.1011) & iOS Agent (8.309.1.1009)
|
|
1473
|
+
* Fixed issue with metro when internal require was not resolved correctly
|
|
1474
|
+
|
|
1466
1475
|
2.307.1
|
|
1467
1476
|
* Updated Android (8.307.1.1005) & iOS Agent (8.307.1.1014)
|
|
1468
1477
|
* Now require the use of NodeJS 18+
|
package/android/build.gradle
CHANGED
|
@@ -16,10 +16,12 @@ buildscript {
|
|
|
16
16
|
|
|
17
17
|
dependencies {
|
|
18
18
|
classpath 'com.android.tools.build:gradle:7.3.1'
|
|
19
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10"
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
apply plugin: 'com.android.library'
|
|
24
|
+
apply plugin: 'org.jetbrains.kotlin.android'
|
|
23
25
|
|
|
24
26
|
if (isNewArchitectureEnabled()) {
|
|
25
27
|
apply plugin: 'com.facebook.react'
|
|
@@ -70,7 +72,7 @@ repositories {
|
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
dependencies {
|
|
73
|
-
implementation 'com.dynatrace.agent:agent-android:8.
|
|
75
|
+
implementation 'com.dynatrace.agent:agent-android:8.311.1.1007'
|
|
74
76
|
implementation "com.facebook.react:react-native:${safeExtGet('reactNative', '+')}"
|
|
75
77
|
}
|
|
76
78
|
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
package com.dynatrace.android.agent
|
|
2
|
+
|
|
3
|
+
import android.os.SystemClock
|
|
4
|
+
import com.dynatrace.android.agent.model.AppStartMeasurement
|
|
5
|
+
import com.dynatrace.android.agent.model.AppStartMeasurementType
|
|
6
|
+
import com.facebook.react.bridge.Arguments
|
|
7
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
8
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
9
|
+
import com.facebook.react.bridge.ReactMarker
|
|
10
|
+
import com.facebook.react.bridge.ReactMarkerConstants
|
|
11
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
12
|
+
import java.util.Queue
|
|
13
|
+
import java.util.concurrent.ConcurrentLinkedQueue
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Name of the module
|
|
17
|
+
*/
|
|
18
|
+
private const val APP_START_MODULE = "DynatraceAppStartModule"
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Emitting app start event with this identifier
|
|
22
|
+
*/
|
|
23
|
+
private const val EMIT_APP_START = "dynatraceAppStartMeasurements"
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Queue which contains all our measured app start timestamps
|
|
27
|
+
*/
|
|
28
|
+
private val buffer: Queue<AppStartMeasurement> = ConcurrentLinkedQueue()
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Setup to register all time points which we want to use to report correct app startup time.
|
|
32
|
+
*/
|
|
33
|
+
fun setupAppStartListener() {
|
|
34
|
+
ReactMarker.addListener { name: ReactMarkerConstants?, _: String?, _: Int ->
|
|
35
|
+
when (name) {
|
|
36
|
+
ReactMarkerConstants.RELOAD -> {
|
|
37
|
+
buffer.clear()
|
|
38
|
+
buffer.add(
|
|
39
|
+
AppStartMeasurement(
|
|
40
|
+
AppStartMeasurementType.RELOAD.value,
|
|
41
|
+
SystemClock.uptimeMillis()
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
ReactMarkerConstants.CONTENT_APPEARED -> buffer.add(
|
|
47
|
+
AppStartMeasurement(
|
|
48
|
+
AppStartMeasurementType.CONTENT_APPEARED.value,
|
|
49
|
+
SystemClock.uptimeMillis()
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
ReactMarkerConstants.DOWNLOAD_END -> buffer.add(
|
|
54
|
+
AppStartMeasurement(
|
|
55
|
+
AppStartMeasurementType.DOWNLOAD_END.value,
|
|
56
|
+
SystemClock.uptimeMillis()
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
ReactMarkerConstants.DOWNLOAD_START -> buffer.add(
|
|
61
|
+
AppStartMeasurement(
|
|
62
|
+
AppStartMeasurementType.DOWNLOAD_START.value,
|
|
63
|
+
SystemClock.uptimeMillis()
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
ReactMarkerConstants.RUN_JS_BUNDLE_END -> buffer.add(
|
|
68
|
+
AppStartMeasurement(
|
|
69
|
+
AppStartMeasurementType.RUN_JS_BUNDLE_END.value,
|
|
70
|
+
SystemClock.uptimeMillis()
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
ReactMarkerConstants.RUN_JS_BUNDLE_START -> buffer.add(
|
|
75
|
+
AppStartMeasurement(
|
|
76
|
+
AppStartMeasurementType.RUN_JS_BUNDLE_START.value,
|
|
77
|
+
SystemClock.uptimeMillis()
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
else -> {
|
|
82
|
+
// Not important
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Module which is handling the app start measurements
|
|
90
|
+
*/
|
|
91
|
+
internal class DynatraceAppStartModule(reactContext: ReactApplicationContext?) :
|
|
92
|
+
ReactContextBaseJavaModule(reactContext) {
|
|
93
|
+
init {
|
|
94
|
+
setupInternalListener()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* We setup the listener internally as we
|
|
99
|
+
*/
|
|
100
|
+
private fun setupInternalListener() {
|
|
101
|
+
ReactMarker.addListener { name: ReactMarkerConstants, _: String?, _: Int ->
|
|
102
|
+
if (name == ReactMarkerConstants.CONTENT_APPEARED) {
|
|
103
|
+
// When content appeared we will emit the event with all the information
|
|
104
|
+
flushMeasurements()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* We flush all events when content appeared is triggered, as it marks the last event
|
|
111
|
+
*/
|
|
112
|
+
private fun flushMeasurements() {
|
|
113
|
+
val params = Arguments.createMap()
|
|
114
|
+
val iterator: Iterator<AppStartMeasurement> = buffer.iterator()
|
|
115
|
+
while (iterator.hasNext()) {
|
|
116
|
+
val entry = iterator.next()
|
|
117
|
+
params.putDouble(entry.name, entry.timestamp.toDouble())
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
reactApplicationContext
|
|
121
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
122
|
+
.emit(EMIT_APP_START, params)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
override fun getName(): String {
|
|
126
|
+
return APP_START_MODULE
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package com.dynatrace.android.agent
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
5
|
+
import com.facebook.react.bridge.ReactMethod
|
|
6
|
+
|
|
7
|
+
class DynatraceInternalModule(reactContext: ReactApplicationContext?) :
|
|
8
|
+
ReactContextBaseJavaModule(reactContext) {
|
|
9
|
+
override fun getName(): String {
|
|
10
|
+
return "DynatraceInternalModule"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Helper method which should not be called.
|
|
15
|
+
* @param name Action name
|
|
16
|
+
* @return Action
|
|
17
|
+
*/
|
|
18
|
+
@ReactMethod
|
|
19
|
+
fun enterAction(name: String?): DTXAction {
|
|
20
|
+
return Dynatrace.integrateNewAction(name)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
package com.dynatrace.android.agent
|
|
2
|
+
|
|
3
|
+
import android.location.Location
|
|
4
|
+
import com.dynatrace.android.agent.conf.DataCollectionLevel
|
|
5
|
+
import com.dynatrace.android.agent.conf.DynatraceConfigurationBuilder
|
|
6
|
+
import com.dynatrace.android.agent.conf.UserPrivacyOptions
|
|
7
|
+
import com.dynatrace.android.agent.crash.PlatformType
|
|
8
|
+
import com.facebook.react.bridge.Arguments
|
|
9
|
+
import com.facebook.react.bridge.Promise
|
|
10
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
11
|
+
import com.facebook.react.bridge.ReadableMap
|
|
12
|
+
import org.json.JSONObject
|
|
13
|
+
import java.net.URI
|
|
14
|
+
import java.net.URISyntaxException
|
|
15
|
+
|
|
16
|
+
private const val PLATFORM_ANDROID = "android"
|
|
17
|
+
private const val PLATFORM_IOS = "ios"
|
|
18
|
+
private const val DATA_COLLECTION_OFF = "OFF"
|
|
19
|
+
private const val DATA_COLLECTION_PERFORMANCE = "PERFORMANCE"
|
|
20
|
+
private const val DATA_COLLECTION_USERBEHAVIOR = "USER_BEHAVIOR"
|
|
21
|
+
const val BRIDGE_NAME = "DynatraceBridge"
|
|
22
|
+
|
|
23
|
+
class DynatraceRNBridgeImpl(
|
|
24
|
+
private val reactApplicationContext: ReactApplicationContext,
|
|
25
|
+
private val _internal: DynatraceInternalModule
|
|
26
|
+
) {
|
|
27
|
+
private val webTimings: HashMap<String, WebRequestTiming> = HashMap()
|
|
28
|
+
private val actions: HashMap<String, DTXAction?> = HashMap()
|
|
29
|
+
|
|
30
|
+
private val constants = mapOf(
|
|
31
|
+
"PLATFORM_ANDROID" to PLATFORM_ANDROID,
|
|
32
|
+
"PLATFORM_IOS" to PLATFORM_IOS,
|
|
33
|
+
"DATA_COLLECTION_OFF" to DATA_COLLECTION_OFF,
|
|
34
|
+
"DATA_COLLECTION_PERFORMANCE" to DATA_COLLECTION_PERFORMANCE,
|
|
35
|
+
"DATA_COLLECTION_USERBEHAVIOR" to DATA_COLLECTION_USERBEHAVIOR
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
fun getConstants(): Map<String, Any> {
|
|
39
|
+
return constants;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
fun start(configuration: ReadableMap?, promise: Promise) {
|
|
43
|
+
if (configuration == null) {
|
|
44
|
+
promise.resolve(false)
|
|
45
|
+
return
|
|
46
|
+
} else {
|
|
47
|
+
if (configuration.getString("applicationId") == null || configuration.getString("beaconUrl") == null) {
|
|
48
|
+
promise.resolve(false)
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
val builder = DynatraceConfigurationBuilder(
|
|
53
|
+
configuration.getString("applicationId"),
|
|
54
|
+
configuration.getString("beaconUrl")
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
builder.apply {
|
|
58
|
+
withUserOptIn(configuration.getBoolean("userOptIn"))
|
|
59
|
+
withCrashReporting(configuration.getBoolean("reportCrash"))
|
|
60
|
+
// 0 == Debug / 1 == Info
|
|
61
|
+
withDebugLogging(configuration.getInt("logLevel") == 0)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
Dynatrace.startup(reactApplicationContext, builder.buildConfiguration())
|
|
65
|
+
promise.resolve(true)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//
|
|
70
|
+
// Expects a key which is generated in JS. This is to circumvent the async callback system.
|
|
71
|
+
//
|
|
72
|
+
fun enterAction(name: String, key: String, platform: String?) {
|
|
73
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
74
|
+
newAction(name, key)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
fun enterManualAction(name: String, key: String, platform: String?) {
|
|
79
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
80
|
+
actions[key] = Dynatrace.enterAction(name)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
fun enterManualActionWithParent(
|
|
85
|
+
name: String,
|
|
86
|
+
key: String,
|
|
87
|
+
parentKey: String,
|
|
88
|
+
platform: String?
|
|
89
|
+
) {
|
|
90
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
91
|
+
val parent = actions[parentKey]
|
|
92
|
+
if (parent != null) {
|
|
93
|
+
actions[key] = Dynatrace.enterAction(name, parent)
|
|
94
|
+
} else {
|
|
95
|
+
enterManualAction(name, key, platform)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
fun leaveAction(key: String, @Suppress("UNUSED_PARAMETER") leave: Boolean, platform: String?) {
|
|
101
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
102
|
+
val action = getAction(key) ?: return
|
|
103
|
+
if (action is DTXAutoAction) {
|
|
104
|
+
action.startTimer()
|
|
105
|
+
} else {
|
|
106
|
+
action.leaveAction()
|
|
107
|
+
}
|
|
108
|
+
actions.remove(key)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
fun cancelAction(key: String, platform: String?) {
|
|
113
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
114
|
+
val action = getAction(key) ?: return
|
|
115
|
+
action.cancel()
|
|
116
|
+
actions.remove(key)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
fun endVisit(platform: String?) {
|
|
121
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
122
|
+
Dynatrace.endVisit()
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
fun reportErrorWithoutStacktrace(errorName: String, errorCode: Int, platform: String?) {
|
|
127
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
128
|
+
Dynatrace.internalReportError(errorName, errorCode)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Reports a stacktrace
|
|
134
|
+
* @param errorName Name of the Error - SyntaxError
|
|
135
|
+
* @param errorValue Value of the Error
|
|
136
|
+
* @param reason Reason for the Error
|
|
137
|
+
* @param stacktrace Whole Stacktrace
|
|
138
|
+
* @param platform Platform wise or both
|
|
139
|
+
*/
|
|
140
|
+
fun reportError(
|
|
141
|
+
errorName: String,
|
|
142
|
+
errorValue: String,
|
|
143
|
+
reason: String,
|
|
144
|
+
stacktrace: String,
|
|
145
|
+
platform: String?
|
|
146
|
+
) {
|
|
147
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
148
|
+
Dynatrace.reportError(PlatformType.CUSTOM, errorName, errorValue, reason, stacktrace)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
fun reportCrash(
|
|
153
|
+
errorName: String,
|
|
154
|
+
reason: String,
|
|
155
|
+
stacktrace: String,
|
|
156
|
+
isRealError: Boolean,
|
|
157
|
+
platform: String?
|
|
158
|
+
) {
|
|
159
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
160
|
+
Dynatrace.reportCrash(
|
|
161
|
+
if (isRealError) PlatformType.JAVA_SCRIPT else PlatformType.CUSTOM,
|
|
162
|
+
errorName,
|
|
163
|
+
reason,
|
|
164
|
+
stacktrace
|
|
165
|
+
)
|
|
166
|
+
// Generate new session like iOS to make sure the behavior is the same
|
|
167
|
+
Dynatrace.createNewSession()
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
fun reportErrorInAction(key: String, errorName: String, errorCode: Int, platform: String?) {
|
|
172
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
173
|
+
val action = getAction(key) ?: return
|
|
174
|
+
action.reportError(errorName, errorCode)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
fun reportValue(key: String, valueName: String, value: String, platform: String?) {
|
|
179
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
180
|
+
val action = getAction(key) ?: return
|
|
181
|
+
action.reportValue(valueName, value)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
fun getRequestTag(key: String, @Suppress("UNUSED_PARAMETER") url: String, promise: Promise) {
|
|
186
|
+
val action = getAction(key)
|
|
187
|
+
if (action == null) {
|
|
188
|
+
promise.resolve(Dynatrace.getRequestTag())
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
promise.resolve(action.requestTag)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
fun startWebRequestTiming(requestTag: String?, @Suppress("UNUSED_PARAMETER") url: String) {
|
|
195
|
+
if (requestTag != null) {
|
|
196
|
+
val timing = Dynatrace.getWebRequestTiming(requestTag)
|
|
197
|
+
if (timing != null) {
|
|
198
|
+
webTimings[requestTag] = timing
|
|
199
|
+
timing.startWebRequestTiming()
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
fun stopWebRequestTiming(
|
|
205
|
+
requestTag: String?,
|
|
206
|
+
url: String,
|
|
207
|
+
responseCode: Int,
|
|
208
|
+
responseMessage: String
|
|
209
|
+
) {
|
|
210
|
+
stopWebRequestTimingWithSize(requestTag, url, responseCode, responseMessage, -1, -1)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
fun stopWebRequestTimingWithSize(
|
|
214
|
+
requestTag: String?,
|
|
215
|
+
url: String,
|
|
216
|
+
responseCode: Int,
|
|
217
|
+
responseMessage: String,
|
|
218
|
+
requestSize: Long,
|
|
219
|
+
responseSize: Long
|
|
220
|
+
) {
|
|
221
|
+
if (requestTag != null) {
|
|
222
|
+
val timing = webTimings[requestTag]
|
|
223
|
+
if (timing != null) {
|
|
224
|
+
try {
|
|
225
|
+
timing.stopWebRequestTiming(
|
|
226
|
+
URI(url),
|
|
227
|
+
responseCode,
|
|
228
|
+
responseMessage,
|
|
229
|
+
requestSize,
|
|
230
|
+
responseSize
|
|
231
|
+
)
|
|
232
|
+
webTimings.remove(requestTag)
|
|
233
|
+
} catch (ex: URISyntaxException) {
|
|
234
|
+
// do nothing
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
fun identifyUser(user: String, platform: String?) {
|
|
241
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
242
|
+
Dynatrace.identifyUser(user)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
fun reportEventInAction(actionKey: String, name: String, platform: String?) {
|
|
247
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
248
|
+
val action = getAction(actionKey) ?: return
|
|
249
|
+
action.reportEvent(name)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
fun reportStringValueInAction(
|
|
254
|
+
actionKey: String,
|
|
255
|
+
name: String,
|
|
256
|
+
value: String,
|
|
257
|
+
platform: String?
|
|
258
|
+
) {
|
|
259
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
260
|
+
val action = getAction(actionKey) ?: return
|
|
261
|
+
action.reportValue(name, value)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
fun reportIntValueInAction(actionKey: String, name: String, value: Int, platform: String?) {
|
|
266
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
267
|
+
val action = getAction(actionKey) ?: return
|
|
268
|
+
action.reportValue(name, value)
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
fun reportDoubleValueInAction(
|
|
273
|
+
actionKey: String,
|
|
274
|
+
name: String,
|
|
275
|
+
value: Double,
|
|
276
|
+
platform: String?
|
|
277
|
+
) {
|
|
278
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
279
|
+
val action = getAction(actionKey) ?: return
|
|
280
|
+
action.reportValue(name, value)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
fun sendBizEvent(type: String, attributes: ReadableMap, platform: String?) {
|
|
285
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
286
|
+
Dynatrace.sendBizEvent(type, JSONObject(DynatraceUtils.toHashMap(attributes)))
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
fun forwardEvent(attributes: ReadableMap) {
|
|
291
|
+
HybridBridge.forwardEvent(JSONObject(DynatraceUtils.toHashMap(attributes)))
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
fun startView(name: String) {
|
|
295
|
+
Dynatrace.startView(name)
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
fun stopView() {
|
|
299
|
+
Dynatrace.stopView()
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
fun setGPSLocation(lat: Double, lng: Double, platform: String?) {
|
|
303
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
304
|
+
val location = Location("")
|
|
305
|
+
|
|
306
|
+
location.apply {
|
|
307
|
+
latitude = lat
|
|
308
|
+
longitude = lng
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
Dynatrace.setGpsLocation(location)
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
fun flushEvents(platform: String?) {
|
|
316
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
317
|
+
Dynatrace.flushEvents()
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
fun isCrashReportingOptedIn(platform: String?, promise: Promise) {
|
|
322
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
323
|
+
promise.resolve(Dynatrace.isCrashReportingOptedIn())
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
fun setCrashReportingOptedIn(crashReporting: Boolean, platform: String?) {
|
|
328
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
329
|
+
Dynatrace.setCrashReportingOptedIn(crashReporting)
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
fun setDataCollectionLevel(collectionLevel: String, platform: String?) {
|
|
334
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
335
|
+
Dynatrace.setDataCollectionLevel(DataCollectionLevel.valueOf(collectionLevel))
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
fun getDataCollectionLevel(platform: String?, promise: Promise) {
|
|
340
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
341
|
+
val level = Dynatrace.getDataCollectionLevel()
|
|
342
|
+
promise.resolve(level.name)
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
fun setBeaconHeaders(headers: ReadableMap?, platform: String?) {
|
|
347
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
348
|
+
if (headers == null) {
|
|
349
|
+
Dynatrace.setBeaconHeaders(null)
|
|
350
|
+
} else {
|
|
351
|
+
val beaconHeaders = mutableMapOf<String, String?>()
|
|
352
|
+
val iterator = headers.keySetIterator()
|
|
353
|
+
while (iterator.hasNextKey()) {
|
|
354
|
+
val currentKey = iterator.nextKey()
|
|
355
|
+
beaconHeaders[currentKey] = headers.getString(currentKey)
|
|
356
|
+
}
|
|
357
|
+
Dynatrace.setBeaconHeaders(beaconHeaders)
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
fun applyUserPrivacyOptions(userPrivacyOptions: ReadableMap, platform: String?) {
|
|
363
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
364
|
+
val optionsBuilder = UserPrivacyOptions.builder()
|
|
365
|
+
optionsBuilder.withCrashReportingOptedIn(userPrivacyOptions.getBoolean("_crashReportingOptedIn"))
|
|
366
|
+
optionsBuilder.withDataCollectionLevel(
|
|
367
|
+
DataCollectionLevel.valueOf(
|
|
368
|
+
userPrivacyOptions.getString(
|
|
369
|
+
"_dataCollectionLevel"
|
|
370
|
+
)!!
|
|
371
|
+
)
|
|
372
|
+
)
|
|
373
|
+
Dynatrace.applyUserPrivacyOptions(
|
|
374
|
+
optionsBuilder
|
|
375
|
+
.build()
|
|
376
|
+
)
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
fun getUserPrivacyOptions(platform: String?, promise: Promise) {
|
|
381
|
+
if (shouldWorkOnAndroid(platform)) {
|
|
382
|
+
val options = Dynatrace.getUserPrivacyOptions()
|
|
383
|
+
val privacyMap = Arguments.createMap()
|
|
384
|
+
privacyMap.putString("dataCollectionLevel", options.dataCollectionLevel.name)
|
|
385
|
+
privacyMap.putBoolean("crashReportingOptedIn", options.isCrashReportingOptedIn)
|
|
386
|
+
promise.resolve(privacyMap)
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
@Suppress("UNUSED_PARAMETER")
|
|
391
|
+
fun addListener(eventName: String) {
|
|
392
|
+
// Here because of event emitter
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
@Suppress("UNUSED_PARAMETER")
|
|
396
|
+
fun removeListeners(count: Double) {
|
|
397
|
+
// Here because of event emitter
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
private fun newAction(name: String, key: String) {
|
|
401
|
+
actions[key] = _internal.enterAction(name)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
private fun getAction(key: String): DTXAction? {
|
|
405
|
+
return actions[key]
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
private fun shouldWorkOnAndroid(platform: String?): Boolean {
|
|
409
|
+
return platform == null || platform == PLATFORM_ANDROID || platform == ""
|
|
410
|
+
}
|
|
411
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
package com.dynatrace.android.agent
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.TurboReactPackage
|
|
5
|
+
import com.facebook.react.bridge.NativeModule
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
8
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
9
|
+
import com.facebook.react.uimanager.ViewManager
|
|
10
|
+
import java.util.Arrays
|
|
11
|
+
|
|
12
|
+
class DynatraceReactPackage : TurboReactPackage() {
|
|
13
|
+
init {
|
|
14
|
+
setupAppStartListener()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
18
|
+
return emptyList()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
22
|
+
val bridge = DynatraceInternalModule(reactContext)
|
|
23
|
+
val appStart = DynatraceAppStartModule(reactContext)
|
|
24
|
+
return Arrays.asList<NativeModule>(
|
|
25
|
+
DynatraceRNBridge(reactContext, bridge),
|
|
26
|
+
bridge,
|
|
27
|
+
appStart
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
|
32
|
+
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
|
33
|
+
val isTurboModule: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
|
|
34
|
+
moduleInfos[BRIDGE_NAME] = ReactModuleInfo(
|
|
35
|
+
BRIDGE_NAME,
|
|
36
|
+
BRIDGE_NAME,
|
|
37
|
+
false, // canOverrideExistingModule
|
|
38
|
+
false, // needsEagerInit
|
|
39
|
+
true, // hasConstants
|
|
40
|
+
false, // isCxxModule
|
|
41
|
+
isTurboModule // isTurboModule
|
|
42
|
+
)
|
|
43
|
+
return ReactModuleInfoProvider { moduleInfos }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
47
|
+
return if (name == BRIDGE_NAME) {
|
|
48
|
+
DynatraceAppStartModule(reactContext)
|
|
49
|
+
DynatraceRNBridge(reactContext, DynatraceInternalModule(reactContext))
|
|
50
|
+
} else {
|
|
51
|
+
null
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|