@ansight/react-native 1.3.0-preview.2 → 1.3.0-preview.5
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 +15 -3
- package/android/build.gradle +2 -2
- package/android/src/main/kotlin/ai/ansight/reactnative/AnsightReactNativeModule.kt +60 -8
- package/index.d.ts +32 -2
- package/index.js +128 -27
- package/ios/AnsightReactNative.swift +55 -6
- package/ios/AnsightReactNativeModule.m +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,8 +77,8 @@ bundle; its API requires the native Ansight module.
|
|
|
77
77
|
|
|
78
78
|
This package version expects matching native SDK packages:
|
|
79
79
|
|
|
80
|
-
- CocoaPods: `Ansight`, `AnsightObjC` version `1.3.0-preview.
|
|
81
|
-
- Maven: `ai.ansight:ansight-android:1.3.0-preview.
|
|
80
|
+
- CocoaPods: `Ansight`, `AnsightObjC` version `1.3.0-preview.5`
|
|
81
|
+
- Maven: `ai.ansight:ansight-android:1.3.0-preview.5`
|
|
82
82
|
|
|
83
83
|
## Quickstart
|
|
84
84
|
|
|
@@ -136,10 +136,12 @@ The TypeScript `AnsightOptions` surface mirrors Android `AnsightOptions`, iOS
|
|
|
136
136
|
| `retentionPeriodSeconds` | Local metric/event retention window. |
|
|
137
137
|
| `enableFramesPerSecond` | Enables native FPS sampling. |
|
|
138
138
|
| `enableBatteryLevel` | Enables battery sampling where available. |
|
|
139
|
+
| `enableOpenFileHandleTracking` | Enables native process open-file-handle sampling. Disabled by default. |
|
|
140
|
+
| `enableJniReferenceCountTracking` | Enables JNI reference-count tracking where the runtime can supply it. Disabled by default. |
|
|
139
141
|
| `defaultMemoryChannels` | Selects built-in memory channels. Prefer `managedHeap`, `nativeHeap`, `residentSetSize`, and `physicalFootprint`; `javaHeap` and `rss` are accepted as Android/RN compatibility aliases. |
|
|
140
142
|
| `reactNativeMemory` | Controls native React Native runtime memory channels. Enabled by default; set to `false` to disable, or use `{ jsHeapUsed, jsHeapTotal }`. |
|
|
141
143
|
| `additionalChannels` | Registers custom metric channels. |
|
|
142
|
-
| `sessionJpegCapture` | Object to enable/configure capture, or `false` to disable. Supports `captureGpuBackedSurfaces`; on iOS it defaults to `true` so Metal, SceneKit, and similar GPU-backed views are included. |
|
|
144
|
+
| `sessionJpegCapture` | Object to enable/configure capture, or `false` to disable. `mode` accepts `screenshotOnly`, `screenshotAndVisualTree`, or `screenshotWithVisualTreeOnTouch`. Supports `captureGpuBackedSurfaces`; on iOS it defaults to `true` so Metal, SceneKit, and similar GPU-backed views are included. |
|
|
143
145
|
| `touchCapture` | Object to enable/configure capture, or `false` to disable. |
|
|
144
146
|
| `lifecycleCapture` | Native lifecycle and screen-view capture options. |
|
|
145
147
|
| `toolGuard` | `"disabled"`, `"readOnly"`, `"readWrite"`, or `"fullAccess"`. |
|
|
@@ -150,6 +152,11 @@ The TypeScript `AnsightOptions` surface mirrors Android `AnsightOptions`, iOS
|
|
|
150
152
|
| `remoteTools` | Native visual tree, file, database, preferences, reflection, and secure-storage tool options. |
|
|
151
153
|
| `lifecycle` | JS AppState tracking toggle. Defaults to true. |
|
|
152
154
|
|
|
155
|
+
Use `withOpenFileHandleTracking()` and `withJniReferenceCountTracking()` to
|
|
156
|
+
opt in through the builder. Matching `without...` methods disable the channels
|
|
157
|
+
again. Open handles are sampled by the native Android/iOS runtime. JNI counts
|
|
158
|
+
are available on Android only when the host integration can supply them.
|
|
159
|
+
|
|
153
160
|
Cellular host connections are disabled by default. The restriction applies to
|
|
154
161
|
enrollment and reconnect requests. Opt in only for a trusted development host
|
|
155
162
|
or personal hotspot:
|
|
@@ -175,6 +182,7 @@ await Ansight.initializeAndActivate({
|
|
|
175
182
|
quality: 60,
|
|
176
183
|
maxWidth: 480,
|
|
177
184
|
captureGpuBackedSurfaces: true,
|
|
185
|
+
mode: "screenshotWithVisualTreeOnTouch",
|
|
178
186
|
},
|
|
179
187
|
touchCapture: {
|
|
180
188
|
captureMoveEvents: true,
|
|
@@ -192,6 +200,10 @@ await Ansight.initializeAndActivate({
|
|
|
192
200
|
});
|
|
193
201
|
```
|
|
194
202
|
|
|
203
|
+
The touch mode captures native visual trees at gesture start, every 250 ms
|
|
204
|
+
throughout the gesture, and at the final up or cancel. It requires native touch
|
|
205
|
+
capture and visual-tree tools/providers to remain enabled.
|
|
206
|
+
|
|
195
207
|
On iOS, `captureGpuBackedSurfaces` defaults to `true` so Metal, SceneKit, and
|
|
196
208
|
similar GPU-backed views are included. Set it to `false` to use a lower-overhead
|
|
197
209
|
capture path when those surfaces are not needed.
|
package/android/build.gradle
CHANGED
|
@@ -67,6 +67,6 @@ repositories {
|
|
|
67
67
|
dependencies {
|
|
68
68
|
implementation("com.facebook.react:react-android")
|
|
69
69
|
def ansightAndroidVersion =
|
|
70
|
-
findProperty("ansightAndroidVersion") ?: "1.3.0-preview.
|
|
71
|
-
implementation("ai.ansight:ansight-android:1.3.0-preview.
|
|
70
|
+
findProperty("ansightAndroidVersion") ?: "1.3.0-preview.5"
|
|
71
|
+
implementation("ai.ansight:ansight-android:1.3.0-preview.5")
|
|
72
72
|
}
|
|
@@ -6,6 +6,7 @@ import ai.ansight.runtime.AndroidToolExecutionContext
|
|
|
6
6
|
import ai.ansight.runtime.AndroidToolResult
|
|
7
7
|
import ai.ansight.runtime.AnsightChannel
|
|
8
8
|
import ai.ansight.runtime.AnsightChannels
|
|
9
|
+
import ai.ansight.runtime.AnsightCrashCaptureOptions
|
|
9
10
|
import ai.ansight.runtime.AnsightHostAutoProbeOptions
|
|
10
11
|
import ai.ansight.runtime.AnsightHostConnectionOptions
|
|
11
12
|
import ai.ansight.runtime.AnsightLogCallback
|
|
@@ -225,6 +226,21 @@ class AnsightReactNativeModule(
|
|
|
225
226
|
}.resolve(promise)
|
|
226
227
|
}
|
|
227
228
|
|
|
229
|
+
@ReactMethod
|
|
230
|
+
fun recordCrashCandidate(input: ReadableMap, promise: Promise) {
|
|
231
|
+
runCatching {
|
|
232
|
+
val candidateId = AnsightRuntime.recordCrashCandidate(
|
|
233
|
+
runtime = input.stringValue("runtime") ?: "react-native-javascript",
|
|
234
|
+
kind = input.stringValue("kind") ?: "unhandled_javascript_error",
|
|
235
|
+
message = input.stringValue("message"),
|
|
236
|
+
stack = input.stringValue("stack"),
|
|
237
|
+
fatal = input.booleanValue("fatal", false),
|
|
238
|
+
metadataJson = input.stringValue("metadata"),
|
|
239
|
+
)
|
|
240
|
+
Arguments.createMap().apply { putString("candidateId", candidateId) }
|
|
241
|
+
}.resolve(promise)
|
|
242
|
+
}
|
|
243
|
+
|
|
228
244
|
@ReactMethod
|
|
229
245
|
fun screenViewed(name: String, details: ReadableMap?, promise: Promise) {
|
|
230
246
|
runCatching {
|
|
@@ -693,6 +709,22 @@ class AnsightReactNativeModule(
|
|
|
693
709
|
if (map.hasBoolean("enableBatteryLevel")) {
|
|
694
710
|
options = options.copy(enableBatteryLevel = map.booleanValue("enableBatteryLevel", options.enableBatteryLevel))
|
|
695
711
|
}
|
|
712
|
+
if (map.hasBoolean("enableOpenFileHandleTracking")) {
|
|
713
|
+
options = options.copy(
|
|
714
|
+
enableOpenFileHandleTracking = map.booleanValue(
|
|
715
|
+
"enableOpenFileHandleTracking",
|
|
716
|
+
options.enableOpenFileHandleTracking,
|
|
717
|
+
),
|
|
718
|
+
)
|
|
719
|
+
}
|
|
720
|
+
if (map.hasBoolean("enableJniReferenceCountTracking")) {
|
|
721
|
+
options = options.copy(
|
|
722
|
+
enableJniReferenceCountTracking = map.booleanValue(
|
|
723
|
+
"enableJniReferenceCountTracking",
|
|
724
|
+
options.enableJniReferenceCountTracking,
|
|
725
|
+
),
|
|
726
|
+
)
|
|
727
|
+
}
|
|
696
728
|
if (map.hasMap("defaultMemoryChannels")) {
|
|
697
729
|
val memory = map.getMapOrNull("defaultMemoryChannels")
|
|
698
730
|
val managedHeap = if (memory.hasBoolean("managedHeap")) {
|
|
@@ -768,6 +800,24 @@ class AnsightReactNativeModule(
|
|
|
768
800
|
},
|
|
769
801
|
)
|
|
770
802
|
}
|
|
803
|
+
if (map.hasKey("crashCapture")) {
|
|
804
|
+
options = options.copy(
|
|
805
|
+
crashCapture = if (map.isFalse("crashCapture")) {
|
|
806
|
+
options.crashCapture.copy(enabled = false)
|
|
807
|
+
} else {
|
|
808
|
+
val crash = map.getMapOrNull("crashCapture")
|
|
809
|
+
AnsightCrashCaptureOptions(
|
|
810
|
+
enabled = crash.booleanValue("enabled", true),
|
|
811
|
+
studioHandoffEnabled = crash.booleanValue("studioHandoffEnabled", true),
|
|
812
|
+
offlineCaptureAttachmentEnabled = crash.booleanValue("offlineCaptureAttachmentEnabled", true),
|
|
813
|
+
maximumPendingReports = crash.intValue("maximumPendingReports", 8),
|
|
814
|
+
retentionDays = crash.intValue("retentionDays", 7),
|
|
815
|
+
maximumBreadcrumbs = crash.intValue("maximumBreadcrumbs", 64),
|
|
816
|
+
maximumTraceBytes = crash.intValue("maximumTraceBytes", 1_048_576),
|
|
817
|
+
)
|
|
818
|
+
},
|
|
819
|
+
)
|
|
820
|
+
}
|
|
771
821
|
if (map.hasString("toolGuard")) {
|
|
772
822
|
options = options.copy(toolGuard = toolGuard(map.stringValue("toolGuard")))
|
|
773
823
|
}
|
|
@@ -935,10 +985,10 @@ class AnsightReactNativeModule(
|
|
|
935
985
|
}
|
|
936
986
|
|
|
937
987
|
private fun sessionJpegCaptureMode(value: String?): AnsightSessionJpegCaptureMode =
|
|
938
|
-
|
|
939
|
-
AnsightSessionJpegCaptureMode.ScreenshotAndVisualTree
|
|
940
|
-
|
|
941
|
-
AnsightSessionJpegCaptureMode.ScreenshotOnly
|
|
988
|
+
when (value) {
|
|
989
|
+
"screenshotAndVisualTree" -> AnsightSessionJpegCaptureMode.ScreenshotAndVisualTree
|
|
990
|
+
"screenshotWithVisualTreeOnTouch" -> AnsightSessionJpegCaptureMode.ScreenshotWithVisualTreeOnTouch
|
|
991
|
+
else -> AnsightSessionJpegCaptureMode.ScreenshotOnly
|
|
942
992
|
}
|
|
943
993
|
|
|
944
994
|
private fun toolDefinition(map: ReadableMap): ToolDefinition =
|
|
@@ -1111,6 +1161,8 @@ class AnsightReactNativeModule(
|
|
|
1111
1161
|
putInt("retentionPeriodSeconds", options.retentionPeriodSeconds)
|
|
1112
1162
|
putBoolean("enableFramesPerSecond", options.enableFramesPerSecond)
|
|
1113
1163
|
putBoolean("enableBatteryLevel", options.enableBatteryLevel)
|
|
1164
|
+
putBoolean("enableOpenFileHandleTracking", options.enableOpenFileHandleTracking)
|
|
1165
|
+
putBoolean("enableJniReferenceCountTracking", options.enableJniReferenceCountTracking)
|
|
1114
1166
|
putMap("defaultMemoryChannels", mapOf(
|
|
1115
1167
|
"managedHeap" to options.defaultMemoryChannels.javaHeap,
|
|
1116
1168
|
"javaHeap" to options.defaultMemoryChannels.javaHeap,
|
|
@@ -1127,10 +1179,10 @@ class AnsightReactNativeModule(
|
|
|
1127
1179
|
"quality" to capture.quality,
|
|
1128
1180
|
"maxWidth" to capture.maxWidth,
|
|
1129
1181
|
"captureGpuBackedSurfaces" to capture.captureGpuBackedSurfaces,
|
|
1130
|
-
"mode" to
|
|
1131
|
-
"screenshotAndVisualTree"
|
|
1132
|
-
|
|
1133
|
-
"screenshotOnly"
|
|
1182
|
+
"mode" to when (capture.mode) {
|
|
1183
|
+
AnsightSessionJpegCaptureMode.ScreenshotAndVisualTree -> "screenshotAndVisualTree"
|
|
1184
|
+
AnsightSessionJpegCaptureMode.ScreenshotWithVisualTreeOnTouch -> "screenshotWithVisualTreeOnTouch"
|
|
1185
|
+
else -> "screenshotOnly"
|
|
1134
1186
|
},
|
|
1135
1187
|
).toWritableMap())
|
|
1136
1188
|
} ?: putNull("sessionJpegCapture")
|
package/index.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export interface AnsightSessionJpegCaptureOptions {
|
|
|
37
37
|
quality?: number;
|
|
38
38
|
maxWidth?: number;
|
|
39
39
|
captureGpuBackedSurfaces?: boolean;
|
|
40
|
-
mode?: "screenshotOnly" | "screenshotAndVisualTree";
|
|
40
|
+
mode?: "screenshotOnly" | "screenshotAndVisualTree" | "screenshotWithVisualTreeOnTouch";
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export interface AnsightTouchCaptureOptions {
|
|
@@ -110,6 +110,8 @@ export interface AnsightOptions {
|
|
|
110
110
|
retentionPeriodSeconds?: number;
|
|
111
111
|
enableFramesPerSecond?: boolean;
|
|
112
112
|
enableBatteryLevel?: boolean;
|
|
113
|
+
enableOpenFileHandleTracking?: boolean;
|
|
114
|
+
enableJniReferenceCountTracking?: boolean;
|
|
113
115
|
defaultMemoryChannels?: {
|
|
114
116
|
managedHeap?: boolean;
|
|
115
117
|
physicalFootprint?: boolean;
|
|
@@ -121,6 +123,7 @@ export interface AnsightOptions {
|
|
|
121
123
|
reactNativeMemory?: false | AnsightReactNativeMemoryOptions;
|
|
122
124
|
sessionJpegCapture?: false | AnsightSessionJpegCaptureOptions;
|
|
123
125
|
touchCapture?: false | AnsightTouchCaptureOptions;
|
|
126
|
+
crashCapture?: false | AnsightCrashCaptureOptions;
|
|
124
127
|
lifecycleCapture?: {
|
|
125
128
|
enabled?: boolean;
|
|
126
129
|
captureAppLifecycle?: boolean;
|
|
@@ -153,6 +156,25 @@ export interface AnsightOptions {
|
|
|
153
156
|
lifecycle?: boolean;
|
|
154
157
|
}
|
|
155
158
|
|
|
159
|
+
export interface AnsightCrashCaptureOptions {
|
|
160
|
+
enabled?: boolean;
|
|
161
|
+
studioHandoffEnabled?: boolean;
|
|
162
|
+
offlineCaptureAttachmentEnabled?: boolean;
|
|
163
|
+
maximumPendingReports?: number;
|
|
164
|
+
retentionDays?: number;
|
|
165
|
+
maximumBreadcrumbs?: number;
|
|
166
|
+
maximumTraceBytes?: number;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export interface AnsightCrashCandidate {
|
|
170
|
+
runtime?: string;
|
|
171
|
+
kind?: string;
|
|
172
|
+
message?: string;
|
|
173
|
+
stack?: string;
|
|
174
|
+
fatal?: boolean;
|
|
175
|
+
metadata?: string | Record<string, string>;
|
|
176
|
+
}
|
|
177
|
+
|
|
156
178
|
export interface AnsightOperationResult {
|
|
157
179
|
success: boolean;
|
|
158
180
|
message: string;
|
|
@@ -251,6 +273,10 @@ export class AnsightOptionsBuilder {
|
|
|
251
273
|
withoutFramesPerSecond(): this;
|
|
252
274
|
withBatteryLevel(): this;
|
|
253
275
|
withoutBatteryLevel(): this;
|
|
276
|
+
withOpenFileHandleTracking(): this;
|
|
277
|
+
withoutOpenFileHandleTracking(): this;
|
|
278
|
+
withJniReferenceCountTracking(): this;
|
|
279
|
+
withoutJniReferenceCountTracking(): this;
|
|
254
280
|
withRetentionPeriodSeconds(retentionPeriodSeconds: number): this;
|
|
255
281
|
withAdditionalChannels(additionalChannels: AnsightChannel[]): this;
|
|
256
282
|
addAdditionalChannel(additionalChannel: AnsightChannel): this;
|
|
@@ -264,11 +290,13 @@ export class AnsightOptionsBuilder {
|
|
|
264
290
|
quality?: number,
|
|
265
291
|
maxWidth?: number | null,
|
|
266
292
|
captureGpuBackedSurfaces?: boolean,
|
|
267
|
-
mode?: "screenshotOnly" | "screenshotAndVisualTree"
|
|
293
|
+
mode?: "screenshotOnly" | "screenshotAndVisualTree" | "screenshotWithVisualTreeOnTouch"
|
|
268
294
|
): this;
|
|
269
295
|
withoutSessionJpegCapture(): this;
|
|
270
296
|
withTouchCapture(touchCapture?: AnsightTouchCaptureOptions): this;
|
|
271
297
|
withoutTouchCapture(): this;
|
|
298
|
+
withCrashCapture(crashCapture?: AnsightCrashCaptureOptions): this;
|
|
299
|
+
withoutCrashCapture(): this;
|
|
272
300
|
withLifecycleCapture(lifecycleCapture?: NonNullable<AnsightOptions["lifecycleCapture"]>): this;
|
|
273
301
|
withToolGuard(toolGuard: NonNullable<AnsightOptions["toolGuard"]>): this;
|
|
274
302
|
withToolsDisabled(): this;
|
|
@@ -512,6 +540,7 @@ export function metric(value: number, channel?: number): Promise<AnsightDebugSna
|
|
|
512
540
|
export function recordMetric(value: number, channel?: number): Promise<AnsightDebugSnapshot>;
|
|
513
541
|
export function event(input: string | { label: string; type?: string; details?: string; channel?: number }): Promise<AnsightDebugSnapshot>;
|
|
514
542
|
export function recordEvent(input: string | { label: string; type?: string; details?: string; channel?: number }): Promise<AnsightDebugSnapshot>;
|
|
543
|
+
export function recordCrashCandidate(input?: AnsightCrashCandidate): Promise<{ candidateId?: string }>;
|
|
515
544
|
export function screenViewed(name: string, details?: Record<string, string>): Promise<AnsightDebugSnapshot>;
|
|
516
545
|
export function trackRoute(name: string, details?: Record<string, string>): Promise<AnsightDebugSnapshot>;
|
|
517
546
|
export function setAppLifecycleState(state: AnsightLifecycleState): Promise<AnsightDebugSnapshot>;
|
|
@@ -585,6 +614,7 @@ declare const Ansight: {
|
|
|
585
614
|
recordMetric: typeof recordMetric;
|
|
586
615
|
event: typeof event;
|
|
587
616
|
recordEvent: typeof recordEvent;
|
|
617
|
+
recordCrashCandidate: typeof recordCrashCandidate;
|
|
588
618
|
screenViewed: typeof screenViewed;
|
|
589
619
|
trackRoute: typeof trackRoute;
|
|
590
620
|
setAppLifecycleState: typeof setAppLifecycleState;
|
package/index.js
CHANGED
|
@@ -61,6 +61,9 @@ function cloneOptions(options = {}) {
|
|
|
61
61
|
if (options.touchCapture && typeof options.touchCapture === "object") {
|
|
62
62
|
clone.touchCapture = { ...options.touchCapture };
|
|
63
63
|
}
|
|
64
|
+
if (options.crashCapture && typeof options.crashCapture === "object") {
|
|
65
|
+
clone.crashCapture = { ...options.crashCapture };
|
|
66
|
+
}
|
|
64
67
|
if (options.lifecycleCapture) {
|
|
65
68
|
clone.lifecycleCapture = { ...options.lifecycleCapture };
|
|
66
69
|
}
|
|
@@ -157,6 +160,8 @@ class AnsightOptionsBuilder {
|
|
|
157
160
|
retentionPeriodSeconds: 120,
|
|
158
161
|
enableFramesPerSecond: true,
|
|
159
162
|
enableBatteryLevel: false,
|
|
163
|
+
enableOpenFileHandleTracking: false,
|
|
164
|
+
enableJniReferenceCountTracking: false,
|
|
160
165
|
sessionJpegCapture: {
|
|
161
166
|
intervalMilliseconds: 2000,
|
|
162
167
|
quality: 60,
|
|
@@ -209,6 +214,26 @@ class AnsightOptionsBuilder {
|
|
|
209
214
|
return this;
|
|
210
215
|
}
|
|
211
216
|
|
|
217
|
+
withOpenFileHandleTracking() {
|
|
218
|
+
this._options.enableOpenFileHandleTracking = true;
|
|
219
|
+
return this;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
withoutOpenFileHandleTracking() {
|
|
223
|
+
this._options.enableOpenFileHandleTracking = false;
|
|
224
|
+
return this;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
withJniReferenceCountTracking() {
|
|
228
|
+
this._options.enableJniReferenceCountTracking = true;
|
|
229
|
+
return this;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
withoutJniReferenceCountTracking() {
|
|
233
|
+
this._options.enableJniReferenceCountTracking = false;
|
|
234
|
+
return this;
|
|
235
|
+
}
|
|
236
|
+
|
|
212
237
|
withRetentionPeriodSeconds(retentionPeriodSeconds) {
|
|
213
238
|
this._options.retentionPeriodSeconds = retentionPeriodSeconds;
|
|
214
239
|
return this;
|
|
@@ -297,6 +322,16 @@ class AnsightOptionsBuilder {
|
|
|
297
322
|
return this;
|
|
298
323
|
}
|
|
299
324
|
|
|
325
|
+
withCrashCapture(crashCapture = {}) {
|
|
326
|
+
this._options.crashCapture = { ...crashCapture, enabled: true };
|
|
327
|
+
return this;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
withoutCrashCapture() {
|
|
331
|
+
this._options.crashCapture = false;
|
|
332
|
+
return this;
|
|
333
|
+
}
|
|
334
|
+
|
|
300
335
|
withLifecycleCapture(lifecycleCapture = {}) {
|
|
301
336
|
this._options.lifecycleCapture = { ...lifecycleCapture };
|
|
302
337
|
return this;
|
|
@@ -1489,6 +1524,28 @@ function createReactVisual(fiber, props, maxStringLength) {
|
|
|
1489
1524
|
return visual;
|
|
1490
1525
|
}
|
|
1491
1526
|
|
|
1527
|
+
function createReactZIndex(props) {
|
|
1528
|
+
const style = StyleSheet && typeof StyleSheet.flatten === "function"
|
|
1529
|
+
? StyleSheet.flatten(props && props.style)
|
|
1530
|
+
: props && props.style;
|
|
1531
|
+
const zIndex = style && style.zIndex != null ? Number(style.zIndex) : NaN;
|
|
1532
|
+
const elevation = style && style.elevation != null ? Number(style.elevation) : NaN;
|
|
1533
|
+
if (Number.isFinite(zIndex) && zIndex !== 0) return zIndex;
|
|
1534
|
+
if (Number.isFinite(elevation) && elevation !== 0) return elevation;
|
|
1535
|
+
return null;
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
function registerReactType(context, typeName) {
|
|
1539
|
+
const normalizedTypeName = String(typeName || "UnknownComponent").trim() || "UnknownComponent";
|
|
1540
|
+
const existingTypeId = context.typeIdsByName.get(normalizedTypeName);
|
|
1541
|
+
if (existingTypeId != null) return existingTypeId;
|
|
1542
|
+
|
|
1543
|
+
const typeId = context.types.length;
|
|
1544
|
+
context.types.push(normalizedTypeName);
|
|
1545
|
+
context.typeIdsByName.set(normalizedTypeName, typeId);
|
|
1546
|
+
return typeId;
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1492
1549
|
function nativeTagForFiber(fiber) {
|
|
1493
1550
|
const stateNode = fiber && fiber.stateNode;
|
|
1494
1551
|
if (!stateNode) {
|
|
@@ -1560,17 +1617,17 @@ function serializeFiber(fiber, context, depth) {
|
|
|
1560
1617
|
|
|
1561
1618
|
const props = fiber.memoizedProps || fiber.pendingProps || {};
|
|
1562
1619
|
const type = reactFiberTypeName(fiber);
|
|
1563
|
-
const kind = reactFiberKind(fiber.tag);
|
|
1564
1620
|
const node = {
|
|
1565
1621
|
id: reactFiberId(fiber),
|
|
1566
|
-
type,
|
|
1567
|
-
kind,
|
|
1622
|
+
typeId: registerReactType(context, type),
|
|
1568
1623
|
tag: fiber.tag,
|
|
1569
1624
|
key: fiber.key == null ? null : String(fiber.key),
|
|
1570
1625
|
depth,
|
|
1571
1626
|
visual: createReactVisual(fiber, props, context.maxStringLength),
|
|
1572
1627
|
children: [],
|
|
1573
1628
|
};
|
|
1629
|
+
const zIndex = createReactZIndex(props);
|
|
1630
|
+
if (zIndex != null) node.z = zIndex;
|
|
1574
1631
|
|
|
1575
1632
|
if (fiber._debugSource) {
|
|
1576
1633
|
node.source = {
|
|
@@ -1582,7 +1639,7 @@ function serializeFiber(fiber, context, depth) {
|
|
|
1582
1639
|
|
|
1583
1640
|
const owner = fiber._debugOwner && reactFiberTypeName(fiber._debugOwner);
|
|
1584
1641
|
if (owner) {
|
|
1585
|
-
node.
|
|
1642
|
+
node.ownerTypeId = registerReactType(context, owner);
|
|
1586
1643
|
}
|
|
1587
1644
|
|
|
1588
1645
|
const nativeTag = nativeTagForFiber(fiber);
|
|
@@ -1641,14 +1698,15 @@ function createShadowTreeNode(fiber, context, depth) {
|
|
|
1641
1698
|
const type = reactFiberTypeName(fiber);
|
|
1642
1699
|
const node = {
|
|
1643
1700
|
id: reactFiberId(fiber),
|
|
1644
|
-
type,
|
|
1645
|
-
kind: fiber.tag === 3 ? "root" : fiber.tag === 6 ? "text" : "host",
|
|
1701
|
+
typeId: registerReactType(context, type),
|
|
1646
1702
|
tag: fiber.tag,
|
|
1647
1703
|
key: fiber.key == null ? null : String(fiber.key),
|
|
1648
1704
|
depth,
|
|
1649
1705
|
visual: createReactVisual(fiber, props, context.maxStringLength),
|
|
1650
1706
|
children: [],
|
|
1651
1707
|
};
|
|
1708
|
+
const zIndex = createReactZIndex(props);
|
|
1709
|
+
if (zIndex != null) node.z = zIndex;
|
|
1652
1710
|
|
|
1653
1711
|
const nativeTag = nativeTagForFiber(fiber);
|
|
1654
1712
|
if (nativeTag != null) {
|
|
@@ -1732,19 +1790,21 @@ async function captureReactVisualTree(rawOptions = {}) {
|
|
|
1732
1790
|
maxStringLength: rawOptions.maxStringLength || 180,
|
|
1733
1791
|
maxValueDepth: rawOptions.maxValueDepth || 2,
|
|
1734
1792
|
nodesWithNativeTags: [],
|
|
1793
|
+
typeIdsByName: new Map(),
|
|
1794
|
+
types: [],
|
|
1735
1795
|
count: 0,
|
|
1736
1796
|
truncated: false,
|
|
1737
1797
|
visited: new Set(),
|
|
1738
1798
|
};
|
|
1739
1799
|
const roots = getReactRoots();
|
|
1740
|
-
const rootNodes = roots.roots.map((root
|
|
1800
|
+
const rootNodes = roots.roots.map((root) => {
|
|
1741
1801
|
const node = serializeFiber(root.fiber, context, 0);
|
|
1742
1802
|
if (node) {
|
|
1743
1803
|
node.rendererId = root.rendererId;
|
|
1744
|
-
node.rootIndex = index;
|
|
1745
1804
|
}
|
|
1746
1805
|
return node;
|
|
1747
1806
|
}).filter(Boolean);
|
|
1807
|
+
const rootTypeId = registerReactType(context, "ReactRoots");
|
|
1748
1808
|
|
|
1749
1809
|
if (includeBounds && context.nodesWithNativeTags.length > 0) {
|
|
1750
1810
|
await Promise.all(context.nodesWithNativeTags.slice(0, 300).map(async (node) => {
|
|
@@ -1756,6 +1816,7 @@ async function captureReactVisualTree(rawOptions = {}) {
|
|
|
1756
1816
|
}
|
|
1757
1817
|
|
|
1758
1818
|
return {
|
|
1819
|
+
format: "ansight.react.visual-tree.compact.v2",
|
|
1759
1820
|
platform: Platform.OS,
|
|
1760
1821
|
source: "react",
|
|
1761
1822
|
adapter: "react.fiber",
|
|
@@ -1765,11 +1826,11 @@ async function captureReactVisualTree(rawOptions = {}) {
|
|
|
1765
1826
|
renderers: roots.renderers,
|
|
1766
1827
|
root: {
|
|
1767
1828
|
id: "react:roots",
|
|
1768
|
-
|
|
1769
|
-
|
|
1829
|
+
typeId: rootTypeId,
|
|
1830
|
+
childCount: rootNodes.length,
|
|
1770
1831
|
children: rootNodes,
|
|
1771
1832
|
},
|
|
1772
|
-
|
|
1833
|
+
types: context.types,
|
|
1773
1834
|
nodeCount: context.count,
|
|
1774
1835
|
truncated: context.truncated,
|
|
1775
1836
|
unavailableReason: roots.hookAvailable ? undefined : "React DevTools global hook is not available in this runtime.",
|
|
@@ -1789,19 +1850,21 @@ async function captureReactShadowTree(rawOptions = {}) {
|
|
|
1789
1850
|
maxStringLength: rawOptions.maxStringLength || 180,
|
|
1790
1851
|
maxValueDepth: rawOptions.maxValueDepth || 2,
|
|
1791
1852
|
nodesWithNativeTags: [],
|
|
1853
|
+
typeIdsByName: new Map(),
|
|
1854
|
+
types: [],
|
|
1792
1855
|
count: 0,
|
|
1793
1856
|
truncated: false,
|
|
1794
1857
|
visited: new Set(),
|
|
1795
1858
|
};
|
|
1796
1859
|
const roots = getReactRoots();
|
|
1797
|
-
const rootNodes = roots.roots.flatMap((root
|
|
1860
|
+
const rootNodes = roots.roots.flatMap((root) => {
|
|
1798
1861
|
const nodes = serializeShadowFiber(root.fiber, context, 0);
|
|
1799
1862
|
nodes.forEach((node) => {
|
|
1800
1863
|
node.rendererId = root.rendererId;
|
|
1801
|
-
node.rootIndex = index;
|
|
1802
1864
|
});
|
|
1803
1865
|
return nodes;
|
|
1804
1866
|
});
|
|
1867
|
+
const rootTypeId = registerReactType(context, "ReactNativeShadowRoots");
|
|
1805
1868
|
|
|
1806
1869
|
if (includeBounds && context.nodesWithNativeTags.length > 0) {
|
|
1807
1870
|
await Promise.all(context.nodesWithNativeTags.slice(0, 300).map(async (node) => {
|
|
@@ -1813,6 +1876,7 @@ async function captureReactShadowTree(rawOptions = {}) {
|
|
|
1813
1876
|
}
|
|
1814
1877
|
|
|
1815
1878
|
return {
|
|
1879
|
+
format: "ansight.react.visual-tree.compact.v2",
|
|
1816
1880
|
platform: Platform.OS,
|
|
1817
1881
|
source: "react-native",
|
|
1818
1882
|
adapter: "react-native.host-fiber",
|
|
@@ -1822,11 +1886,11 @@ async function captureReactShadowTree(rawOptions = {}) {
|
|
|
1822
1886
|
renderers: roots.renderers,
|
|
1823
1887
|
root: {
|
|
1824
1888
|
id: "react:shadow-roots",
|
|
1825
|
-
|
|
1826
|
-
|
|
1889
|
+
typeId: rootTypeId,
|
|
1890
|
+
childCount: rootNodes.length,
|
|
1827
1891
|
children: rootNodes,
|
|
1828
1892
|
},
|
|
1829
|
-
|
|
1893
|
+
types: context.types,
|
|
1830
1894
|
nodeCount: context.count,
|
|
1831
1895
|
truncated: context.truncated,
|
|
1832
1896
|
unavailableReason: roots.hookAvailable ? undefined : "React DevTools global hook is not available in this runtime.",
|
|
@@ -1842,13 +1906,18 @@ function flattenReactTree(node, output = []) {
|
|
|
1842
1906
|
return output;
|
|
1843
1907
|
}
|
|
1844
1908
|
|
|
1845
|
-
function
|
|
1909
|
+
function createReactNodeSnapshot(node) {
|
|
1910
|
+
const snapshot = { ...node };
|
|
1911
|
+
delete snapshot.children;
|
|
1912
|
+
return snapshot;
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
function nodeSearchText(node, types) {
|
|
1846
1916
|
return [
|
|
1847
1917
|
node.id,
|
|
1848
|
-
node.
|
|
1849
|
-
node.kind,
|
|
1918
|
+
types[node.typeId],
|
|
1850
1919
|
node.label,
|
|
1851
|
-
node.
|
|
1920
|
+
types[node.ownerTypeId],
|
|
1852
1921
|
node.propsSummary && node.propsSummary.testID,
|
|
1853
1922
|
node.propsSummary && node.propsSummary.nativeID,
|
|
1854
1923
|
node.propsSummary && node.propsSummary.accessibilityLabel,
|
|
@@ -1856,14 +1925,14 @@ function nodeSearchText(node) {
|
|
|
1856
1925
|
].filter(Boolean).join(" ").toLowerCase();
|
|
1857
1926
|
}
|
|
1858
1927
|
|
|
1859
|
-
function matchesReactNode(node, args) {
|
|
1928
|
+
function matchesReactNode(node, args, types) {
|
|
1860
1929
|
const query = args.query ? String(args.query).toLowerCase() : null;
|
|
1861
1930
|
const type = args.type ? String(args.type).toLowerCase() : null;
|
|
1862
1931
|
const testID = args.testID ? String(args.testID).toLowerCase() : null;
|
|
1863
1932
|
const text = args.text ? String(args.text).toLowerCase() : null;
|
|
1864
|
-
const searchText = nodeSearchText(node);
|
|
1933
|
+
const searchText = nodeSearchText(node, types);
|
|
1865
1934
|
return (!query || searchText.includes(query)) &&
|
|
1866
|
-
(!type || String(node.
|
|
1935
|
+
(!type || String(types[node.typeId] || "").toLowerCase().includes(type)) &&
|
|
1867
1936
|
(!testID || String((node.propsSummary && node.propsSummary.testID) || "").toLowerCase() === testID) &&
|
|
1868
1937
|
(!text || searchText.includes(text));
|
|
1869
1938
|
}
|
|
@@ -2084,12 +2153,14 @@ function installReactTools(options = {}) {
|
|
|
2084
2153
|
});
|
|
2085
2154
|
const maxResults = parseInteger(args.maxResults, 50, 1, 500);
|
|
2086
2155
|
const matches = flattenReactTree(tree.root)
|
|
2087
|
-
.filter((node) => node.id !== "react:roots" && matchesReactNode(node, args))
|
|
2088
|
-
.slice(0, maxResults)
|
|
2156
|
+
.filter((node) => node.id !== "react:roots" && matchesReactNode(node, args, tree.types))
|
|
2157
|
+
.slice(0, maxResults)
|
|
2158
|
+
.map(createReactNodeSnapshot);
|
|
2089
2159
|
return {
|
|
2090
2160
|
success: tree.hookAvailable,
|
|
2091
2161
|
message: `Found ${matches.length} React component(s).`,
|
|
2092
2162
|
result: {
|
|
2163
|
+
types: tree.types,
|
|
2093
2164
|
matches,
|
|
2094
2165
|
count: matches.length,
|
|
2095
2166
|
truncated: matches.length === maxResults,
|
|
@@ -2101,7 +2172,11 @@ function installReactTools(options = {}) {
|
|
|
2101
2172
|
const tree = await captureReactVisualTree(reactToolOptions(options, args));
|
|
2102
2173
|
const node = flattenReactTree(tree.root).find((candidate) => candidate.id === args.nodeId);
|
|
2103
2174
|
return node
|
|
2104
|
-
? {
|
|
2175
|
+
? {
|
|
2176
|
+
success: true,
|
|
2177
|
+
message: "React component captured.",
|
|
2178
|
+
result: { types: tree.types, node: createReactNodeSnapshot(node) },
|
|
2179
|
+
}
|
|
2105
2180
|
: { success: false, message: `React component '${args.nodeId}' was not found.`, errorCode: "react_component_not_found" };
|
|
2106
2181
|
}
|
|
2107
2182
|
|
|
@@ -2142,7 +2217,7 @@ function installReactTools(options = {}) {
|
|
|
2142
2217
|
result: {
|
|
2143
2218
|
nodeId: args.nodeId,
|
|
2144
2219
|
prop,
|
|
2145
|
-
type: node.
|
|
2220
|
+
type: tree.types[node.typeId],
|
|
2146
2221
|
},
|
|
2147
2222
|
};
|
|
2148
2223
|
}
|
|
@@ -2178,6 +2253,14 @@ function installErrorHandlers(options = {}) {
|
|
|
2178
2253
|
|
|
2179
2254
|
if (global.ErrorUtils && global.ErrorUtils.setGlobalHandler) {
|
|
2180
2255
|
global.ErrorUtils.setGlobalHandler((error, isFatal) => {
|
|
2256
|
+
nativeModule.recordCrashCandidate({
|
|
2257
|
+
runtime: "react-native-javascript",
|
|
2258
|
+
kind: "unhandled_javascript_error",
|
|
2259
|
+
message: error && error.message,
|
|
2260
|
+
stack: error && error.stack,
|
|
2261
|
+
fatal: !!isFatal,
|
|
2262
|
+
metadata: JSON.stringify({ name: error && error.name }),
|
|
2263
|
+
}).catch(() => {});
|
|
2181
2264
|
nativeModule.recordEvent({
|
|
2182
2265
|
label: error && error.message ? error.message : "Unhandled JavaScript error",
|
|
2183
2266
|
type: "Exception",
|
|
@@ -2200,6 +2283,13 @@ function installErrorHandlers(options = {}) {
|
|
|
2200
2283
|
global.__ansightUnhandledRejectionTrackingInstalled = true;
|
|
2201
2284
|
global.addEventListener("unhandledrejection", (event) => {
|
|
2202
2285
|
const reason = event && event.reason;
|
|
2286
|
+
nativeModule.recordCrashCandidate({
|
|
2287
|
+
runtime: "react-native-javascript",
|
|
2288
|
+
kind: "unhandled_promise_rejection",
|
|
2289
|
+
message: reason && reason.message ? reason.message : String(reason),
|
|
2290
|
+
stack: reason && reason.stack,
|
|
2291
|
+
fatal: false,
|
|
2292
|
+
}).catch(() => {});
|
|
2203
2293
|
nativeModule.recordEvent({
|
|
2204
2294
|
label: reason && reason.message ? reason.message : "Unhandled JavaScript promise rejection",
|
|
2205
2295
|
type: "Exception",
|
|
@@ -2294,6 +2384,16 @@ function recordEvent(input) {
|
|
|
2294
2384
|
return nativeModule.recordEvent(input || {});
|
|
2295
2385
|
}
|
|
2296
2386
|
|
|
2387
|
+
function recordCrashCandidate(input = {}) {
|
|
2388
|
+
const metadata = input.metadata && typeof input.metadata === "object"
|
|
2389
|
+
? JSON.stringify(input.metadata)
|
|
2390
|
+
: input.metadata;
|
|
2391
|
+
return nativeModule.recordCrashCandidate({
|
|
2392
|
+
...input,
|
|
2393
|
+
metadata,
|
|
2394
|
+
});
|
|
2395
|
+
}
|
|
2396
|
+
|
|
2297
2397
|
function screenViewed(name, details) {
|
|
2298
2398
|
return nativeModule.screenViewed(name, details || {});
|
|
2299
2399
|
}
|
|
@@ -2336,6 +2436,7 @@ const Ansight = {
|
|
|
2336
2436
|
recordMetric: (value, channel = 255) => nativeModule.recordMetric(value, channel),
|
|
2337
2437
|
event: recordEvent,
|
|
2338
2438
|
recordEvent,
|
|
2439
|
+
recordCrashCandidate,
|
|
2339
2440
|
screenViewed,
|
|
2340
2441
|
trackRoute,
|
|
2341
2442
|
setAppLifecycleState: (state) => nativeModule.setAppLifecycleState(state),
|
|
@@ -292,6 +292,31 @@ final class AnsightReactNative: RCTEventEmitter {
|
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
+
@objc(recordCrashCandidate:resolver:rejecter:)
|
|
296
|
+
func recordCrashCandidate(
|
|
297
|
+
_ input: NSDictionary,
|
|
298
|
+
resolver resolve: RCTPromiseResolveBlock,
|
|
299
|
+
rejecter reject: RCTPromiseRejectBlock
|
|
300
|
+
) {
|
|
301
|
+
let metadata: [String: String]
|
|
302
|
+
if let metadataJson = stringValue(input, "metadata"),
|
|
303
|
+
let data = metadataJson.data(using: .utf8),
|
|
304
|
+
let decoded = try? JSONDecoder().decode([String: String].self, from: data) {
|
|
305
|
+
metadata = decoded
|
|
306
|
+
} else {
|
|
307
|
+
metadata = [:]
|
|
308
|
+
}
|
|
309
|
+
let candidateId = AnsightRuntime.shared.recordCrashCandidate(
|
|
310
|
+
runtime: stringValue(input, "runtime") ?? "react-native-javascript",
|
|
311
|
+
kind: stringValue(input, "kind") ?? "unhandled_javascript_error",
|
|
312
|
+
message: stringValue(input, "message"),
|
|
313
|
+
stack: stringValue(input, "stack"),
|
|
314
|
+
fatal: boolValue(input, "fatal", defaultValue: false),
|
|
315
|
+
metadata: metadata
|
|
316
|
+
)
|
|
317
|
+
resolve(candidateId.map { ["candidateId": $0] } ?? [:])
|
|
318
|
+
}
|
|
319
|
+
|
|
295
320
|
@objc(screenViewed:details:resolver:rejecter:)
|
|
296
321
|
func screenViewed(
|
|
297
322
|
_ name: NSString,
|
|
@@ -895,6 +920,13 @@ final class AnsightReactNative: RCTEventEmitter {
|
|
|
895
920
|
if hasBool(dictionary, "enableBatteryLevel") {
|
|
896
921
|
options.enableBatteryLevel = boolValue(dictionary, "enableBatteryLevel", defaultValue: options.enableBatteryLevel)
|
|
897
922
|
}
|
|
923
|
+
if hasBool(dictionary, "enableOpenFileHandleTracking") {
|
|
924
|
+
options.enableOpenFileHandleTracking = boolValue(
|
|
925
|
+
dictionary,
|
|
926
|
+
"enableOpenFileHandleTracking",
|
|
927
|
+
defaultValue: options.enableOpenFileHandleTracking
|
|
928
|
+
)
|
|
929
|
+
}
|
|
898
930
|
if let memory = dictionary?["defaultMemoryChannels"] as? NSDictionary {
|
|
899
931
|
var channels: DefaultMemoryChannels = []
|
|
900
932
|
if boolValue(memory, "managedHeap", defaultValue: boolValue(memory, "javaHeap", defaultValue: false)) {
|
|
@@ -942,9 +974,9 @@ final class AnsightReactNative: RCTEventEmitter {
|
|
|
942
974
|
"captureGpuBackedSurfaces",
|
|
943
975
|
defaultValue: AnsightSessionJpegCaptureOptions.defaultCaptureGpuBackedSurfaces
|
|
944
976
|
),
|
|
945
|
-
mode:
|
|
946
|
-
|
|
947
|
-
|
|
977
|
+
mode: AnsightSessionJpegCaptureMode(
|
|
978
|
+
rawValue: stringValue(jpeg, "mode") ?? ""
|
|
979
|
+
) ?? .screenshotOnly
|
|
948
980
|
)
|
|
949
981
|
}
|
|
950
982
|
}
|
|
@@ -960,6 +992,21 @@ final class AnsightReactNative: RCTEventEmitter {
|
|
|
960
992
|
)
|
|
961
993
|
}
|
|
962
994
|
}
|
|
995
|
+
if let raw = dictionary?["crashCapture"] {
|
|
996
|
+
if (raw as? Bool) == false {
|
|
997
|
+
options.crashCapture.enabled = false
|
|
998
|
+
} else if let crash = raw as? NSDictionary {
|
|
999
|
+
options.crashCapture = AnsightCrashCaptureOptions(
|
|
1000
|
+
enabled: boolValue(crash, "enabled", defaultValue: true),
|
|
1001
|
+
studioHandoffEnabled: boolValue(crash, "studioHandoffEnabled", defaultValue: true),
|
|
1002
|
+
offlineCaptureAttachmentEnabled: boolValue(crash, "offlineCaptureAttachmentEnabled", defaultValue: true),
|
|
1003
|
+
maximumPendingReports: intValue(crash, "maximumPendingReports", defaultValue: 8),
|
|
1004
|
+
retentionDays: intValue(crash, "retentionDays", defaultValue: 7),
|
|
1005
|
+
maximumBreadcrumbs: intValue(crash, "maximumBreadcrumbs", defaultValue: 64),
|
|
1006
|
+
maximumTraceBytes: intValue(crash, "maximumTraceBytes", defaultValue: 1_048_576)
|
|
1007
|
+
)
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
963
1010
|
if let lifecycle = dictionary?["lifecycleCapture"] as? NSDictionary {
|
|
964
1011
|
options.lifecycleCapture = AnsightLifecycleCaptureOptions(
|
|
965
1012
|
enabled: boolValue(lifecycle, "enabled", defaultValue: options.lifecycleCapture.enabled),
|
|
@@ -1271,9 +1318,9 @@ final class AnsightReactNative: RCTEventEmitter {
|
|
|
1271
1318
|
"captureGpuBackedSurfaces",
|
|
1272
1319
|
defaultValue: AnsightSessionJpegCaptureOptions.defaultCaptureGpuBackedSurfaces
|
|
1273
1320
|
),
|
|
1274
|
-
mode:
|
|
1275
|
-
|
|
1276
|
-
|
|
1321
|
+
mode: AnsightSessionJpegCaptureMode(
|
|
1322
|
+
rawValue: stringValue(dictionary, "mode") ?? ""
|
|
1323
|
+
) ?? .screenshotOnly
|
|
1277
1324
|
)
|
|
1278
1325
|
}
|
|
1279
1326
|
|
|
@@ -1283,6 +1330,8 @@ final class AnsightReactNative: RCTEventEmitter {
|
|
|
1283
1330
|
"retentionPeriodSeconds": options.retentionPeriodSeconds,
|
|
1284
1331
|
"enableFramesPerSecond": options.enableFramesPerSecond,
|
|
1285
1332
|
"enableBatteryLevel": options.enableBatteryLevel,
|
|
1333
|
+
"enableOpenFileHandleTracking": options.enableOpenFileHandleTracking,
|
|
1334
|
+
"enableJniReferenceCountTracking": false,
|
|
1286
1335
|
"defaultMemoryChannels": [
|
|
1287
1336
|
"managedHeap": options.defaultMemoryChannels.contains(.managedHeap),
|
|
1288
1337
|
"javaHeap": options.defaultMemoryChannels.contains(.managedHeap),
|
|
@@ -33,6 +33,10 @@ RCT_EXTERN_METHOD(recordEvent:(NSDictionary *)input
|
|
|
33
33
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
34
34
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
35
35
|
|
|
36
|
+
RCT_EXTERN_METHOD(recordCrashCandidate:(NSDictionary *)input
|
|
37
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
38
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
39
|
+
|
|
36
40
|
RCT_EXTERN_METHOD(screenViewed:(NSString *)name
|
|
37
41
|
details:(NSDictionary *)details
|
|
38
42
|
resolver:(RCTPromiseResolveBlock)resolve
|