@dynatrace/react-native-plugin 2.323.1 → 2.323.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 +21 -2
- package/android/build.gradle +2 -2
- package/files/plugin-runtime.gradle +8 -1
- package/index.js +1 -0
- package/instrumentation/DynatraceInstrumentation.js +1 -1
- package/instrumentation/jsx/ElementHelper.js +0 -5
- package/instrumentation/libs/react-native/Switch.js +55 -12
- package/instrumentation/libs/withOnPressMonitoring.js +1 -1
- package/lib/core/Dynatrace.js +4 -1
- package/lib/core/ErrorHandler.js +18 -34
- package/lib/next/Dynatrace.js +13 -10
- package/lib/next/events/EventCreator.js +2 -1
- package/lib/next/events/HttpRequestEventBuilder.js +196 -0
- package/lib/next/events/ViewInfoCreator.js +1 -1
- package/lib/next/events/modifier/EventModifierUtil.js +14 -1
- package/lib/next/events/modifier/SendEventValidation.js +23 -10
- package/lib/next/events/spec/EventSpecContstants.js +1 -1
- package/package.json +3 -3
- package/typings/react-native-dynatrace.d.ts +121 -1
- package/instrumentation/jsx/components/Switch.js +0 -57
package/README.md
CHANGED
|
@@ -21,13 +21,14 @@ If you want to start using this plugin and are not a Dynatrace customer yet, hea
|
|
|
21
21
|
## Requirements
|
|
22
22
|
* React v16.8 or newer
|
|
23
23
|
* React Native v0.60 or newer
|
|
24
|
-
* For Android users:
|
|
24
|
+
* For Android users:
|
|
25
25
|
* SDK version 21+
|
|
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)
|
|
29
30
|
* For iOS users: Minimum iOS 12
|
|
30
|
-
* NodeJS
|
|
31
|
+
* NodeJS 16.0.0+ since our dependencies require NodeJS 16.0.0
|
|
31
32
|
|
|
32
33
|
## Agent Versions
|
|
33
34
|
This agent versions are configured in this plugin:
|
|
@@ -80,6 +81,7 @@ This agent versions are configured in this plugin:
|
|
|
80
81
|
* [React Automatic Runtime](#react-automatic-runtime)
|
|
81
82
|
* [Using a second transformer besides the dynatrace transformer](#using-a-second-transformer-besides-the-dynatrace-transformer)
|
|
82
83
|
* [Upgrading project to Gradle 7](#updating-to-gradle-7)
|
|
84
|
+
* [Kotlin Compatibility Note](#⚠️-kotlin-compatibility-note)
|
|
83
85
|
* [Maven Central in top-level gradle file](#maven-central-in-top-level-gradle-file)
|
|
84
86
|
* [Configuration of standalone React Native project](#configuration-of-standalone-react-native-project)
|
|
85
87
|
* [Instrumentation Overhead](#instrumentation-overhead)
|
|
@@ -1378,6 +1380,18 @@ dependencies {
|
|
|
1378
1380
|
|
|
1379
1381
|
```
|
|
1380
1382
|
|
|
1383
|
+
## ⚠️ Kotlin Compatibility Note
|
|
1384
|
+
|
|
1385
|
+
Our Android Agent currently (2025-09-15) 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:
|
|
1386
|
+
|
|
1387
|
+
Kotlin embeds language-specific features that Java doesn't natively support (like nullability and extension functions) into bytecode using `@Metadata` annotations. These annotations include a `metadataVersion`.
|
|
1388
|
+
|
|
1389
|
+
- **React Native 0.66**, for instance, works with Kotlin 2.0.21 because its `react-native-gradle-plugin` does **not use Kotlin**, avoiding metadata conflicts.
|
|
1390
|
+
- **React Native 0.71**, for instance, uses a `react-native-gradle-plugin` compiled with Kotlin **1.7.22**, which expects `metadataVersion 1.6.0`. Using Kotlin 2.0.21 (which produces `metadataVersion 1.9.0`) can lead to build failures.
|
|
1391
|
+
- **React Native 0.72**, for instance, again is compatible with Kotlin 2.0.21, as its `react-native-gradle-plugin` expects a metadata version that is compatible with `1.9.0`.
|
|
1392
|
+
|
|
1393
|
+
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`.
|
|
1394
|
+
|
|
1381
1395
|
## Configuration of standalone React Native project
|
|
1382
1396
|
|
|
1383
1397
|
This section explains the configuration of a standalone React Native project. This means you have a React Native project, but don't use the typicial `iOS` and `android` folders. Instead you have a seperate native `iOS` or `android` project which is embedding your React Native project.
|
|
@@ -1477,6 +1491,11 @@ If you are struggling with a problem, submit a support ticket to Dynatrace (supp
|
|
|
1477
1491
|
<br/><br/>
|
|
1478
1492
|
## Changelog
|
|
1479
1493
|
|
|
1494
|
+
2.323.2
|
|
1495
|
+
* Fixed error "Execution failed for task ':app:mergeReleaseAssets'. A problem occured starting process 'command 'npx''" when building for release on Windows.
|
|
1496
|
+
* Downgraded required NodeJS version to 16.0.0+
|
|
1497
|
+
* Fixing Switch instrumentation for React Native 0.81+
|
|
1498
|
+
|
|
1480
1499
|
2.323.1
|
|
1481
1500
|
* Updated Android (8.323.1.1002) & iOS Agent (8.323.1.1009)
|
|
1482
1501
|
* Fixing Touchable/Text instrumentation for React Native 0.81+
|
package/android/build.gradle
CHANGED
|
@@ -11,7 +11,7 @@ def isNewArchitectureEnabled() {
|
|
|
11
11
|
buildscript {
|
|
12
12
|
repositories {
|
|
13
13
|
google()
|
|
14
|
-
|
|
14
|
+
mavenCentral()
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
dependencies {
|
|
@@ -68,7 +68,7 @@ android {
|
|
|
68
68
|
|
|
69
69
|
repositories {
|
|
70
70
|
google()
|
|
71
|
-
|
|
71
|
+
mavenCentral()
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
dependencies {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
|
|
2
|
+
|
|
1
3
|
android.applicationVariants.all { variant ->
|
|
2
4
|
if (variant.buildType.name == "release") {
|
|
3
5
|
variant.mergeAssetsProvider.configure { task ->
|
|
@@ -10,7 +12,12 @@ android.applicationVariants.all { variant ->
|
|
|
10
12
|
|
|
11
13
|
exec {
|
|
12
14
|
workingDir rootDir
|
|
13
|
-
|
|
15
|
+
if (DefaultNativePlatform.currentOperatingSystem.isWindows()) {
|
|
16
|
+
// On windows, npx.cmd may not be a true binary executable and may need to be interpreted by a shell instead of executed direclty
|
|
17
|
+
commandLine 'cmd', '/c', 'npx', 'lineOffsetDynatrace', 'env=prod'
|
|
18
|
+
} else {
|
|
19
|
+
commandLine 'npx', 'lineOffsetDynatrace', 'env=prod'
|
|
20
|
+
}
|
|
14
21
|
}
|
|
15
22
|
|
|
16
23
|
} else {
|
package/index.js
CHANGED
|
@@ -8,3 +8,4 @@ export { ApplicationHandler } from './lib/core/Application';
|
|
|
8
8
|
export { UserPrivacyOptions } from './lib/core/UserPrivacyOptions';
|
|
9
9
|
export { DynatraceWebRequestTiming } from './lib/core/DynatraceWebRequestTiming';
|
|
10
10
|
export { createElement } from './instrumentation/jsx/CreateElement';
|
|
11
|
+
export { default as HttpRequestEventBuilder } from './lib/next/events/HttpRequestEventBuilder'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var o,n=require("@babel/runtime/helpers/interopRequireDefault"),e=n(require("@babel/runtime/helpers/toConsumableArray")),l=(Object.defineProperty(exports,"t",{value:!0}),exports.instrument=void 0,require("path")),i=require("jscodeshift"),u=require("jscodeshift/src/Collection"),r=require("../scripts/FileOperationHelper"),c=require("../scripts/PathsConstants"),f=require("../lib/core/util/GetValuesFromPackage"),t=require("../scripts/util/InstrumentUtil"),a=require("./libs/react-native/Touchables.InstrInfo"),s=require("./libs/react-native/RefreshControl.InstrInfo"),d=require("./libs/react-native/Switch.InstrInfo"),v=require("./libs/community/gesture-handler/Touchables.InstrInfo"),p=require("./libs/community/Picker.InstrInfo"),m=require("./model/Types"),y=require("./parser/ParserUtil"),g=((n=>{n[n.i=-1]="Filtered",n[n.u=0]="Normal",n[n.o=1]="ReactNative",n[n.l=2]="React",n[n.v=3]="ReactNativeCssInterop"})(o=o||{}),[]),b=(g.push.apply(g,(0,e.default)(a.instrumentationInfo)),g.push.apply(g,(0,e.default)(s.instrumentationInfo)),g.push.apply(g,(0,e.default)(d.instrumentationInfo)),g.push.apply(g,(0,e.default)(v.instrumentationInfo)),g.push.apply(g,(0,e.default)(p.instrumentationInfo)),["AppRegistry","AppRegistryImpl","renderApplication","setUpErrorHandling"]),U="@dynatrace/react-native-plugin/instrumentation/libs",instrument=function(n,e,r){e=k(e);var t,i=K(e);if(i!==o.i){var u=!1,a=I(e,n);if(i===o.l)w(a),u=!0;else if(i===o.o)e.endsWith("AppRegistryImpl.js")?null!=r&&r.autoStart&&J(a)&&(u=!0):e.endsWith("AppRegistry.js")?null!=r&&r.autoStart&&M(a)&&(u=!0):e.endsWith("renderApplication.js")?(q(a),u=!0):e.endsWith("setUpErrorHandling.js")&&void 0!==r&&r.autoStart&&r.errorHandler.enabled&&(G(a,r.autoStart,r.errorHandler.reportFatalErrorAsCrash),u=!0);else if(i===o.v)u=z(a)||u;else{var i=T(e,r);if(r.custom.reactnavigation&&B(e,a))u=!0;else{if(!i.input&&!i.lifecycle)return null!=r&&r.debug&&console.log("Dynatrace - Filtered All: ".concat(e)),N(e),n;i.lifecycle&&q(a)&&(u=!0),i.input&&g.forEach(function(n){n=Y(a,n);a=n.root,u=u||n.p})}}u?(n=a.toSource({quote:"single"}),x(n,e)):N(e),null!=r&&r.debug&&u&&console.log("Dynatrace - Modified Filename: "+e)}else e.includes(l.join("@dynatrace","react-native-plugin"))&&e.endsWith(l.join("lib","core","configuration","ConfigurationPreset.js"))&&void 0!==r&&(i=(0,f.getHostAppBundleInfo)(c.default.getPackageJsonFile()),t=I(e,n),void 0!==r.lifecycle&&j(t,"getLifecycleUpdate",r.lifecycle.includeUpdate),void 0!==r.debug&&j(t,"getLogLevel",r.debug?0:1),void 0!==r.bundleName?j(t,"getBundleName",r.bundleName):null!==i&&j(t,"getBundleName",null==i?void 0:i.name),void 0!==r.bundleVersion?j(t,"getBundleVersion",r.bundleVersion):null!==i&&j(t,"getBundleVersion",null==i?void 0:i.version),void 0!==r.input&&void 0!==r.input.actionNamePrivacy&&j(t,"getActionNamePrivacy",r.input.actionNamePrivacy),void 0!==r.errorHandler&&(j(t,"isErrorHandlerEnabled",r.errorHandler.enabled),j(t,"isReportFatalErrorAsCrash",r.errorHandler.reportFatalErrorAsCrash)),r.autoStart&&j(t,"isAutoStartupEnabled",r.autoStart),n=t.toSource({quote:"single"}),x(n,e));return n},B=(exports.instrument=instrument,function(n,e){return!!O(n,e)&&(n="import { registerListener } from '".concat(U,"/react-navigation/ReactNavigation';"),e.find(i.ImportDeclaration).at(0).insertBefore(n),!0)}),O=function(n,e){var r=!1;return n.includes("react-navigation")&&n.includes("NavigationContainer.tsx")&&e.find(i.VariableDeclarator).forEach(function(n){r||null==n.value||null==n.value.id||"refContainer"!==n.value.id.name||null!=n.parent&&null!=n.parent.value&&null!=n.parent.value.type&&"VariableDeclaration"===n.parent.value.type&&(n.parent.insertAfter("registerListener(refContainer);"),r=!0)}),r},q=function(n){var e=n.findJSXElements(),t=!1;return 0<e.length&&(n.find(i.FunctionDeclaration).forEach(function(n){var e,r=(0,u.fromPaths)([n]);0<r.findJSXElements().length&&null!=n&&null!=n.value&&null!=n.value.id&&n.value.id.name.toString()&&(e=r.find(i.ClassDeclaration),r=r.find(i.ClassExpression),0===e.length)&&0===r.length&&(A(n,m.Types.FunctionalComponent,n.value.id.name.toString()),t=!0)}),n.find(i.ClassDeclaration).forEach(function(n){0<(0,u.fromPaths)([n]).findJSXElements().length&&null!=n&&null!=n.value&&n.value.id&&n.value.id.name.toString()&&(A(n,m.Types.ClassComponent,n.value.id.name.toString()),t=!0)}),n.find(i.ArrowFunctionExpression).forEach(function(n){0<(0,u.fromPaths)([n]).findJSXElements().length&&null!=n.parent&&null!=n.parent.value&&null!=n.parent.value.id&&null!=n.parent.value.id.name&&(A(n,m.Types.FunctionalComponent,n.parent.value.id.name),t=!0)})),t},A=function(n,e,r){for(e=i.expressionStatement(i.assignmentExpression("=",i.memberExpression(i.identifier(r),i.identifier("_dtInfo")),V(e,r)));"body"!==(null==n?void 0:n.parentPath.name);)n=n.parentPath;void 0!==n.parentPath&&n.insertAfter(e)},V=function(n,e){return i.objectExpression([i.objectProperty(i.identifier("type"),i.numericLiteral(n)),i.objectProperty(i.identifier("name"),i.stringLiteral(e))])},j=function(n,e,r){var n=n.find(i.Identifier).filter(function(n){return n.node.name===e});1===n.length&&"ReturnStatement"===(n=n.paths()[0].parent.value.body.body[0]).type&&("boolean"==typeof r&&(n.argument=i.booleanLiteral(r)),"string"==typeof r&&(n.argument=i.stringLiteral(r)),"number"==typeof r)&&(n.argument=i.numericLiteral(r))},I=function(n,e){return i.withParser((0,y.chooseParser)(n,e))(e)},k=function(n){return l.isAbsolute(n)?n.replace(c.default.getApplicationPath()+l.sep,""):n},N=function(n){try{var e=l.join(c.default.getBuildPath(),n+t.INSTRUMENTED_FILE_EXTENSION);r.default.checkIfFileExistsSync(e),r.default.deleteFileSync(e)}catch(n){}},x=function(n,e){e=l.join(c.default.getBuildPath(),e);try{r.default.checkIfFileExistsSync(l.dirname(e))}catch(n){r.default.createDirectorySync(l.dirname(e))}r.default.writeTextToFileSync(e+t.INSTRUMENTED_FILE_EXTENSION,n)},T=function(n,e){var r={input:!1,lifecycle:!1};return void 0!==e&&(void 0!==e.lifecycle&&void 0!==e.lifecycle.instrument&&e.lifecycle.instrument(n)&&(r.lifecycle=!0),void 0!==e.input)&&void 0!==e.input.instrument&&e.input.instrument(n)&&(r.input=!0),r},w=function(n){var e,n=n.find(i.Program);1===n.length&&(e=i.expressionStatement(i.callExpression(i.memberExpression(i.callExpression(i.identifier("require"),[i.stringLiteral("@dynatrace/react-native-plugin/instrumentation/jsx/ElementHelper")]),i.identifier("instrumentCreateElement")),[i.memberExpression(i.identifier("module"),i.identifier("exports"))])),n.paths()[0].node.body.push(e))},J=function(n){var e=n.find(i.FunctionDeclaration,{id:{name:"runApplication"}});return 1===e.length&&(D(n,{m:"_DynatraceApplicationHandler",module:"@dynatrace/react-native-plugin",reference:"ApplicationHandler"}),H(e.get().value.body.body,0,_("_DynatraceApplicationHandler","startup",[])),!0)},M=function(n){var e=n.find(i.ObjectMethod,{key:{name:"runApplication"}});return 1===e.length&&(D(n,{m:"_DynatraceApplicationHandler",module:"@dynatrace/react-native-plugin",reference:"ApplicationHandler"}),H(e.get().value.body.body,0,_("_DynatraceApplicationHandler","startup",[])),!0)},G=function(n,e,r){n=n.paths()[0].value.program.body;null!=n&&(H(n,n.length,L({m:"_DynatraceErrorHandler",module:"@dynatrace/react-native-plugin/lib/core/ErrorHandler",reference:""})),H(n,n.length,_("_DynatraceErrorHandler","registerErrorHandler",[i.literal(r)])))},z=function(n){var e=!1,n=n.find(i.CallExpression,{callee:{name:"require"}});return n.find(i.Literal,{value:"react/jsx-runtime"}).replaceWith(function(n){n=n.node;return n.value="@dynatrace/react-native-plugin/jsx-runtime",e=!0,n}),n.find(i.Literal,{value:"react/jsx-dev-runtime"}).replaceWith(function(n){n=n.node;return n.value="@dynatrace/react-native-plugin/jsx-dev-runtime",e=!0,n}),e},H=function(n,e){for(var r=arguments.length,t=new Array(2<r?r-2:0),i=2;i<r;i++)t[i-2]=arguments[i];return n.splice.apply(n,[e,0].concat(t))},K=function(n){if(n.includes("@dynatrace"))return o.i;var e=l.extname(n);if(".js"!==e&&".ts"!==e&&".tsx"!==e&&".jsx"!==e)return o.i;for(var r=l.parse(n),t=r.dir.split(l.sep),i=0;i<t.length;i++)if("node_modules"===t[i]){if("react-native"===t[i+1]||"create-react-class"===t[i+1]||"react-clone-referenced-element"===t[i+1])return b.includes(r.name)?o.o:o.i;if("react"===t[i+1]&&"index"===r.name)return o.l;if("react-native-css-interop"===t[i+1]&&("jsx-runtime"===r.name||"jsx-dev-runtime"===r.name))return o.v}return o.u},Q=function(n,e,r){var t=W(n,e,r);return X(n,e,r)||t},W=function(n,e,r){var t=Z(n,e);return 0<t.length&&(void 0!==(t=R(t,e.reference,!1))&&(r.m=t.localName),un(n,r),!0)},X=function(n,e,r){var t=E(n,e.module);if(1===t.length){t=R(t,e.reference,!0);if(void 0!==t)return an(n,r.defaultImport,t.localName,"ImportNamespaceSpecifier"===t.type),!0}return!1},Y=function(n,e){var r=JSON.parse(JSON.stringify(e.new));return{root:n,p:Q(n,e.old,r)||$(n,e.old,e.new.defaultImport)}},Z=function(n,e){return n.find(i.ImportDeclaration).filter(function(n){return n.node.source.value===e.module&&null!=n.node.specifiers&&n.node.specifiers.some(function(n){return h(n)&&n.imported.name===e.reference||n.local&&n.local.name===e.reference})})},h=function(n){return void 0!==n.imported},$=function(n,e,r){var t=!1;return n.find(i.CallExpression).filter(function(n){return nn(n.node.callee)&&en(n.node.arguments[0])&&n.node.arguments[0].value===e.module&&void 0!==n.parent}).forEach(function(n){(void 0===n.parent.value.property||void 0!==n.parent.value.property&&void 0!==n.parent.value.property.name&&n.parent.value.property.name===e.reference)&&(n.node.arguments[0].value=r,t=t||!0)}),t},nn=function(n){return"require"===n.name},en=function(n){return"StringLiteral"===n.type||"Literal"===n.type},E=function(n,e){return n.find(i.ImportDeclaration).filter(function(n){return n.node.source.value===e})},R=function(n,r,t){var i;return n.forEach(function(n){void 0!==n.node.specifiers&&(n.node.specifiers=n.node.specifiers.filter(function(n){var e;return h(n)&&!t?((e=n.imported.name!==r)||null==n.local||n.imported.name===n.local.name||(i={localName:n.local.name.toString(),type:n.type}),e):!(!h(n)&&t&&(null!=n.local&&(i={localName:n.local.name.toString(),type:n.type}),1))}),0===n.node.specifiers.length)&&n.prune()}),i},rn=function(n,e){n.find(i.ImportDeclaration).filter(function(n){return n.node.source.value===e.module}).forEach(function(n){null!=n.node.specifiers&&n.node.specifiers.push(P(e))})},tn=function(n,e,r){n.find(i.ImportDeclaration).filter(function(n){return n.node.source.value===e}).forEach(function(n){null!=n.node.specifiers&&n.node.specifiers.push(r)})},C=function(n,e,r){var t=n.find(i.ImportDeclaration);0<t.length?i(t.paths()[0]).insertAfter(F(e,r)):1===(t=n.find(i.Program)).length&&t.paths()[0].node.body.unshift(F(e,r))},un=function(n,e){0<E(n,e.module).length?rn(n,e):C(n,e.module,[P(e)])},an=function(n,e,r,t){var i=E(n,e),t=(t?dn:sn)(r);0<i.length?tn(n,e,t):C(n,e,[t])},D=function(n,e){n=n.find(i.VariableDeclaration);0<n.length&&i(n.paths()[0]).insertAfter(L(e))},_=function(n,e,r){return i.expressionStatement(on(n,e,r))},on=function(n,e,r){return i.callExpression(fn(n,e),r)},L=function(n){return i.variableDeclaration("var",[ln(n)])},ln=function(n){return i.variableDeclarator(void 0!==n.m?i.identifier(n.m):i.identifier(n.reference),(0<n.reference.length?cn:S)(n))},cn=function(n){return i.memberExpression(S(n),i.identifier(n.reference))},fn=function(n,e){return i.memberExpression(i.identifier(n),i.identifier(e))},S=function(n){return i.callExpression(i.identifier("require"),[i.literal(n.module)])},F=function(n,e){return i.importDeclaration(e,i.literal(n))},P=function(n){return void 0!==n.m?i.importSpecifier(i.identifier(n.reference),i.identifier(n.m)):i.importSpecifier(i.identifier(n.reference))},sn=function(n){return i.importDefaultSpecifier(i.identifier(n))},dn=function(n){return i.importNamespaceSpecifier(i.identifier(n))};
|
|
1
|
+
var o,n=require("@babel/runtime/helpers/interopRequireDefault"),e=n(require("@babel/runtime/helpers/toConsumableArray")),c=(Object.defineProperty(exports,"t",{value:!0}),exports.instrument=void 0,require("path")),u=require("jscodeshift"),i=require("jscodeshift/src/Collection"),r=require("../scripts/FileOperationHelper"),l=require("../scripts/PathsConstants"),f=require("../lib/core/util/GetValuesFromPackage"),t=require("../scripts/util/InstrumentUtil"),a=require("./libs/react-native/Touchables.InstrInfo"),s=require("./libs/react-native/RefreshControl.InstrInfo"),v=require("./libs/react-native/Switch.InstrInfo"),d=require("./libs/community/gesture-handler/Touchables.InstrInfo"),p=require("./libs/community/Picker.InstrInfo"),m=require("./model/Types"),y=require("./parser/ParserUtil"),g=((n=>{n[n.i=-1]="Filtered",n[n.u=0]="Normal",n[n.o=1]="ReactNative",n[n.l=2]="React",n[n.v=3]="ReactNativeCssInterop"})(o=o||{}),[]),q=(g.push.apply(g,(0,e.default)(a.instrumentationInfo)),g.push.apply(g,(0,e.default)(s.instrumentationInfo)),g.push.apply(g,(0,e.default)(v.instrumentationInfo)),g.push.apply(g,(0,e.default)(d.instrumentationInfo)),g.push.apply(g,(0,e.default)(p.instrumentationInfo)),["AppRegistry","AppRegistryImpl","renderApplication","ExceptionsManager"]),b="@dynatrace/react-native-plugin/instrumentation/libs",instrument=function(n,e,r){e=T(e);var t=z(e);if(t!==o.i){var i=!1,u=I(e,n);if(t===o.l)k(u),i=!0;else if(t===o.o)e.endsWith("AppRegistryImpl.js")?null!=r&&r.autoStart&&U(u)&&(i=!0):e.endsWith("AppRegistry.js")?null!=r&&r.autoStart&&w(u)&&(i=!0):e.endsWith("renderApplication.js")?(A(u),i=!0):e.endsWith("ExceptionsManager.js")&&(a=void 0!==r&&r.autoStart&&r.errorHandler.enabled,J(u,r.errorHandler.reportFatalErrorAsCrash,a),i=!0);else if(t===o.v)i=G(u)||i;else{var a=V(e,r);if(r.custom.reactnavigation&&B(e,u))i=!0;else{if(!a.input&&!a.lifecycle)return null!=r&&r.debug&&console.log("Dynatrace - Filtered All: ".concat(e)),h(e),n;a.lifecycle&&A(u)&&(i=!0),a.input&&g.forEach(function(n){n=X(u,n);u=n.root,i=i||n.p})}}i?(n=u.toSource({quote:"single"}),N(n,e)):h(e),null!=r&&r.debug&&i&&console.log("Dynatrace - Modified Filename: "+e)}else e.includes(c.join("@dynatrace","react-native-plugin"))&&e.endsWith(c.join("lib","core","configuration","ConfigurationPreset.js"))&&void 0!==r&&(t=(0,f.getHostAppBundleInfo)(l.default.getPackageJsonFile()),a=I(e,n),void 0!==r.lifecycle&&j(a,"getLifecycleUpdate",r.lifecycle.includeUpdate),void 0!==r.debug&&j(a,"getLogLevel",r.debug?0:1),void 0!==r.bundleName?j(a,"getBundleName",r.bundleName):null!==t&&j(a,"getBundleName",null==t?void 0:t.name),void 0!==r.bundleVersion?j(a,"getBundleVersion",r.bundleVersion):null!==t&&j(a,"getBundleVersion",null==t?void 0:t.version),void 0!==r.input&&void 0!==r.input.actionNamePrivacy&&j(a,"getActionNamePrivacy",r.input.actionNamePrivacy),void 0!==r.errorHandler&&(j(a,"isErrorHandlerEnabled",r.errorHandler.enabled),j(a,"isReportFatalErrorAsCrash",r.errorHandler.reportFatalErrorAsCrash)),r.autoStart&&j(a,"isAutoStartupEnabled",r.autoStart),n=a.toSource({quote:"single"}),N(n,e));return n},B=(exports.instrument=instrument,function(n,e){return!!M(n,e)&&(n="import { registerListener } from '".concat(b,"/react-navigation/ReactNavigation';"),e.find(u.ImportDeclaration).at(0).insertBefore(n),!0)}),M=function(n,e){var r=!1;return n.includes("react-navigation")&&n.includes("NavigationContainer.tsx")&&e.find(u.VariableDeclarator).forEach(function(n){r||null==n.value||null==n.value.id||"refContainer"!==n.value.id.name||null!=n.parent&&null!=n.parent.value&&null!=n.parent.value.type&&"VariableDeclaration"===n.parent.value.type&&(n.parent.insertAfter("registerListener(refContainer);"),r=!0)}),r},A=function(n){var e=n.findJSXElements(),t=!1;return 0<e.length&&(n.find(u.FunctionDeclaration).forEach(function(n){var e,r=(0,i.fromPaths)([n]);0<r.findJSXElements().length&&null!=n&&null!=n.value&&null!=n.value.id&&n.value.id.name.toString()&&(e=r.find(u.ClassDeclaration),r=r.find(u.ClassExpression),0===e.length)&&0===r.length&&(x(n,m.Types.FunctionalComponent,n.value.id.name.toString()),t=!0)}),n.find(u.ClassDeclaration).forEach(function(n){0<(0,i.fromPaths)([n]).findJSXElements().length&&null!=n&&null!=n.value&&n.value.id&&n.value.id.name.toString()&&(x(n,m.Types.ClassComponent,n.value.id.name.toString()),t=!0)}),n.find(u.ArrowFunctionExpression).forEach(function(n){0<(0,i.fromPaths)([n]).findJSXElements().length&&null!=n.parent&&null!=n.parent.value&&null!=n.parent.value.id&&null!=n.parent.value.id.name&&(x(n,m.Types.FunctionalComponent,n.parent.value.id.name),t=!0)})),t},x=function(n,e,r){for(e=u.expressionStatement(u.assignmentExpression("=",u.memberExpression(u.identifier(r),u.identifier("_dtInfo")),O(e,r)));"body"!==(null==n?void 0:n.parentPath.name);)n=n.parentPath;void 0!==n.parentPath&&n.insertAfter(e)},O=function(n,e){return u.objectExpression([u.objectProperty(u.identifier("type"),u.numericLiteral(n)),u.objectProperty(u.identifier("name"),u.stringLiteral(e))])},j=function(n,e,r){var n=n.find(u.Identifier).filter(function(n){return n.node.name===e});1===n.length&&"ReturnStatement"===(n=n.paths()[0].parent.value.body.body[0]).type&&("boolean"==typeof r&&(n.argument=u.booleanLiteral(r)),"string"==typeof r&&(n.argument=u.stringLiteral(r)),"number"==typeof r)&&(n.argument=u.numericLiteral(r))},I=function(n,e){return u.withParser((0,y.chooseParser)(n,e))(e)},T=function(n){return c.isAbsolute(n)?n.replace(l.default.getApplicationPath()+c.sep,""):n},h=function(n){try{var e=c.join(l.default.getBuildPath(),n+t.INSTRUMENTED_FILE_EXTENSION);r.default.checkIfFileExistsSync(e),r.default.deleteFileSync(e)}catch(n){}},N=function(n,e){e=c.join(l.default.getBuildPath(),e);try{r.default.checkIfFileExistsSync(c.dirname(e))}catch(n){r.default.createDirectorySync(c.dirname(e))}r.default.writeTextToFileSync(e+t.INSTRUMENTED_FILE_EXTENSION,n)},V=function(n,e){var r={input:!1,lifecycle:!1};return void 0!==e&&(void 0!==e.lifecycle&&void 0!==e.lifecycle.instrument&&e.lifecycle.instrument(n)&&(r.lifecycle=!0),void 0!==e.input)&&void 0!==e.input.instrument&&e.input.instrument(n)&&(r.input=!0),r},k=function(n){var e,n=n.find(u.Program);1===n.length&&(e=u.expressionStatement(u.callExpression(u.memberExpression(u.callExpression(u.identifier("require"),[u.stringLiteral("@dynatrace/react-native-plugin/instrumentation/jsx/ElementHelper")]),u.identifier("instrumentCreateElement")),[u.memberExpression(u.identifier("module"),u.identifier("exports"))])),n.paths()[0].node.body.push(e))},U=function(n){var e=n.find(u.FunctionDeclaration,{id:{name:"runApplication"}});return 1===e.length&&(_(n,{m:"_DynatraceApplicationHandler",module:"@dynatrace/react-native-plugin",reference:"ApplicationHandler"}),R(e.get().value.body.body,0,F("_DynatraceApplicationHandler","startup",[])),!0)},w=function(n){var e=n.find(u.ObjectMethod,{key:{name:"runApplication"}});return 1===e.length&&(_(n,{m:"_DynatraceApplicationHandler",module:"@dynatrace/react-native-plugin",reference:"ApplicationHandler"}),R(e.get().value.body.body,0,F("_DynatraceApplicationHandler","startup",[])),!0)},J=function(n,r,t){var i=u;n.find(i.FunctionDeclaration,{id:{name:"handleException"}}).forEach(function(n){var e=i.expressionStatement(i.callExpression(i.memberExpression(i.callExpression(i.identifier("require"),[i.literal("@dynatrace/react-native-plugin/lib/core/ErrorHandler")]),i.identifier("reportErrorToDynatrace")),[i.identifier("e"),i.identifier("isFatal"),i.literal(r),i.literal(t)]));n.node.body.body.unshift(e)})},G=function(n){var e=!1,n=n.find(u.CallExpression,{callee:{name:"require"}});return n.find(u.Literal,{value:"react/jsx-runtime"}).replaceWith(function(n){n=n.node;return n.value="@dynatrace/react-native-plugin/jsx-runtime",e=!0,n}),n.find(u.Literal,{value:"react/jsx-dev-runtime"}).replaceWith(function(n){n=n.node;return n.value="@dynatrace/react-native-plugin/jsx-dev-runtime",e=!0,n}),e},R=function(n,e){for(var r=arguments.length,t=new Array(2<r?r-2:0),i=2;i<r;i++)t[i-2]=arguments[i];return n.splice.apply(n,[e,0].concat(t))},z=function(n){if(n.includes("@dynatrace"))return o.i;var e=c.extname(n);if(".js"!==e&&".ts"!==e&&".tsx"!==e&&".jsx"!==e)return o.i;for(var r=c.parse(n),t=r.dir.split(c.sep),i=0;i<t.length;i++)if("node_modules"===t[i]){if("react-native"===t[i+1]||"create-react-class"===t[i+1]||"react-clone-referenced-element"===t[i+1])return q.includes(r.name)?o.o:o.i;if("react"===t[i+1]&&"index"===r.name)return o.l;if("react-native-css-interop"===t[i+1]&&("jsx-runtime"===r.name||"jsx-dev-runtime"===r.name))return o.v}return o.u},K=function(n,e,r){var t=Q(n,e,r);return W(n,e,r)||t},Q=function(n,e,r){var t=Y(n,e);return 0<t.length&&(void 0!==(t=H(t,e.reference,!1))&&(r.m=t.localName),tn(n,r),!0)},W=function(n,e,r){var t=E(n,e.module);if(1===t.length){t=H(t,e.reference,!0);if(void 0!==t)return un(n,r.defaultImport,t.localName,"ImportNamespaceSpecifier"===t.type),!0}return!1},X=function(n,e){var r=JSON.parse(JSON.stringify(e.new));return{root:n,p:K(n,e.old,r)||Z(n,e.old,e.new.defaultImport)}},Y=function(n,e){return n.find(u.ImportDeclaration).filter(function(n){return n.node.source.value===e.module&&null!=n.node.specifiers&&n.node.specifiers.some(function(n){return C(n)&&n.imported.name===e.reference||n.local&&n.local.name===e.reference})})},C=function(n){return void 0!==n.imported},Z=function(n,e,r){var t=!1;return n.find(u.CallExpression).filter(function(n){return $(n.node.callee)&&nn(n.node.arguments[0])&&n.node.arguments[0].value===e.module&&void 0!==n.parent}).forEach(function(n){(void 0===n.parent.value.property||void 0!==n.parent.value.property&&void 0!==n.parent.value.property.name&&n.parent.value.property.name===e.reference)&&(n.node.arguments[0].value=r,t=t||!0)}),t},$=function(n){return"require"===n.name},nn=function(n){return"StringLiteral"===n.type||"Literal"===n.type},E=function(n,e){return n.find(u.ImportDeclaration).filter(function(n){return n.node.source.value===e})},H=function(n,r,t){var i;return n.forEach(function(n){void 0!==n.node.specifiers&&(n.node.specifiers=n.node.specifiers.filter(function(n){var e;return C(n)&&!t?((e=n.imported.name!==r)||null==n.local||n.imported.name===n.local.name||(i={localName:n.local.name.toString(),type:n.type}),e):!(!C(n)&&t&&(null!=n.local&&(i={localName:n.local.name.toString(),type:n.type}),1))}),0===n.node.specifiers.length)&&n.prune()}),i},en=function(n,e){n.find(u.ImportDeclaration).filter(function(n){return n.node.source.value===e.module}).forEach(function(n){null!=n.node.specifiers&&n.node.specifiers.push(P(e))})},rn=function(n,e,r){n.find(u.ImportDeclaration).filter(function(n){return n.node.source.value===e}).forEach(function(n){null!=n.node.specifiers&&n.node.specifiers.push(r)})},D=function(n,e,r){var t=n.find(u.ImportDeclaration);0<t.length?u(t.paths()[0]).insertAfter(S(e,r)):1===(t=n.find(u.Program)).length&&t.paths()[0].node.body.unshift(S(e,r))},tn=function(n,e){0<E(n,e.module).length?en(n,e):D(n,e.module,[P(e)])},un=function(n,e,r,t){var i=E(n,e),t=(t?vn:sn)(r);0<i.length?rn(n,e,t):D(n,e,[t])},_=function(n,e){n=n.find(u.VariableDeclaration);0<n.length&&u(n.paths()[0]).insertAfter(on(e))},F=function(n,e,r){return u.expressionStatement(an(n,e,r))},an=function(n,e,r){return u.callExpression(fn(n,e),r)},on=function(n){return u.variableDeclaration("var",[cn(n)])},cn=function(n){return u.variableDeclarator(void 0!==n.m?u.identifier(n.m):u.identifier(n.reference),(0<n.reference.length?ln:L)(n))},ln=function(n){return u.memberExpression(L(n),u.identifier(n.reference))},fn=function(n,e){return u.memberExpression(u.identifier(n),u.identifier(e))},L=function(n){return u.callExpression(u.identifier("require"),[u.literal(n.module)])},S=function(n,e){return u.importDeclaration(e,u.literal(n))},P=function(n){return void 0!==n.m?u.importSpecifier(u.identifier(n.reference),u.identifier(n.m)):u.importSpecifier(u.identifier(n.reference))},sn=function(n){return u.importDefaultSpecifier(u.identifier(n))},vn=function(n){return u.importNamespaceSpecifier(u.identifier(n))};
|
|
@@ -5,7 +5,6 @@ const Types_1 = require("../model/Types");
|
|
|
5
5
|
const Dynatrace_1 = require("../../lib/core/Dynatrace");
|
|
6
6
|
const Picker_1 = require("./components/Picker");
|
|
7
7
|
const RefreshControl_1 = require("./components/RefreshControl");
|
|
8
|
-
const Switch_1 = require("./components/Switch");
|
|
9
8
|
const FunctionalComponent_1 = require("./components/FunctionalComponent");
|
|
10
9
|
const ClassComponent_1 = require("./components/ClassComponent");
|
|
11
10
|
const instrumentCreateElement = (reactModule) => {
|
|
@@ -38,10 +37,6 @@ const modifyElement = (type, props) => {
|
|
|
38
37
|
props.onRefresh != null) {
|
|
39
38
|
(0, RefreshControl_1.RefreshControlHelper)(Dynatrace_1.Dynatrace).attachOnRefresh(props);
|
|
40
39
|
}
|
|
41
|
-
else if (type._dtInfo.type === Types_1.Types.Switch &&
|
|
42
|
-
props.onValueChange != null) {
|
|
43
|
-
(0, Switch_1.SwitchHelper)(Dynatrace_1.Dynatrace).attachOnValueChange(props);
|
|
44
|
-
}
|
|
45
40
|
else if (props.onValueChange != null &&
|
|
46
41
|
type._dtInfo.type === Types_1.Types.Picker) {
|
|
47
42
|
(0, Picker_1.PickerHelper)(Dynatrace_1.Dynatrace).attachOnValueChange(props);
|
|
@@ -1,15 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
3
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.Switch = void 0;
|
|
14
|
+
exports.wrapOnValueChange = exports.Switch = void 0;
|
|
5
15
|
const react_native_1 = require("react-native");
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
const React = require("react");
|
|
17
|
+
const ConfigurationHandler_1 = require("../../../lib/core/configuration/ConfigurationHandler");
|
|
18
|
+
const Dynatrace_1 = require("../../../lib/core/Dynatrace");
|
|
19
|
+
const ComponentUtil_1 = require("../../jsx/components/ComponentUtil");
|
|
20
|
+
exports.Switch = React.forwardRef((_a, ref) => {
|
|
21
|
+
var { onValueChange } = _a, rest = __rest(_a, ["onValueChange"]);
|
|
22
|
+
const shouldWrap = (0, ComponentUtil_1.isDynatraceIgnored)(rest) || !onValueChange;
|
|
23
|
+
const wrappedOnValueChange = shouldWrap
|
|
24
|
+
? onValueChange
|
|
25
|
+
: (0, exports.wrapOnValueChange)(onValueChange, rest);
|
|
26
|
+
return (React.createElement(react_native_1.Switch, Object.assign({ ref: ref, onValueChange: wrappedOnValueChange }, rest)));
|
|
27
|
+
});
|
|
28
|
+
const wrapOnValueChange = (onValueChange, switchProps) => (value) => {
|
|
29
|
+
const switchName = findSwitchName(switchProps);
|
|
30
|
+
const action = Dynatrace_1.Dynatrace.enterAutoAction(`Touch on ${switchName} to ${value}`);
|
|
31
|
+
let isSync = true;
|
|
32
|
+
try {
|
|
33
|
+
const returnValue = onValueChange(value);
|
|
34
|
+
if (returnValue instanceof Promise) {
|
|
35
|
+
isSync = false;
|
|
36
|
+
return Promise.resolve(returnValue).finally(() => {
|
|
37
|
+
action.leaveAction();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
if (isSync) {
|
|
43
|
+
action.leaveAction();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
exports.wrapOnValueChange = wrapOnValueChange;
|
|
48
|
+
const findSwitchName = (switchProps) => {
|
|
49
|
+
var _a;
|
|
50
|
+
if (switchProps.dtActionName) {
|
|
51
|
+
return switchProps.dtActionName;
|
|
52
|
+
}
|
|
53
|
+
if (ConfigurationHandler_1.ConfigurationHandler.isConfigurationAvailable() &&
|
|
54
|
+
ConfigurationHandler_1.ConfigurationHandler.isActionNamePrivacyEnabled()) {
|
|
55
|
+
return 'Switch';
|
|
56
|
+
}
|
|
57
|
+
return (_a = switchProps.accessibilityLabel) !== null && _a !== void 0 ? _a : 'Switch';
|
|
58
|
+
};
|
|
@@ -71,7 +71,7 @@ const findTouchableName = (props) => {
|
|
|
71
71
|
return props.accessibilityLabel;
|
|
72
72
|
}
|
|
73
73
|
if (typeof props.children === 'function') {
|
|
74
|
-
return
|
|
74
|
+
return null;
|
|
75
75
|
}
|
|
76
76
|
return findTouchableNameRecursive(props.children);
|
|
77
77
|
};
|
package/lib/core/Dynatrace.js
CHANGED
|
@@ -33,7 +33,7 @@ exports.Dynatrace = {
|
|
|
33
33
|
if (configuration !== undefined) {
|
|
34
34
|
yield DynatraceBridge_1.DynatraceNative.start(configuration);
|
|
35
35
|
if (configuration.errorHandler) {
|
|
36
|
-
(0, ErrorHandler_1.
|
|
36
|
+
(0, ErrorHandler_1.startErrorHandler)(configuration.reportFatalErrorAsCrash);
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
39
39
|
logger.debug('Dynatrace error handler will not be enabled as errorHandler was set to false!');
|
|
@@ -353,4 +353,7 @@ exports.Dynatrace = {
|
|
|
353
353
|
sendExceptionEvent: (error, fields) => {
|
|
354
354
|
Dynatrace_1.Dynatrace.sendExceptionEvent(error, fields);
|
|
355
355
|
},
|
|
356
|
+
sendHttpRequestEvent(httpRequestEventBuilder) {
|
|
357
|
+
Dynatrace_1.Dynatrace.sendHttpRequestEvent(httpRequestEventBuilder);
|
|
358
|
+
},
|
|
356
359
|
};
|
package/lib/core/ErrorHandler.js
CHANGED
|
@@ -1,56 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const react_native_1 = require("react-native");
|
|
3
|
+
exports.reportErrorToDynatrace = exports.startErrorHandler = void 0;
|
|
5
4
|
const DynatraceInternal_1 = require("./DynatraceInternal");
|
|
6
5
|
const Dynatrace_1 = require("./Dynatrace");
|
|
7
6
|
const StringUtils_1 = require("./util/StringUtils");
|
|
8
7
|
const ConsoleLogger_1 = require("./logging/ConsoleLogger");
|
|
9
|
-
let _isReportFatalErrorAsCrash = true;
|
|
10
|
-
const _isReactNativeGlobal = (globalScope) => globalScope.ErrorUtils !== undefined;
|
|
11
8
|
const logger = new ConsoleLogger_1.ConsoleLogger('ErrorHandler');
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
});
|
|
19
|
-
const setter = global.ErrorUtils.setGlobalHandler;
|
|
20
|
-
global.ErrorUtils.setGlobalHandler = (errorHandler) => {
|
|
21
|
-
setter((error, isFatal) => {
|
|
22
|
-
(0, exports._reportErrorToDynatrace)(error, isFatal, errorHandler);
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
}
|
|
9
|
+
let manualStart = { enabled: false };
|
|
10
|
+
const startErrorHandler = (reportFatalErrorAsCrash) => {
|
|
11
|
+
manualStart = {
|
|
12
|
+
enabled: true,
|
|
13
|
+
reportFatalErrorAsCrash: reportFatalErrorAsCrash,
|
|
14
|
+
};
|
|
26
15
|
};
|
|
27
|
-
exports.
|
|
28
|
-
const
|
|
16
|
+
exports.startErrorHandler = startErrorHandler;
|
|
17
|
+
const reportErrorToDynatrace = (exception, isFatal, reportFatalErrorAsCrashFromConfig, autoStart) => {
|
|
18
|
+
if (!autoStart && !manualStart)
|
|
19
|
+
return;
|
|
20
|
+
const reportFatalErrorAsCrash = manualStart.enabled
|
|
21
|
+
? manualStart.reportFatalErrorAsCrash
|
|
22
|
+
: reportFatalErrorAsCrashFromConfig;
|
|
29
23
|
if (exception != null && isExceptionAnError(exception)) {
|
|
30
24
|
if (!StringUtils_1.StringUtils.isStringNullEmptyOrUndefined(exception.name)) {
|
|
31
25
|
if (isFatal === undefined) {
|
|
32
26
|
isFatal = false;
|
|
33
27
|
}
|
|
34
|
-
DynatraceInternal_1.DynatraceInternal.reportErrorFromHandler(isFatal, String(exception.name), adjustedReason(exception.message), exception.stack != null ? exception.stack : '',
|
|
35
|
-
logger.debug(`
|
|
28
|
+
DynatraceInternal_1.DynatraceInternal.reportErrorFromHandler(isFatal, String(exception.name), adjustedReason(exception.message), exception.stack != null ? exception.stack : '', reportFatalErrorAsCrash);
|
|
29
|
+
logger.debug(`reportErrorToDynatrace(${exception}, ${isFatal})`);
|
|
36
30
|
}
|
|
37
31
|
}
|
|
38
32
|
else {
|
|
39
33
|
Dynatrace_1.Dynatrace.reportError(String(exception), -1);
|
|
40
|
-
logger.debug(`
|
|
41
|
-
}
|
|
42
|
-
if (oldHandler !== undefined) {
|
|
43
|
-
if (react_native_1.Platform.OS === 'ios') {
|
|
44
|
-
setTimeout(() => {
|
|
45
|
-
oldHandler(exception, isFatal);
|
|
46
|
-
}, 200);
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
oldHandler(exception, isFatal);
|
|
50
|
-
}
|
|
34
|
+
logger.debug(`reportErrorToDynatrace(${exception}, -1)`);
|
|
51
35
|
}
|
|
52
36
|
};
|
|
53
|
-
exports.
|
|
37
|
+
exports.reportErrorToDynatrace = reportErrorToDynatrace;
|
|
54
38
|
const adjustedReason = (reason) => {
|
|
55
39
|
if (!StringUtils_1.StringUtils.isStringNullEmptyOrUndefined(reason)) {
|
|
56
40
|
const reasonNewLineIndex = reason.indexOf('\n');
|
package/lib/next/Dynatrace.js
CHANGED
|
@@ -42,8 +42,7 @@ class DynatraceImpl {
|
|
|
42
42
|
const eventTimestamp = new EventTimestamp_1.EventTimestamp(this.timestampProvider);
|
|
43
43
|
const event = Object.assign(Object.assign({}, (0, EventCreator_1.createCrashEvent)(crash.name, crash.message, crash.stack, isFatal)), eventTimestamp.getEventTimeInfo());
|
|
44
44
|
if (isApiReported) {
|
|
45
|
-
event
|
|
46
|
-
true;
|
|
45
|
+
(0, EventModifierUtil_1.addIsApiReported)(event);
|
|
47
46
|
event["dt.support.is_legacy_api_reported"] = true;
|
|
48
47
|
}
|
|
49
48
|
EventPipeline_1.EventPipeline.insertEvent(event);
|
|
@@ -53,8 +52,7 @@ class DynatraceImpl {
|
|
|
53
52
|
const eventTimestamp = new EventTimestamp_1.EventTimestamp(this.timestampProvider);
|
|
54
53
|
const event = Object.assign(Object.assign({}, (0, EventCreator_1.createErrorCodeEvent)(errorName, errorCode)), eventTimestamp.getEventTimeInfo());
|
|
55
54
|
if (isApiReported) {
|
|
56
|
-
event
|
|
57
|
-
true;
|
|
55
|
+
(0, EventModifierUtil_1.addIsApiReported)(event);
|
|
58
56
|
event["dt.support.is_legacy_api_reported"] = true;
|
|
59
57
|
}
|
|
60
58
|
EventPipeline_1.EventPipeline.insertEvent(event);
|
|
@@ -64,8 +62,7 @@ class DynatraceImpl {
|
|
|
64
62
|
const eventTimestamp = new EventTimestamp_1.EventTimestamp(this.timestampProvider);
|
|
65
63
|
const event = Object.assign(Object.assign({}, (0, EventCreator_1.createErrorEvent)(error.name, error.message, error.stack)), eventTimestamp.getEventTimeInfo());
|
|
66
64
|
if (isApiReported) {
|
|
67
|
-
event
|
|
68
|
-
true;
|
|
65
|
+
(0, EventModifierUtil_1.addIsApiReported)(event);
|
|
69
66
|
event["dt.support.is_legacy_api_reported"] = true;
|
|
70
67
|
}
|
|
71
68
|
EventPipeline_1.EventPipeline.insertEvent(event);
|
|
@@ -76,15 +73,14 @@ class DynatraceImpl {
|
|
|
76
73
|
const event = Object.assign({}, (0, EventCreator_1.createErrorEvent)(error.name, error.message, error.stack));
|
|
77
74
|
let eventValidated = SendEventValidation_1.SendEventValidation.modifyEvent(fieldsCheck);
|
|
78
75
|
eventValidated = Object.assign(Object.assign({}, event), eventValidated);
|
|
79
|
-
eventValidated
|
|
76
|
+
(0, EventModifierUtil_1.addIsApiReported)(eventValidated);
|
|
80
77
|
EventPipeline_1.EventPipeline.insertEvent(eventValidated);
|
|
81
78
|
}
|
|
82
79
|
sendEvent(properties, context) {
|
|
83
80
|
this.logger.debug(`sendEvent(${JSON.stringify(properties, context)})`);
|
|
84
81
|
const eventValidated = SendEventValidation_1.SendEventValidation.modifyEvent(properties);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
82
|
+
(0, EventModifierUtil_1.flagEventProperties)(eventValidated);
|
|
83
|
+
(0, EventModifierUtil_1.addIsApiReported)(eventValidated);
|
|
88
84
|
EventPipeline_1.EventPipeline.insertEvent(eventValidated, context);
|
|
89
85
|
}
|
|
90
86
|
sendSessionPropertyEvent(properties) {
|
|
@@ -94,7 +90,14 @@ class DynatraceImpl {
|
|
|
94
90
|
(0, EventModifierUtil_1.containSessionProperties)(eventValidated)) {
|
|
95
91
|
eventValidated["characteristics.has_session_properties"] = true;
|
|
96
92
|
}
|
|
93
|
+
(0, EventModifierUtil_1.addIsApiReported)(eventValidated);
|
|
97
94
|
EventPipeline_1.EventPipeline.insertEvent(eventValidated);
|
|
98
95
|
}
|
|
96
|
+
sendHttpRequestEvent(httpRequestEventBuilder) {
|
|
97
|
+
const sanitizedEvent = httpRequestEventBuilder.build();
|
|
98
|
+
this.logger.debug(`sendHttpRequestEvent(${JSON.stringify(sanitizedEvent)})`);
|
|
99
|
+
(0, EventModifierUtil_1.flagEventProperties)(sanitizedEvent);
|
|
100
|
+
EventPipeline_1.EventPipeline.insertEvent(sanitizedEvent);
|
|
101
|
+
}
|
|
99
102
|
}
|
|
100
103
|
exports.Dynatrace = new DynatraceImpl(TimestampProvider_1.defaultTimestampProvider);
|
|
@@ -26,7 +26,8 @@ const createErrorCodeEvent = (errorName, errorCode) => {
|
|
|
26
26
|
'error.is_fatal': false,
|
|
27
27
|
};
|
|
28
28
|
if (errorName != null) {
|
|
29
|
-
event["name"] = errorName;
|
|
29
|
+
event["error.name"] = errorName;
|
|
30
|
+
event["error.has_custom_name"] = true;
|
|
30
31
|
}
|
|
31
32
|
if (errorCode != null) {
|
|
32
33
|
event["error.code"] = errorCode;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const ConsoleLogger_1 = require("../../core/logging/ConsoleLogger");
|
|
4
|
+
const SendEventValidation_1 = require("./modifier/SendEventValidation");
|
|
5
|
+
const TimestampProvider_1 = require("../provider/TimestampProvider");
|
|
6
|
+
const logger = new ConsoleLogger_1.ConsoleLogger('Dynatrace');
|
|
7
|
+
class HttpRequestEventBuilder {
|
|
8
|
+
constructor(url, requestMethod) {
|
|
9
|
+
this.url = url;
|
|
10
|
+
this.requestMethod = requestMethod;
|
|
11
|
+
this.duration = 0;
|
|
12
|
+
this.rawEventProperties = {};
|
|
13
|
+
this.hasDroppedTraceparent = false;
|
|
14
|
+
this.hasDroppedCustomProperties = false;
|
|
15
|
+
this.hasNfnValues = false;
|
|
16
|
+
this.triedToOverwriteDuration = false;
|
|
17
|
+
this.requestMethod =
|
|
18
|
+
requestMethod.toUpperCase();
|
|
19
|
+
}
|
|
20
|
+
withDuration(duration) {
|
|
21
|
+
this.duration = duration;
|
|
22
|
+
this.triedToOverwriteDuration = true;
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
withStatusCode(statusCode) {
|
|
26
|
+
this.statusCode = statusCode;
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
withReasonPhrase(reasonPhrase) {
|
|
30
|
+
this.reasonPhrase = reasonPhrase;
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
withError(error) {
|
|
34
|
+
this.error = error;
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
withBytesSent(bytesSent) {
|
|
38
|
+
this.bytesSent = bytesSent;
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
withBytesReceived(bytesReceived) {
|
|
42
|
+
this.bytesReceived = bytesReceived;
|
|
43
|
+
return this;
|
|
44
|
+
}
|
|
45
|
+
withTraceparentHeader(traceparentHeader) {
|
|
46
|
+
this.traceparentHeader = traceparentHeader;
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
addEventProperty(key, value) {
|
|
50
|
+
this.rawEventProperties[key] = value;
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
build() {
|
|
54
|
+
if (!this.hasValidMandatoryAttriutes()) {
|
|
55
|
+
logger.debug('HttpRequestEventBuilder dropped invalid event');
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
this.sanitizeDuration();
|
|
59
|
+
this.sanitizeStatusCode();
|
|
60
|
+
this.sanitizeReasonPhrase();
|
|
61
|
+
this.sanitizeBytesReceived();
|
|
62
|
+
this.sanitizeBytesSent();
|
|
63
|
+
const parsedTraceparentHeader = this.traceparentHeader &&
|
|
64
|
+
this.parseTraceparent(this.traceparentHeader);
|
|
65
|
+
this.hasDroppedTraceparent =
|
|
66
|
+
!!this.traceparentHeader && !parsedTraceparentHeader;
|
|
67
|
+
const hasFailedRequest = this.isStatusCodeError() || !!this.error;
|
|
68
|
+
const filteredEventProperties = Object.fromEntries(Object.entries(this.rawEventProperties).filter(this.isEventPropertyKey, this));
|
|
69
|
+
const sanitizedEventProperties = SendEventValidation_1.SendEventValidation.modifyEvent(filteredEventProperties);
|
|
70
|
+
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, sanitizedEventProperties), { ["url.full"]: this.url, ["network.protocol.name"]: 'http', ["http.request.method"]: this.requestMethod, ["duration"]: this.duration, ["start_time"]: TimestampProvider_1.defaultTimestampProvider.getCurrentTimestamp() - this.duration }), (this.triedToOverwriteDuration && {
|
|
71
|
+
["dt.support.api.overridden_fields"]: [
|
|
72
|
+
'duration',
|
|
73
|
+
],
|
|
74
|
+
})), this.includeIfDefined("http.response.status_code", this.statusCode)), this.includeIfDefined("http.response.reason_phrase", this.reasonPhrase)), this.includeIfDefined("request.bytes_sent", this.bytesSent)), this.includeIfDefined("request.bytes_received", this.bytesReceived)), { ["characteristics.has_request"]: true, ["characteristics.is_api_reported"]: true }), this.includeIfTrue("characteristics.has_failed_request", hasFailedRequest)), this.includeIfTrue("characteristics.has_error", hasFailedRequest)), (this.error !== undefined && Object.assign({ ["characteristics.has_exception"]: true, ["exception.type"]: this.error.name, ["exception.message"]: this.error.message }, this.includeIfDefined("exception.stack_trace", this.error.stack)))), (parsedTraceparentHeader && {
|
|
75
|
+
["trace.id"]: parsedTraceparentHeader.traceId,
|
|
76
|
+
["span.id"]: parsedTraceparentHeader.spanId,
|
|
77
|
+
})), (this.hasDroppedTraceparent && {
|
|
78
|
+
["request.trace_context_hint"]: 'invalid_header',
|
|
79
|
+
})), this.includeIfTrue("dt.support.api.has_dropped_custom_properties", this.hasDroppedCustomProperties)), this.includeIfTrue("dt.support.has_nfn_values", this.hasNfnValues));
|
|
80
|
+
}
|
|
81
|
+
hasValidMandatoryAttriutes() {
|
|
82
|
+
let isValid = true;
|
|
83
|
+
if (this.isInvalidUrl(this.url)) {
|
|
84
|
+
logger.debug(`HttpRequestEventBuilder: dropped event since given URL is malformed: ${this.url}`);
|
|
85
|
+
isValid = false;
|
|
86
|
+
}
|
|
87
|
+
if (!HttpRequestEventBuilder.allowedRequestMethods.includes(this.requestMethod)) {
|
|
88
|
+
logger.debug(`HttpRequestEventBuilder: dropped event since given Request Method is invalid: ${this.requestMethod}`);
|
|
89
|
+
isValid = false;
|
|
90
|
+
}
|
|
91
|
+
return isValid;
|
|
92
|
+
}
|
|
93
|
+
isInvalidUrl(url) {
|
|
94
|
+
try {
|
|
95
|
+
if (!url.match(/^(https?):\/\/[^\s/$.?#-][^\s]*$/i)) {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
new URL(url);
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
catch (_a) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
sanitizeStatusCode() {
|
|
106
|
+
if (this.statusCode == undefined && this.error === undefined) {
|
|
107
|
+
this.statusCode = 0;
|
|
108
|
+
}
|
|
109
|
+
if (this.statusCode && this.statusCode < 0) {
|
|
110
|
+
logger.debug('HttpRequestEventBuilder: overriding invalid Status Code with 0');
|
|
111
|
+
this.statusCode = 0;
|
|
112
|
+
this.hasDroppedCustomProperties = true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
sanitizeReasonPhrase() {
|
|
116
|
+
if (this.reasonPhrase &&
|
|
117
|
+
this.reasonPhrase.length >
|
|
118
|
+
HttpRequestEventBuilder.maxReasonPhraseLength) {
|
|
119
|
+
logger.debug(`HttpRequestEventBuilder: trimming too long Reason Phrase to a length of ${HttpRequestEventBuilder.maxReasonPhraseLength}`);
|
|
120
|
+
this.reasonPhrase = this.reasonPhrase.slice(0, HttpRequestEventBuilder.maxReasonPhraseLength);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
sanitizeDuration() {
|
|
124
|
+
this.hasNfnValues || (this.hasNfnValues = !Number.isFinite(this.duration));
|
|
125
|
+
if (!Number.isFinite(this.duration) || this.duration < 0) {
|
|
126
|
+
logger.debug('HttpRequestEventBuilder: overriding invalid Duration with 0');
|
|
127
|
+
this.duration = 0;
|
|
128
|
+
this.hasDroppedCustomProperties = true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
sanitizeBytesSent() {
|
|
132
|
+
if (this.bytesSent && this.bytesSent < 0) {
|
|
133
|
+
logger.debug(`HttpRequestEventBuilder: dropping invalid value for Bytes Sent: ${this.bytesSent}`);
|
|
134
|
+
this.bytesSent = undefined;
|
|
135
|
+
this.hasDroppedCustomProperties = true;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
sanitizeBytesReceived() {
|
|
139
|
+
if (this.bytesReceived && this.bytesReceived < 0) {
|
|
140
|
+
logger.debug(`HttpRequestEventBuilder: dropping invalid value for Bytes Received: ${this.bytesReceived}`);
|
|
141
|
+
this.bytesReceived = undefined;
|
|
142
|
+
this.hasDroppedCustomProperties = true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
isStatusCodeError() {
|
|
146
|
+
return (this.statusCode && 400 <= this.statusCode && this.statusCode <= 599);
|
|
147
|
+
}
|
|
148
|
+
isEventPropertyKey([key, _]) {
|
|
149
|
+
if (key.startsWith("event_properties")) {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
logger.debug(`HttpRequestEventBuilder: dropped event property '$key' as it did not start with prefix ${"event_properties"}`);
|
|
153
|
+
this.hasDroppedCustomProperties = true;
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
includeIfDefined(key, value) {
|
|
157
|
+
return value !== undefined ? { [key]: value } : {};
|
|
158
|
+
}
|
|
159
|
+
includeIfTrue(key, value) {
|
|
160
|
+
return value === true ? { [key]: value } : {};
|
|
161
|
+
}
|
|
162
|
+
parseTraceparent(header) {
|
|
163
|
+
const traceparentRegex = /^00-([0-9a-f]{32})-([0-9a-f]{16})-0[01]$/;
|
|
164
|
+
const match = header.match(traceparentRegex);
|
|
165
|
+
if (!match) {
|
|
166
|
+
logger.debug("The provided traceparent header does not match the format: '00-<trace-id-32-HEXDIG>-<parent-id-16-HEXDIG>-<trace-flags-2-HEXDIG>'");
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const [, traceId, spanId] = match;
|
|
170
|
+
if (this.allZeros(traceId)) {
|
|
171
|
+
logger.debug('Trace ID in traceparent header must not be all zeros');
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
if (this.allZeros(spanId)) {
|
|
175
|
+
logger.debug('Parent ID in traceparent header must not be all zeros');
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
return { traceId, spanId };
|
|
179
|
+
}
|
|
180
|
+
allZeros(str) {
|
|
181
|
+
return /^0*$/.test(str);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
exports.default = HttpRequestEventBuilder;
|
|
185
|
+
HttpRequestEventBuilder.allowedRequestMethods = [
|
|
186
|
+
'GET',
|
|
187
|
+
'HEAD',
|
|
188
|
+
'POST',
|
|
189
|
+
'PUT',
|
|
190
|
+
'DELETE',
|
|
191
|
+
'CONNECT',
|
|
192
|
+
'OPTIONS',
|
|
193
|
+
'TRACE',
|
|
194
|
+
'PATCH',
|
|
195
|
+
];
|
|
196
|
+
HttpRequestEventBuilder.maxReasonPhraseLength = 5000;
|
|
@@ -8,7 +8,7 @@ const ASCII_CODE_A = 65;
|
|
|
8
8
|
const NUMERICAL_CHARACTER_COUNT = 10;
|
|
9
9
|
const OFFSET_A = ASCII_CODE_A - NUMERICAL_CHARACTER_COUNT;
|
|
10
10
|
const createViewInfo = (name) => ({
|
|
11
|
-
["view.
|
|
11
|
+
["view.instance_id"]: createRandomHexString(VIEW_ID_LENGTH),
|
|
12
12
|
["view.name"]: name,
|
|
13
13
|
});
|
|
14
14
|
exports.createViewInfo = createViewInfo;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.containEventPropertiesInArray = exports.containEventProperties = exports.containSessionProperties = exports.trimStringValuesInObject = exports.trimString = exports.isObject = exports.flattenAdditionalData = void 0;
|
|
3
|
+
exports.containEventPropertiesInArray = exports.addIsApiReported = exports.flagEventProperties = exports.containEventProperties = exports.containSessionProperties = exports.trimStringValuesInObject = exports.trimString = exports.isObject = exports.flattenAdditionalData = void 0;
|
|
4
4
|
const MAX_STRING_LENGTH_FOR_VALUES = 5000;
|
|
5
5
|
const flattenAdditionalData = (obj, parent, res = {}) => {
|
|
6
6
|
for (const key in obj) {
|
|
@@ -60,6 +60,19 @@ const containEventProperties = (jsonData) => {
|
|
|
60
60
|
return false;
|
|
61
61
|
};
|
|
62
62
|
exports.containEventProperties = containEventProperties;
|
|
63
|
+
const flagEventProperties = (event) => {
|
|
64
|
+
if (event !== null && (0, exports.containEventProperties)(event)) {
|
|
65
|
+
event["characteristics.has_event_properties"] =
|
|
66
|
+
true;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
exports.flagEventProperties = flagEventProperties;
|
|
70
|
+
const addIsApiReported = (event) => {
|
|
71
|
+
if (event !== null) {
|
|
72
|
+
event["characteristics.is_api_reported"] = true;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
exports.addIsApiReported = addIsApiReported;
|
|
63
76
|
const containEventPropertiesInArray = (eventEntries) => {
|
|
64
77
|
for (const [key, value] of eventEntries) {
|
|
65
78
|
if (key.startsWith(`${"event_properties"}.`)) {
|
|
@@ -23,18 +23,17 @@ class SendEventValidationImpl {
|
|
|
23
23
|
}
|
|
24
24
|
const timeNow = this.timestampProvider.getCurrentTimestamp();
|
|
25
25
|
const eventCopy = Object.entries(event).slice();
|
|
26
|
-
const filteredEvent = eventCopy
|
|
27
|
-
.filter(this.isKeyNameAllowed, this)
|
|
28
|
-
.filter(this.isFieldTypeAllowed, this);
|
|
26
|
+
const filteredEvent = eventCopy.filter(this.isKeyNameAllowed, this);
|
|
29
27
|
const limitedEntries = new EventLimitation_1.EventLimitation().limitEventEntries(filteredEvent);
|
|
30
28
|
const sizedEntries = new EventLimitation_1.EventLimitation().limitEventProperties(limitedEntries);
|
|
31
|
-
this.applyOverriddenKeys(sizedEntries);
|
|
32
29
|
if (sizedEntries.length < eventCopy.length) {
|
|
33
30
|
sizedEntries.push([
|
|
34
31
|
"dt.support.api.has_dropped_custom_properties",
|
|
35
32
|
true,
|
|
36
33
|
]);
|
|
37
34
|
}
|
|
35
|
+
this.sanitizeDuration(sizedEntries);
|
|
36
|
+
this.applyOverriddenKeys(sizedEntries);
|
|
38
37
|
const jsonObject = Object.fromEntries(sizedEntries);
|
|
39
38
|
if (jsonObject["duration"] !== undefined) {
|
|
40
39
|
jsonObject["start_time"] =
|
|
@@ -60,13 +59,27 @@ class SendEventValidationImpl {
|
|
|
60
59
|
]);
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
key === "
|
|
67
|
-
|
|
62
|
+
sanitizeDuration(event) {
|
|
63
|
+
for (const entry of event) {
|
|
64
|
+
const [key, value] = entry;
|
|
65
|
+
if (key === "duration") {
|
|
66
|
+
if (typeof value !== 'number' ||
|
|
67
|
+
!isFinite(value) ||
|
|
68
|
+
value < 0) {
|
|
69
|
+
entry[1] = 0;
|
|
70
|
+
event.push([
|
|
71
|
+
"dt.support.api.has_dropped_custom_properties",
|
|
72
|
+
true,
|
|
73
|
+
]);
|
|
74
|
+
}
|
|
75
|
+
if (typeof value === 'number' && !isFinite(value)) {
|
|
76
|
+
event.push([
|
|
77
|
+
"dt.support.has_nfn_values",
|
|
78
|
+
true,
|
|
79
|
+
]);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
68
82
|
}
|
|
69
|
-
return true;
|
|
70
83
|
}
|
|
71
84
|
isKeyNameAllowed(entry) {
|
|
72
85
|
const [key] = entry;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
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.
|
|
4
|
+
const SPECIFICATION_VERSION = '0.22';
|
|
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;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynatrace/react-native-plugin",
|
|
3
|
-
"version": "2.323.
|
|
3
|
+
"version": "2.323.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": "typings/react-native-dynatrace.d.ts",
|
|
@@ -167,6 +167,6 @@
|
|
|
167
167
|
}
|
|
168
168
|
},
|
|
169
169
|
"engines": {
|
|
170
|
-
"node": ">=
|
|
170
|
+
"node": ">=16"
|
|
171
171
|
}
|
|
172
|
-
}
|
|
172
|
+
}
|
|
@@ -529,7 +529,7 @@ export declare const Dynatrace: {
|
|
|
529
529
|
*
|
|
530
530
|
* @see https://www.npmjs.com/package/@dynatrace/react-native-plugin#manually-report-a-crash
|
|
531
531
|
*/
|
|
532
|
-
reportCrashWithException(crashName: string, crash: Error, platform?: Platform);
|
|
532
|
+
reportCrashWithException(crashName: string, crash: Error, platform?: Platform): void;
|
|
533
533
|
|
|
534
534
|
/**
|
|
535
535
|
* Puts a set of http headers on every agent http request (eg. the Authorization header). It also triggers the agent to
|
|
@@ -640,6 +640,35 @@ export declare const Dynatrace: {
|
|
|
640
640
|
* @param properties any attributes that should be reported for every event in the session.
|
|
641
641
|
*/
|
|
642
642
|
sendSessionPropertyEvent(properties: JSONObject): void;
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
*
|
|
646
|
+
* Send an HttpRequestEvent by passing in an instance of HttpRequestEventBuilder.
|
|
647
|
+
* The Builder allows you to configure common properties of an HttpRequest like url, requestMethod and duration.
|
|
648
|
+
* Additionally, it allows you to set custom event properties.
|
|
649
|
+
*
|
|
650
|
+
* @param httpRequestEventBuilder Mandatory Builder which allows you to configure common properties of an HttpRequest
|
|
651
|
+
*
|
|
652
|
+
* Usage:
|
|
653
|
+
*
|
|
654
|
+
* ```ts
|
|
655
|
+
* import { Dynatrace, HttpRequestEventBuilder } from '@dynatrace/react-native-plugin';
|
|
656
|
+
*
|
|
657
|
+
* Dynatrace.sendHttpRequestEvent(
|
|
658
|
+
* new HttpRequestEventBuilder("http://www.dynatrace.com", "POST")
|
|
659
|
+
* .withDuration(100)
|
|
660
|
+
* .withStatusCode(404)
|
|
661
|
+
* .withReasonPhrase("HTTP/1.1 404 Not Found")
|
|
662
|
+
* .withError(new Error())
|
|
663
|
+
* .withBytesSent(100)
|
|
664
|
+
* .withBytesReceived(100)
|
|
665
|
+
* .withTraceparentHeader("traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01")
|
|
666
|
+
* .addEventProperty("event_properties.userid", 12345)
|
|
667
|
+
* .addEventProperty("event_properties.response", "example body")
|
|
668
|
+
* );
|
|
669
|
+
* ```
|
|
670
|
+
*/
|
|
671
|
+
sendHttpRequestEvent(httpRequestEventBuilder: HttpRequestEventBuilder): void
|
|
643
672
|
}
|
|
644
673
|
|
|
645
674
|
/**
|
|
@@ -1722,6 +1751,97 @@ export declare class ConfigurationBuilder {
|
|
|
1722
1751
|
public buildConfiguration(): IConfiguration;
|
|
1723
1752
|
}
|
|
1724
1753
|
|
|
1754
|
+
type EventProperty = string | number | boolean;
|
|
1755
|
+
type TraceparentHeader = `00-${string}-${string}-0${'0' | '1'}`;
|
|
1756
|
+
type AllowedRequestMethods =
|
|
1757
|
+
| 'GET'
|
|
1758
|
+
| 'HEAD'
|
|
1759
|
+
| 'POST'
|
|
1760
|
+
| 'PUT'
|
|
1761
|
+
| 'DELETE'
|
|
1762
|
+
| 'CONNECT'
|
|
1763
|
+
| 'OPTIONS'
|
|
1764
|
+
| 'TRACE'
|
|
1765
|
+
| 'PATCH'
|
|
1766
|
+
| 'get'
|
|
1767
|
+
| 'head'
|
|
1768
|
+
| 'post'
|
|
1769
|
+
| 'put'
|
|
1770
|
+
| 'delete'
|
|
1771
|
+
| 'connect'
|
|
1772
|
+
| 'options'
|
|
1773
|
+
| 'trace'
|
|
1774
|
+
| 'patch';
|
|
1775
|
+
|
|
1776
|
+
export declare class HttpRequestEventBuilder {
|
|
1777
|
+
/**
|
|
1778
|
+
*
|
|
1779
|
+
* @param url Accepts only URLs that are valid according to the WHATWG URL Standard. Mandatory.
|
|
1780
|
+
* @param requestMethod Accepts GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE and PATCH. Mandatory
|
|
1781
|
+
*/
|
|
1782
|
+
constructor(
|
|
1783
|
+
url: `http://${string}` | `https://${string}`,
|
|
1784
|
+
requestMethod: AllowedRequestMethods
|
|
1785
|
+
);
|
|
1786
|
+
|
|
1787
|
+
/**
|
|
1788
|
+
*
|
|
1789
|
+
* @param duration Only positive numbers are valid.
|
|
1790
|
+
* @returns the HttpRequestEventBuilder
|
|
1791
|
+
*/
|
|
1792
|
+
withDuration(duration: number): this;
|
|
1793
|
+
|
|
1794
|
+
/**
|
|
1795
|
+
*
|
|
1796
|
+
* @param statusCode Only positive numbers are valid.
|
|
1797
|
+
* @returns the HttpRequestEventBuilder
|
|
1798
|
+
*/
|
|
1799
|
+
withStatusCode(statusCode: number): this;
|
|
1800
|
+
|
|
1801
|
+
/**
|
|
1802
|
+
*
|
|
1803
|
+
* @param reasonPhrase Max. 5000 characters.
|
|
1804
|
+
* @returns the HttpRequestEventBuilder
|
|
1805
|
+
*/
|
|
1806
|
+
withReasonPhrase(reasonPhrase: string): this;
|
|
1807
|
+
|
|
1808
|
+
/**
|
|
1809
|
+
*
|
|
1810
|
+
* @param error A standard Javascript Error Object.
|
|
1811
|
+
* @returns the HttpRequestEventBuilder
|
|
1812
|
+
*/
|
|
1813
|
+
withError(error: Error): this;
|
|
1814
|
+
|
|
1815
|
+
/**
|
|
1816
|
+
*
|
|
1817
|
+
* @param bytesSent Only positive numbers are valid.
|
|
1818
|
+
* @returns the HttpRequestEventBuilder
|
|
1819
|
+
*/
|
|
1820
|
+
withBytesSent(bytesSent: number): this;
|
|
1821
|
+
|
|
1822
|
+
/**
|
|
1823
|
+
*
|
|
1824
|
+
* @param bytesReceived Only positive numbers are valid.
|
|
1825
|
+
* @returns the HttpRequestEventBuilder
|
|
1826
|
+
*/
|
|
1827
|
+
withBytesReceived(bytesReceived: number): this;
|
|
1828
|
+
|
|
1829
|
+
/**
|
|
1830
|
+
*
|
|
1831
|
+
* @param traceparentHeader Accepts Traceparent Headers that are valid according to the W3C Trace Context Specification.
|
|
1832
|
+
* @returns the HttpRequestEventBuilder
|
|
1833
|
+
*/
|
|
1834
|
+
withTraceparentHeader(traceparentHeader: TraceparentHeader): this;
|
|
1835
|
+
|
|
1836
|
+
/**
|
|
1837
|
+
*
|
|
1838
|
+
* @param key Accepts any string that starts with 'event_properties.'.
|
|
1839
|
+
* @param value Accepts any string (max. 5000 characters), number or boolean.
|
|
1840
|
+
* @returns the HttpRequestEventBuilder
|
|
1841
|
+
*/
|
|
1842
|
+
addEventProperty(key: `event_properties.${string}`, value: EventProperty): this;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1725
1845
|
declare module 'react' {
|
|
1726
1846
|
namespace JSX {
|
|
1727
1847
|
interface IntrinsicAttributes extends IDynatraceProperties {}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SwitchHelper = void 0;
|
|
4
|
-
const ComponentUtil_1 = require("./ComponentUtil");
|
|
5
|
-
const ConfigurationHandler_1 = require("../../../lib/core/configuration/ConfigurationHandler");
|
|
6
|
-
const SwitchHelper = (Dynatrace) => ({
|
|
7
|
-
attachOnValueChange: (switchProps) => {
|
|
8
|
-
if ((0, ComponentUtil_1.isDynatraceIgnored)(switchProps)) {
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
const origOnValueChange = switchProps.onValueChange;
|
|
12
|
-
const nameOfAction = _findActionName(switchProps);
|
|
13
|
-
if (origOnValueChange != null) {
|
|
14
|
-
switchProps.onValueChange = (value) => {
|
|
15
|
-
const useGenericName = nameOfAction == null ||
|
|
16
|
-
(!(0, ComponentUtil_1.isDynatraceNaming)(switchProps) &&
|
|
17
|
-
ConfigurationHandler_1.ConfigurationHandler.isActionNamePrivacyEnabled());
|
|
18
|
-
const finalNameOfAction = useGenericName
|
|
19
|
-
? `Touch on Switch to ${value}`
|
|
20
|
-
: `Touch on ${nameOfAction} to ${value}`;
|
|
21
|
-
const action = Dynatrace.enterAutoAction(finalNameOfAction);
|
|
22
|
-
let isSyncError = true;
|
|
23
|
-
try {
|
|
24
|
-
const returnValue = origOnValueChange(value);
|
|
25
|
-
if (_isPromise(returnValue)) {
|
|
26
|
-
isSyncError = false;
|
|
27
|
-
return returnValue.finally(() => {
|
|
28
|
-
action.leaveAction();
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
action.leaveAction();
|
|
33
|
-
}
|
|
34
|
-
isSyncError = false;
|
|
35
|
-
}
|
|
36
|
-
finally {
|
|
37
|
-
if (isSyncError) {
|
|
38
|
-
action.leaveAction();
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
exports.SwitchHelper = SwitchHelper;
|
|
46
|
-
const _findActionName = (switchProps) => {
|
|
47
|
-
if ((0, ComponentUtil_1.isDynatraceNaming)(switchProps)) {
|
|
48
|
-
return switchProps.dtActionName;
|
|
49
|
-
}
|
|
50
|
-
else if (switchProps.accessibilityLabel != null) {
|
|
51
|
-
return switchProps.accessibilityLabel;
|
|
52
|
-
}
|
|
53
|
-
return null;
|
|
54
|
-
};
|
|
55
|
-
const _isPromise = (object) => object != null &&
|
|
56
|
-
typeof object.then === 'function' &&
|
|
57
|
-
typeof object.catch === 'function';
|