@goliapkg/sentori-react-native 0.9.1 → 0.9.3
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/android/src/main/java/com/sentori/SentoriCrashHandler.kt +3 -0
- package/android/src/main/java/com/sentori/SentoriModule.kt +5 -0
- package/android/src/main/java/com/sentori/SentoriReplayCapture.kt +153 -0
- package/ios/SentoriModule.swift +5 -0
- package/ios/SentoriReplayCapture.swift +147 -0
- package/lib/capture.d.ts +3 -0
- package/lib/capture.d.ts.map +1 -1
- package/lib/capture.js +29 -0
- package/lib/capture.js.map +1 -1
- package/lib/control-channel.d.ts +6 -0
- package/lib/control-channel.d.ts.map +1 -0
- package/lib/control-channel.js +89 -0
- package/lib/control-channel.js.map +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/init.d.ts +16 -0
- package/lib/init.d.ts.map +1 -1
- package/lib/init.js +21 -0
- package/lib/init.js.map +1 -1
- package/lib/long-task-monitor.d.ts +11 -0
- package/lib/long-task-monitor.d.ts.map +1 -0
- package/lib/long-task-monitor.js +88 -0
- package/lib/long-task-monitor.js.map +1 -0
- package/lib/replay.d.ts +13 -0
- package/lib/replay.d.ts.map +1 -0
- package/lib/replay.js +111 -0
- package/lib/replay.js.map +1 -0
- package/lib/transport.d.ts.map +1 -1
- package/lib/transport.js +8 -0
- package/lib/transport.js.map +1 -1
- package/package.json +2 -2
- package/src/capture.ts +35 -0
- package/src/control-channel.ts +90 -0
- package/src/init.ts +31 -0
- package/src/long-task-monitor.ts +99 -0
- package/src/replay.ts +123 -0
- package/src/transport.ts +8 -0
|
@@ -47,6 +47,9 @@ object SentoriCrashHandler {
|
|
|
47
47
|
// foreground Activity so it knows which Window to PixelCopy.
|
|
48
48
|
(appCtx as? android.app.Application)?.let {
|
|
49
49
|
SentoriScreenshotCapture.register(it)
|
|
50
|
+
// v0.9.6 #2 — replay capture also tracks the activity for
|
|
51
|
+
// wireframe view-tree walks.
|
|
52
|
+
SentoriReplayCapture.register(it)
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
|
|
@@ -29,6 +29,11 @@ class SentoriModule : Module() {
|
|
|
29
29
|
SentoriNativeExceptionBridge.getRecent()
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
// v0.9.6 #2 — wireframe session replay capture.
|
|
33
|
+
Function("captureWireframe") { maskedIds: List<String> ->
|
|
34
|
+
SentoriReplayCapture.captureWireframe(maskedIds)
|
|
35
|
+
}
|
|
36
|
+
|
|
32
37
|
// v0.9.4 #1 — Mobile Vitals exposure.
|
|
33
38
|
Function("markJsBridgeReady") {
|
|
34
39
|
SentoriMobileVitals.markJsBridgeReady()
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
package com.sentori
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.graphics.Rect
|
|
5
|
+
import android.view.View
|
|
6
|
+
import android.view.ViewGroup
|
|
7
|
+
import android.widget.EditText
|
|
8
|
+
import android.widget.ImageView
|
|
9
|
+
import android.widget.TextView
|
|
10
|
+
import org.json.JSONArray
|
|
11
|
+
import org.json.JSONObject
|
|
12
|
+
import java.lang.ref.WeakReference
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* v0.9.6 #2 — wireframe session replay (Android side).
|
|
16
|
+
*
|
|
17
|
+
* Mirrors SentoriReplayCapture.swift. Walks View hierarchy from the
|
|
18
|
+
* current activity's decor view at 1 Hz. Each visible node becomes
|
|
19
|
+
* a JSON dict { kind, x, y, w, h, text?, color? }. Returns one JSON
|
|
20
|
+
* object string per snapshot.
|
|
21
|
+
*
|
|
22
|
+
* Mask: nodes whose `View.tag` (cast to String) matches `maskedIds`
|
|
23
|
+
* render as a single black "mask" rect. Descendants of a masked
|
|
24
|
+
* node are not emitted.
|
|
25
|
+
*/
|
|
26
|
+
object SentoriReplayCapture {
|
|
27
|
+
|
|
28
|
+
private const val MAX_NODES = 800
|
|
29
|
+
|
|
30
|
+
@Volatile private var lastActivity: WeakReference<Activity>? = null
|
|
31
|
+
|
|
32
|
+
@JvmStatic
|
|
33
|
+
fun setActivity(activity: Activity?) {
|
|
34
|
+
lastActivity = activity?.let { WeakReference(it) }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Attach an ActivityLifecycleCallbacks so future
|
|
38
|
+
* `captureWireframe()` calls know which Activity to walk. */
|
|
39
|
+
@JvmStatic
|
|
40
|
+
fun register(application: android.app.Application) {
|
|
41
|
+
application.registerActivityLifecycleCallbacks(object :
|
|
42
|
+
android.app.Application.ActivityLifecycleCallbacks {
|
|
43
|
+
override fun onActivityCreated(a: Activity, b: android.os.Bundle?) { setActivity(a) }
|
|
44
|
+
override fun onActivityStarted(a: Activity) { setActivity(a) }
|
|
45
|
+
override fun onActivityResumed(a: Activity) { setActivity(a) }
|
|
46
|
+
override fun onActivityPaused(a: Activity) {}
|
|
47
|
+
override fun onActivityStopped(a: Activity) {}
|
|
48
|
+
override fun onActivitySaveInstanceState(a: Activity, b: android.os.Bundle) {}
|
|
49
|
+
override fun onActivityDestroyed(a: Activity) {}
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@JvmStatic
|
|
54
|
+
fun captureWireframe(maskedIds: List<String>): String? {
|
|
55
|
+
val activity = lastActivity?.get() ?: return null
|
|
56
|
+
val root = activity.window?.decorView ?: return null
|
|
57
|
+
if (root.width <= 0 || root.height <= 0) return null
|
|
58
|
+
|
|
59
|
+
val maskedSet = maskedIds.toHashSet()
|
|
60
|
+
val nodes = JSONArray()
|
|
61
|
+
val rect = Rect()
|
|
62
|
+
val rootLoc = IntArray(2).also { root.getLocationInWindow(it) }
|
|
63
|
+
walk(root, false, maskedSet, rootLoc, rect, nodes)
|
|
64
|
+
|
|
65
|
+
val payload = JSONObject().apply {
|
|
66
|
+
put("ts", System.currentTimeMillis())
|
|
67
|
+
put("width", root.width)
|
|
68
|
+
put("height", root.height)
|
|
69
|
+
put("nodes", nodes)
|
|
70
|
+
}
|
|
71
|
+
return payload.toString()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private fun walk(
|
|
75
|
+
view: View,
|
|
76
|
+
parentMasked: Boolean,
|
|
77
|
+
maskedSet: Set<String>,
|
|
78
|
+
rootLoc: IntArray,
|
|
79
|
+
scratch: Rect,
|
|
80
|
+
nodes: JSONArray,
|
|
81
|
+
) {
|
|
82
|
+
if (nodes.length() >= MAX_NODES) return
|
|
83
|
+
if (view.visibility != View.VISIBLE || view.alpha < 0.01) return
|
|
84
|
+
|
|
85
|
+
val viewTag = view.tag as? String
|
|
86
|
+
val isThisMasked = viewTag != null && maskedSet.contains(viewTag)
|
|
87
|
+
val masked = parentMasked || isThisMasked
|
|
88
|
+
|
|
89
|
+
val loc = IntArray(2)
|
|
90
|
+
view.getLocationInWindow(loc)
|
|
91
|
+
val x = loc[0] - rootLoc[0]
|
|
92
|
+
val y = loc[1] - rootLoc[1]
|
|
93
|
+
val w = view.width
|
|
94
|
+
val h = view.height
|
|
95
|
+
if (w <= 0 || h <= 0) return
|
|
96
|
+
|
|
97
|
+
val node = JSONObject().apply {
|
|
98
|
+
put("x", x)
|
|
99
|
+
put("y", y)
|
|
100
|
+
put("w", w)
|
|
101
|
+
put("h", h)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
var kindEmitted = false
|
|
105
|
+
when {
|
|
106
|
+
masked -> {
|
|
107
|
+
node.put("kind", "mask")
|
|
108
|
+
kindEmitted = true
|
|
109
|
+
}
|
|
110
|
+
view is TextView && !view.text.isNullOrEmpty() -> {
|
|
111
|
+
node.put("kind", "text")
|
|
112
|
+
val text = view.text.toString().let { if (it.length > 200) it.substring(0, 200) else it }
|
|
113
|
+
node.put("text", text)
|
|
114
|
+
node.put("color", colorToHex(view.currentTextColor))
|
|
115
|
+
kindEmitted = true
|
|
116
|
+
}
|
|
117
|
+
view is EditText -> {
|
|
118
|
+
node.put("kind", "text")
|
|
119
|
+
val text = (view.text ?: "").toString().let { if (it.length > 200) it.substring(0, 200) else it }
|
|
120
|
+
node.put("text", text)
|
|
121
|
+
kindEmitted = true
|
|
122
|
+
}
|
|
123
|
+
view is ImageView -> {
|
|
124
|
+
node.put("kind", "image")
|
|
125
|
+
kindEmitted = true
|
|
126
|
+
}
|
|
127
|
+
view.background != null -> {
|
|
128
|
+
node.put("kind", "rect")
|
|
129
|
+
// Background drawables don't always expose color directly.
|
|
130
|
+
// Skip color for non-ColorDrawable; renderer falls back to neutral.
|
|
131
|
+
kindEmitted = true
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (kindEmitted) {
|
|
136
|
+
nodes.put(node)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (!masked && view is ViewGroup) {
|
|
140
|
+
for (i in 0 until view.childCount) {
|
|
141
|
+
walk(view.getChildAt(i), masked, maskedSet, rootLoc, scratch, nodes)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private fun colorToHex(c: Int): String {
|
|
147
|
+
val a = (c shr 24) and 0xff
|
|
148
|
+
val r = (c shr 16) and 0xff
|
|
149
|
+
val g = (c shr 8) and 0xff
|
|
150
|
+
val b = c and 0xff
|
|
151
|
+
return String.format("#%02X%02X%02X%02X", r, g, b, a)
|
|
152
|
+
}
|
|
153
|
+
}
|
package/ios/SentoriModule.swift
CHANGED
|
@@ -25,6 +25,11 @@ public class SentoriModule: Module {
|
|
|
25
25
|
return SentoriNativeExceptionBridge.getRecentException()
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
// v0.9.6 #2 — wireframe session replay capture.
|
|
29
|
+
Function("captureWireframe") { (maskedIds: [String]) -> String? in
|
|
30
|
+
return SentoriReplayCapture.captureWireframe(maskedIds: maskedIds)
|
|
31
|
+
}
|
|
32
|
+
|
|
28
33
|
// v0.9.4 #1 — Mobile Vitals exposure.
|
|
29
34
|
Function("markJsBridgeReady") {
|
|
30
35
|
SentoriMobileVitals.markJsBridgeReady()
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
/// v0.9.6 #2 — wireframe session replay (iOS side).
|
|
5
|
+
///
|
|
6
|
+
/// Walks the UIView hierarchy at 1 Hz and serializes each visible
|
|
7
|
+
/// node as a compact JSON dict:
|
|
8
|
+
/// { kind, x, y, w, h, text?, color? }
|
|
9
|
+
///
|
|
10
|
+
/// Mask: nodes whose `accessibilityIdentifier` matches the JS-side
|
|
11
|
+
/// mask registry (passed in as `maskedIds`) have their text replaced
|
|
12
|
+
/// with "***" and the masked flag set so descendants render as
|
|
13
|
+
/// black-filled rects in the dashboard player.
|
|
14
|
+
///
|
|
15
|
+
/// Output: one JSON object per snapshot, returned as a string. The
|
|
16
|
+
/// JS side appends each snapshot to a 60-slot ring buffer; on
|
|
17
|
+
/// `captureException` the ring is uploaded as a `replay` attachment
|
|
18
|
+
/// (NDJSON: one snapshot per line).
|
|
19
|
+
@objc public final class SentoriReplayCapture: NSObject {
|
|
20
|
+
|
|
21
|
+
@objc public static func captureWireframe(maskedIds: [String]) -> String? {
|
|
22
|
+
if Thread.isMainThread {
|
|
23
|
+
return captureSync(maskedIds: Set(maskedIds))
|
|
24
|
+
}
|
|
25
|
+
var result: String?
|
|
26
|
+
DispatchQueue.main.sync {
|
|
27
|
+
result = captureSync(maskedIds: Set(maskedIds))
|
|
28
|
+
}
|
|
29
|
+
return result
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private static func captureSync(maskedIds: Set<String>) -> String? {
|
|
33
|
+
guard let window = keyWindow() else { return nil }
|
|
34
|
+
var nodes: [[String: Any]] = []
|
|
35
|
+
walk(
|
|
36
|
+
view: window,
|
|
37
|
+
parentMasked: false,
|
|
38
|
+
maskedIds: maskedIds,
|
|
39
|
+
window: window,
|
|
40
|
+
nodes: &nodes
|
|
41
|
+
)
|
|
42
|
+
let payload: [String: Any] = [
|
|
43
|
+
"ts": Int(Date().timeIntervalSince1970 * 1000),
|
|
44
|
+
"width": Double(window.bounds.width),
|
|
45
|
+
"height": Double(window.bounds.height),
|
|
46
|
+
"nodes": nodes,
|
|
47
|
+
]
|
|
48
|
+
if let data = try? JSONSerialization.data(withJSONObject: payload, options: []) {
|
|
49
|
+
return String(data: data, encoding: .utf8)
|
|
50
|
+
}
|
|
51
|
+
return nil
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private static func keyWindow() -> UIWindow? {
|
|
55
|
+
if #available(iOS 13.0, *) {
|
|
56
|
+
for scene in UIApplication.shared.connectedScenes {
|
|
57
|
+
guard let ws = scene as? UIWindowScene else { continue }
|
|
58
|
+
if let key = ws.windows.first(where: { $0.isKeyWindow }) {
|
|
59
|
+
return key
|
|
60
|
+
}
|
|
61
|
+
if let first = ws.windows.first {
|
|
62
|
+
return first
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return UIApplication.shared.windows.first
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// Cap on nodes per snapshot — extremely deep / wide trees can
|
|
70
|
+
/// have thousands of subviews (UICollectionView recyclers).
|
|
71
|
+
private static let MAX_NODES = 800
|
|
72
|
+
|
|
73
|
+
private static func walk(
|
|
74
|
+
view: UIView,
|
|
75
|
+
parentMasked: Bool,
|
|
76
|
+
maskedIds: Set<String>,
|
|
77
|
+
window: UIWindow,
|
|
78
|
+
nodes: inout [[String: Any]]
|
|
79
|
+
) {
|
|
80
|
+
if nodes.count >= MAX_NODES { return }
|
|
81
|
+
if view.isHidden || view.alpha < 0.01 { return }
|
|
82
|
+
|
|
83
|
+
let isThisMasked = view.accessibilityIdentifier
|
|
84
|
+
.map { maskedIds.contains($0) } ?? false
|
|
85
|
+
let masked = parentMasked || isThisMasked
|
|
86
|
+
|
|
87
|
+
let frame = view.convert(view.bounds, to: window)
|
|
88
|
+
// Skip nodes outside the window bounds (off-screen recyclers).
|
|
89
|
+
if !frame.intersects(window.bounds) {
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
var node: [String: Any] = [
|
|
94
|
+
"x": Double(frame.origin.x),
|
|
95
|
+
"y": Double(frame.origin.y),
|
|
96
|
+
"w": Double(frame.size.width),
|
|
97
|
+
"h": Double(frame.size.height),
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
if masked {
|
|
101
|
+
node["kind"] = "mask"
|
|
102
|
+
} else if let label = view as? UILabel, let text = label.text, !text.isEmpty {
|
|
103
|
+
node["kind"] = "text"
|
|
104
|
+
node["text"] = text.count > 200 ? String(text.prefix(200)) : text
|
|
105
|
+
if let color = label.textColor.flatMap(colorToHex) {
|
|
106
|
+
node["color"] = color
|
|
107
|
+
}
|
|
108
|
+
} else if let textView = view as? UITextView, let text = textView.text, !text.isEmpty {
|
|
109
|
+
node["kind"] = "text"
|
|
110
|
+
node["text"] = text.count > 200 ? String(text.prefix(200)) : text
|
|
111
|
+
} else if view is UIImageView {
|
|
112
|
+
node["kind"] = "image"
|
|
113
|
+
} else if let bg = view.backgroundColor, let hex = colorToHex(bg), hex != "#00000000" {
|
|
114
|
+
node["kind"] = "rect"
|
|
115
|
+
node["color"] = hex
|
|
116
|
+
}
|
|
117
|
+
// else: invisible container — skip emitting but recurse.
|
|
118
|
+
|
|
119
|
+
if node["kind"] != nil {
|
|
120
|
+
nodes.append(node)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if !masked {
|
|
124
|
+
// Don't expose internals of masked subtrees.
|
|
125
|
+
for sub in view.subviews {
|
|
126
|
+
walk(
|
|
127
|
+
view: sub,
|
|
128
|
+
parentMasked: masked,
|
|
129
|
+
maskedIds: maskedIds,
|
|
130
|
+
window: window,
|
|
131
|
+
nodes: &nodes
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private static func colorToHex(_ color: UIColor?) -> String? {
|
|
138
|
+
guard let c = color else { return nil }
|
|
139
|
+
var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
|
|
140
|
+
c.getRed(&r, green: &g, blue: &b, alpha: &a)
|
|
141
|
+
let ri = max(0, min(255, Int(r * 255)))
|
|
142
|
+
let gi = max(0, min(255, Int(g * 255)))
|
|
143
|
+
let bi = max(0, min(255, Int(b * 255)))
|
|
144
|
+
let ai = max(0, min(255, Int(a * 255)))
|
|
145
|
+
return String(format: "#%02X%02X%02X%02X", ri, gi, bi, ai)
|
|
146
|
+
}
|
|
147
|
+
}
|
package/lib/capture.d.ts
CHANGED
|
@@ -15,6 +15,9 @@ export declare const __resetScreenshotBudgetForTests: () => void;
|
|
|
15
15
|
*/
|
|
16
16
|
export declare const setUser: (user: User | null) => void;
|
|
17
17
|
export declare const getUser: () => User | null;
|
|
18
|
+
/** v1.1 +S7 升级 — read just the current user id for the control
|
|
19
|
+
* channel poll. Returns `undefined` until `setUser({ id })` runs. */
|
|
20
|
+
export declare const getCurrentUserId: () => string | undefined;
|
|
18
21
|
export type CaptureExtras = {
|
|
19
22
|
tags?: Tags;
|
|
20
23
|
user?: User;
|
package/lib/capture.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAoD,IAAI,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE5F,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAgB5D,eAAO,MAAM,+BAA+B,QAAO,IAElD,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,OAAO,GAAI,MAAM,IAAI,GAAG,IAAI,KAAG,IAE3C,CAAC;AAEF,eAAO,MAAM,OAAO,QAAO,IAAI,GAAG,IAAa,CAAC;AAEhD;sEACsE;AACtE,eAAO,MAAM,gBAAgB,QAAO,MAAM,GAAG,SAAmC,CAAC;AAEjF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB;;;qDAGiD;IACjD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,GAAU,OAAO;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,KAAG,OAAO,CAAC,IAAI,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,IAAI,GAAG,MAAM,CAAA;CAAE,CAKxD,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,OAAO,KAAK,EAAE,SAAS,aAAa,KAAG,IA2EnE,CAAC;AAyFF,eAAO,MAAM,gBAAgB,UApKO,KAAK,WAAW,aAAa,KAAG,IAoKxB,CAAC"}
|
package/lib/capture.js
CHANGED
|
@@ -3,6 +3,7 @@ import { addBreadcrumb, getBreadcrumbs } from './breadcrumbs';
|
|
|
3
3
|
import { getBundleInfo } from './bundle-info';
|
|
4
4
|
import { getConfig, isInitialized } from './config';
|
|
5
5
|
import { getFeatureFlagSnapshot } from './feature-flags';
|
|
6
|
+
import { drainReplay } from './replay';
|
|
6
7
|
import { clearStateSnapshots, getStateSnapshots } from './state-snapshots';
|
|
7
8
|
import { symbolicateErrorViaMetro } from './handlers/dev-symbolicate';
|
|
8
9
|
import { captureScreenshot } from './handlers/screenshot';
|
|
@@ -42,6 +43,9 @@ export const setUser = (user) => {
|
|
|
42
43
|
_user = user;
|
|
43
44
|
};
|
|
44
45
|
export const getUser = () => _user;
|
|
46
|
+
/** v1.1 +S7 升级 — read just the current user id for the control
|
|
47
|
+
* channel poll. Returns `undefined` until `setUser({ id })` runs. */
|
|
48
|
+
export const getCurrentUserId = () => _user?.id ?? undefined;
|
|
45
49
|
/**
|
|
46
50
|
* v0.8.2 — submit an end-user-supplied bug report. Use this when the
|
|
47
51
|
* host app surfaces a "Report a problem" form. Pass `eventId` if the
|
|
@@ -122,10 +126,35 @@ export const captureError = (error, extras) => {
|
|
|
122
126
|
await captureAndAttachStateSnapshots(event, stateSnapshots);
|
|
123
127
|
clearStateSnapshots();
|
|
124
128
|
}
|
|
129
|
+
// v0.9.6 #2 — wireframe replay attachment. drainReplay clears the
|
|
130
|
+
// ring as a side effect so next session's replay starts fresh.
|
|
131
|
+
const replayNdjson = drainReplay();
|
|
132
|
+
if (replayNdjson.length > 0) {
|
|
133
|
+
await captureAndAttachReplay(event, replayNdjson);
|
|
134
|
+
}
|
|
125
135
|
enqueue(event);
|
|
126
136
|
};
|
|
127
137
|
void pipeline();
|
|
128
138
|
};
|
|
139
|
+
/** v0.9.6 #2 — upload the wireframe replay ring as a `replay`
|
|
140
|
+
* attachment. Plain NDJSON (one snapshot per line) — server may
|
|
141
|
+
* gzip on storage; the network upload is base64. */
|
|
142
|
+
async function captureAndAttachReplay(event, ndjson) {
|
|
143
|
+
try {
|
|
144
|
+
const base64 = typeof globalThis.btoa === 'function'
|
|
145
|
+
? globalThis.btoa(ndjson)
|
|
146
|
+
: Buffer.from(ndjson, 'utf8').toString('base64');
|
|
147
|
+
const meta = await uploadAttachment(event.id, 'replay', { base64, mediaType: 'application/x-ndjson' }, { source: 'js' });
|
|
148
|
+
if (meta) {
|
|
149
|
+
if (!event.attachments)
|
|
150
|
+
event.attachments = [];
|
|
151
|
+
event.attachments.push(meta);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// best-effort
|
|
156
|
+
}
|
|
157
|
+
}
|
|
129
158
|
/** v0.9.2 +S2 — upload the rolling state-snapshot ring as a
|
|
130
159
|
* `stateSnapshot` attachment so the dashboard time-travel viewer can
|
|
131
160
|
* scrub through diffs alongside the breadcrumb timeline. */
|
package/lib/capture.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEjE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAGpD,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAI5D,IAAI,KAAK,GAAgB,IAAI,CAAC;AAE9B,oEAAoE;AACpE,oEAAoE;AACpE,4DAA4D;AAC5D,MAAM,qBAAqB,GAAG,EAAE,CAAC;AACjC,IAAI,iBAAiB,GAAG,CAAC,CAAC;AAE1B,SAAS,gBAAgB;IACvB,OAAO,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC;AAChF,CAAC;AAED,MAAM,CAAC,MAAM,+BAA+B,GAAG,GAAS,EAAE;IACxD,iBAAiB,GAAG,CAAC,CAAC;AACxB,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAiB,EAAQ,EAAE;IACjD,KAAK,GAAG,IAAI,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,GAAgB,EAAE,CAAC,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function isLiveMode(): boolean;
|
|
2
|
+
export declare function startControlChannel(): void;
|
|
3
|
+
export declare function stopControlChannel(): void;
|
|
4
|
+
/** Test-only. */
|
|
5
|
+
export declare function __resetControlChannelForTests(): void;
|
|
6
|
+
//# sourceMappingURL=control-channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-channel.d.ts","sourceRoot":"","sources":["../src/control-channel.ts"],"names":[],"mappings":"AAyBA,wBAAgB,UAAU,IAAI,OAAO,CAQpC;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAS1C;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAOzC;AAiCD,iBAAiB;AACjB,wBAAgB,6BAA6B,IAAI,IAAI,CAEpD"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// v1.1 +S7 升级 — SDK control channel for sub-second live debug.
|
|
2
|
+
//
|
|
3
|
+
// Every 30 s the SDK polls `/v1/control/poll?userId=<current>` and
|
|
4
|
+
// reads back `{ liveMode: boolean, ttlMs: number }`. While live mode
|
|
5
|
+
// is on, the transport flushes events immediately (BATCH_SIZE = 1,
|
|
6
|
+
// FLUSH_INTERVAL = 0) so dashboard's live-debug viewer sees each
|
|
7
|
+
// event with sub-second latency instead of waiting for the 5 s
|
|
8
|
+
// batch tick.
|
|
9
|
+
//
|
|
10
|
+
// When live mode goes off the SDK reverts to its normal batching —
|
|
11
|
+
// no permanent overhead, no state to clean up.
|
|
12
|
+
//
|
|
13
|
+
// Implementation note: the control channel is purely advisory.
|
|
14
|
+
// transport.ts reads `isLiveMode()` before each enqueue and decides
|
|
15
|
+
// whether to wait for batch or flush right now.
|
|
16
|
+
import { getConfig } from './config';
|
|
17
|
+
import { getCurrentUserId } from './capture';
|
|
18
|
+
const POLL_INTERVAL_MS = 30_000;
|
|
19
|
+
let _liveMode = false;
|
|
20
|
+
let _liveModeUntil = 0;
|
|
21
|
+
let _timer = null;
|
|
22
|
+
export function isLiveMode() {
|
|
23
|
+
if (!_liveMode)
|
|
24
|
+
return false;
|
|
25
|
+
// Self-expire if the server-side TTL has passed without a refresh.
|
|
26
|
+
if (Date.now() > _liveModeUntil) {
|
|
27
|
+
_liveMode = false;
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
export function startControlChannel() {
|
|
33
|
+
if (_timer !== null)
|
|
34
|
+
return;
|
|
35
|
+
// Fire one poll right away so init → setUser → quick captureException
|
|
36
|
+
// can already pick up an existing live-debug session.
|
|
37
|
+
void pollOnce();
|
|
38
|
+
_timer = setInterval(() => {
|
|
39
|
+
void pollOnce();
|
|
40
|
+
}, POLL_INTERVAL_MS);
|
|
41
|
+
_timer.unref?.();
|
|
42
|
+
}
|
|
43
|
+
export function stopControlChannel() {
|
|
44
|
+
if (_timer !== null) {
|
|
45
|
+
clearInterval(_timer);
|
|
46
|
+
_timer = null;
|
|
47
|
+
}
|
|
48
|
+
_liveMode = false;
|
|
49
|
+
_liveModeUntil = 0;
|
|
50
|
+
}
|
|
51
|
+
async function pollOnce() {
|
|
52
|
+
const config = getConfig();
|
|
53
|
+
if (!config)
|
|
54
|
+
return;
|
|
55
|
+
const userId = getCurrentUserId();
|
|
56
|
+
if (!userId) {
|
|
57
|
+
// Without setUser we have no key. Live mode is per-user-id.
|
|
58
|
+
_liveMode = false;
|
|
59
|
+
_liveModeUntil = 0;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const url = `${config.ingestUrl}/v1/control/poll?userId=${encodeURIComponent(userId)}`;
|
|
64
|
+
const resp = await fetch(url, {
|
|
65
|
+
headers: { Authorization: `Bearer ${config.token}` },
|
|
66
|
+
method: 'GET',
|
|
67
|
+
});
|
|
68
|
+
if (!resp.ok)
|
|
69
|
+
return;
|
|
70
|
+
const body = (await resp.json());
|
|
71
|
+
if (body.liveMode === true) {
|
|
72
|
+
_liveMode = true;
|
|
73
|
+
_liveModeUntil = Date.now() + Math.max(0, Math.min(body.ttlMs ?? 0, 15 * 60_000));
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
_liveMode = false;
|
|
77
|
+
_liveModeUntil = 0;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Network failure → leave the previous state. Self-expiring TTL
|
|
82
|
+
// handles "didn't reach server" gracefully.
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Test-only. */
|
|
86
|
+
export function __resetControlChannelForTests() {
|
|
87
|
+
stopControlChannel();
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=control-channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"control-channel.js","sourceRoot":"","sources":["../src/control-channel.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAkB,KAAK,oBAAoB,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAOxG,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACL,cAAc,EACd,qBAAqB,EAEtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAO5C,eAAO,MAAM,OAAO;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAkB,KAAK,oBAAoB,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAOxG,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACL,cAAc,EACd,qBAAqB,EAEtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAO5C,eAAO,MAAM,OAAO;;;;;;;;;;aA8FiV,CAAC;eAAmB,CAAC;YAAgB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;CAhE1Y,CAAC;AAEF,eAAe,OAAO,CAAC;AAEvB,OAAO,EAAE,IAAI,EAAE,IAAI,IAAI,WAAW,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,OAAO,EACP,gBAAgB,EAChB,OAAO,GACR,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxG,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EACL,SAAS,EACT,WAAW,EACX,KAAK,aAAa,EAClB,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,kBAAkB,GACnB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,KAAK,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAE1E,YAAY,EACV,KAAK,EACL,YAAY,EACZ,KAAK,EACL,UAAU,EACV,cAAc,EACd,MAAM,EACN,QAAQ,EACR,GAAG,EACH,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,QAAQ,GACT,MAAM,SAAS,CAAC"}
|
package/lib/init.d.ts
CHANGED
|
@@ -44,6 +44,22 @@ export type InitOptions = {
|
|
|
44
44
|
* signal before an actual crash. */
|
|
45
45
|
preCrashSentinel?: boolean;
|
|
46
46
|
sentinelChannels?: PreCrashChannel[];
|
|
47
|
+
/** v0.9.6 #4 — JS-thread long-task monitor. setInterval(50ms)
|
|
48
|
+
* tick detects JS thread stalls ≥ 200ms (configurable) and
|
|
49
|
+
* emits a `sentori.longtask` span. Pairs with
|
|
50
|
+
* `preCrashSentinel` (slow frames < 32ms) to cover the
|
|
51
|
+
* "JS thread is stuck" spectrum. */
|
|
52
|
+
longTaskMonitor?: boolean | {
|
|
53
|
+
thresholdMs?: number;
|
|
54
|
+
};
|
|
55
|
+
/** v0.9.6 #2 — wireframe session replay. Native walks the iOS
|
|
56
|
+
* UIView / Android View hierarchy at 1 Hz and serializes
|
|
57
|
+
* visible nodes; captureException flushes the last 60 s as a
|
|
58
|
+
* `replay` attachment. Set to `'wireframe'` to enable. */
|
|
59
|
+
replay?: 'off' | 'wireframe' | {
|
|
60
|
+
hz?: number;
|
|
61
|
+
mode: 'off' | 'wireframe';
|
|
62
|
+
};
|
|
47
63
|
/** v0.9.0 #3 — launch-crash loop guard. When two consecutive
|
|
48
64
|
* launches don't reach `markLaunchCompleted()` (typical of an
|
|
49
65
|
* OTA update with a fatal bug), invoke the host callback with
|
package/lib/init.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AASnF,OAAO,KAAK,EAAkB,cAAc,EAA2B,MAAM,SAAS,CAAC;AAIvF,MAAM,MAAM,WAAW,GAAG;IACxB,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,OAAO,CAAC,EAAE;QACR,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,OAAO,CAAC,EACJ,OAAO,GACP;YACE;;qEAEyD;YACzD,OAAO,CAAC,EAAE,OAAO,CAAC;SACnB,CAAC;QACN;;8DAEsD;QACtD,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB;;;;;;;uBAOe;QACf,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB;;;6CAGqC;QACrC,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB;;;;6CAIqC;QACrC,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;QACrC;;;;6CAIqC;QACrC,eAAe,CAAC,EAAE,OAAO,GAAG;YAAE,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACrD;;;mEAG2D;QAC3D,MAAM,CAAC,EAAE,KAAK,GAAG,WAAW,GAAG;YAAE,EAAE,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,KAAK,GAAG,WAAW,CAAA;SAAE,CAAC;QAC1E;;;sEAG8D;QAC9D,gBAAgB,CAAC,EAAE;YACjB,OAAO,EAAE,OAAO,CAAC;YACjB,qBAAqB,CAAC,EAAE,CACtB,IAAI,EAAE,OAAO,sBAAsB,EAAE,eAAe,KAElD,OAAO,sBAAsB,EAAE,iBAAiB,GAChD,OAAO,CAAC,OAAO,sBAAsB,EAAE,iBAAiB,CAAC,CAAC;YAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,SAAS,CAAC,EAAE,MAAM,CAAC;SACpB,CAAC;KACH,CAAC;IACF;;;;;gEAK4D;IAC5D,QAAQ,CAAC,EAAE;QACT,MAAM,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;QACvB,MAAM,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;KACxB,CAAC;CACH,CAAC;AAIF,eAAO,MAAM,IAAI,GAAI,SAAS,WAAW,KAAG,IA+J3C,CAAC;AAiBF,YAAY,EAAE,cAAc,EAAE,CAAC"}
|
package/lib/init.js
CHANGED
|
@@ -9,8 +9,11 @@ import { startMetricsTimer } from './metrics';
|
|
|
9
9
|
import { drainNativePending, markNativeJsBridgeReady, setNativeConfig } from './native';
|
|
10
10
|
import { getColdStartMs } from './mobile-vitals';
|
|
11
11
|
import { startSpan } from '@goliapkg/sentori-core';
|
|
12
|
+
import { startControlChannel } from './control-channel';
|
|
13
|
+
import { startLongTaskMonitor } from './long-task-monitor';
|
|
12
14
|
import { startNetworkTypeWatch } from './netinfo';
|
|
13
15
|
import { startPreCrashSentinel } from './pre-crash-sentinel';
|
|
16
|
+
import { startReplay } from './replay';
|
|
14
17
|
import { startSession } from './session-tracker';
|
|
15
18
|
import { drainOfflineQueue, enqueue, startTransport, uploadAttachment, } from './transport';
|
|
16
19
|
const DEFAULT_INGEST_URL = 'https://ingest.sentori.golia.jp';
|
|
@@ -68,6 +71,8 @@ export const init = (options) => {
|
|
|
68
71
|
span.finish({ status: 'ok' });
|
|
69
72
|
}
|
|
70
73
|
startTransport();
|
|
74
|
+
// v1.1 +S7 升级 — control channel poll for live-debug flag.
|
|
75
|
+
startControlChannel();
|
|
71
76
|
// v0.8.0-c — start watching network class. No-op if NetInfo isn't
|
|
72
77
|
// installed; events just won't carry `device.networkType` in that
|
|
73
78
|
// case.
|
|
@@ -82,6 +87,22 @@ export const init = (options) => {
|
|
|
82
87
|
channels: options.capture.sentinelChannels,
|
|
83
88
|
});
|
|
84
89
|
}
|
|
90
|
+
// v0.9.6 #4 — long-task monitor. Off by default.
|
|
91
|
+
const lt = options.capture?.longTaskMonitor;
|
|
92
|
+
if (lt) {
|
|
93
|
+
startLongTaskMonitor({
|
|
94
|
+
enabled: true,
|
|
95
|
+
thresholdMs: typeof lt === 'object' ? lt.thresholdMs : undefined,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
// v0.9.6 #2 — wireframe replay. Off by default.
|
|
99
|
+
const rp = options.capture?.replay;
|
|
100
|
+
if (rp === 'wireframe') {
|
|
101
|
+
startReplay({ mode: 'wireframe' });
|
|
102
|
+
}
|
|
103
|
+
else if (rp && typeof rp === 'object' && rp.mode === 'wireframe') {
|
|
104
|
+
startReplay({ hz: rp.hz, mode: 'wireframe' });
|
|
105
|
+
}
|
|
85
106
|
const capture = options.capture ?? {};
|
|
86
107
|
if (capture.globalErrors !== false)
|
|
87
108
|
installGlobalHandler();
|