react-native-nitro-tracing 0.6.0
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/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/NitroTracing.podspec +32 -0
- package/README.md +75 -0
- package/android/CMakeLists.txt +49 -0
- package/android/build.gradle +133 -0
- package/android/fix-prefab.gradle +51 -0
- package/android/gradle.properties +5 -0
- package/android/proguard-rules.pro +5 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/cpp-adapter.cpp +47 -0
- package/android/src/main/java/com/margelo/nitro/nitrotracing/HermesSamplingGuard.kt +43 -0
- package/android/src/main/java/com/margelo/nitro/nitrotracing/NitroTracingFrameSource.kt +36 -0
- package/android/src/main/java/com/margelo/nitro/nitrotracing/NitroTracingPackage.kt +31 -0
- package/client.ts +15 -0
- package/cpp/HermesSampling.cpp +26 -0
- package/cpp/HermesSampling.hpp +10 -0
- package/cpp/HybridRecording.cpp +66 -0
- package/cpp/HybridRecording.hpp +30 -0
- package/cpp/HybridTraceSpan.cpp +10 -0
- package/cpp/HybridTraceSpan.hpp +17 -0
- package/cpp/HybridTracing.cpp +10 -0
- package/cpp/HybridTracing.hpp +10 -0
- package/cpp/NativeConversions.cpp +77 -0
- package/cpp/NativeConversions.hpp +15 -0
- package/cpp/core/NativeSampler.cpp +152 -0
- package/cpp/core/NativeSampler.hpp +56 -0
- package/cpp/core/Recorder.cpp +218 -0
- package/cpp/core/Recorder.hpp +60 -0
- package/cpp/core/Retention.cpp +26 -0
- package/cpp/core/Retention.hpp +7 -0
- package/cpp/core/TraceJson.cpp +214 -0
- package/cpp/core/TraceJson.hpp +7 -0
- package/cpp/core/TraceTypes.hpp +62 -0
- package/expo.ts +2 -0
- package/ios/NitroTracingFrameSource.mm +35 -0
- package/lib/commonjs/client.cjs +767 -0
- package/lib/commonjs/client.cjs.map +7 -0
- package/lib/commonjs/expo.cjs +88 -0
- package/lib/commonjs/expo.cjs.map +7 -0
- package/lib/commonjs/index.cjs +28 -0
- package/lib/commonjs/index.cjs.map +7 -0
- package/lib/commonjs/performance.cjs +112 -0
- package/lib/commonjs/performance.cjs.map +7 -0
- package/lib/commonjs/plugins.cjs +477 -0
- package/lib/commonjs/plugins.cjs.map +7 -0
- package/lib/commonjs/react.cjs +3833 -0
- package/lib/commonjs/react.cjs.map +7 -0
- package/lib/commonjs/release-profiler.cjs +142 -0
- package/lib/commonjs/release-profiler.cjs.map +7 -0
- package/lib/commonjs/sentry.cjs +188 -0
- package/lib/commonjs/sentry.cjs.map +7 -0
- package/lib/module/client.mjs +768 -0
- package/lib/module/client.mjs.map +7 -0
- package/lib/module/expo.mjs +62 -0
- package/lib/module/expo.mjs.map +7 -0
- package/lib/module/index.mjs +7 -0
- package/lib/module/index.mjs.map +7 -0
- package/lib/module/performance.mjs +89 -0
- package/lib/module/performance.mjs.map +7 -0
- package/lib/module/plugins.mjs +461 -0
- package/lib/module/plugins.mjs.map +7 -0
- package/lib/module/react.mjs +3851 -0
- package/lib/module/react.mjs.map +7 -0
- package/lib/module/release-profiler.mjs +137 -0
- package/lib/module/release-profiler.mjs.map +7 -0
- package/lib/module/sentry.mjs +165 -0
- package/lib/module/sentry.mjs.map +7 -0
- package/lib/typescript/client.d.ts +4 -0
- package/lib/typescript/expo.d.ts +2 -0
- package/lib/typescript/performance.d.ts +2 -0
- package/lib/typescript/plugins.d.ts +12 -0
- package/lib/typescript/react.d.ts +5 -0
- package/lib/typescript/release-profiler.d.ts +2 -0
- package/lib/typescript/sentry.d.ts +2 -0
- package/lib/typescript/src/client/TracingSink.d.ts +10 -0
- package/lib/typescript/src/client/createTraceClient.d.ts +82 -0
- package/lib/typescript/src/client/playground.d.ts +12 -0
- package/lib/typescript/src/expo/ExpoAdapter.d.ts +15 -0
- package/lib/typescript/src/expo/index.d.ts +2 -0
- package/lib/typescript/src/index.d.ts +6 -0
- package/lib/typescript/src/plugins/TracePlugin.d.ts +22 -0
- package/lib/typescript/src/plugins/errors.d.ts +15 -0
- package/lib/typescript/src/plugins/nativeMetrics.d.ts +13 -0
- package/lib/typescript/src/plugins/navigation.d.ts +29 -0
- package/lib/typescript/src/plugins/network.d.ts +23 -0
- package/lib/typescript/src/plugins/orderSpans.d.ts +3 -0
- package/lib/typescript/src/plugins/performance.d.ts +13 -0
- package/lib/typescript/src/plugins/releaseProfiler.d.ts +25 -0
- package/lib/typescript/src/plugins/runtimeMetrics.d.ts +17 -0
- package/lib/typescript/src/plugins/sentry.d.ts +15 -0
- package/lib/typescript/src/plugins/startPlugins.d.ts +4 -0
- package/lib/typescript/src/react/DetailView.d.ts +11 -0
- package/lib/typescript/src/react/ExplorerFilters.d.ts +9 -0
- package/lib/typescript/src/react/ExplorerView.d.ts +9 -0
- package/lib/typescript/src/react/InspectorControls.d.ts +229 -0
- package/lib/typescript/src/react/InspectorHeader.d.ts +8 -0
- package/lib/typescript/src/react/InspectorSheet.d.ts +16 -0
- package/lib/typescript/src/react/MetricsView.d.ts +7 -0
- package/lib/typescript/src/react/SummaryView.d.ts +11 -0
- package/lib/typescript/src/react/TimelineView.d.ts +8 -0
- package/lib/typescript/src/react/TraceInspector.d.ts +11 -0
- package/lib/typescript/src/react/TraceOverlay.d.ts +17 -0
- package/lib/typescript/src/react/explorerModel.d.ts +38 -0
- package/lib/typescript/src/react/labels.d.ts +203 -0
- package/lib/typescript/src/react/native.d.ts +42 -0
- package/lib/typescript/src/react/readSnapshot.d.ts +4 -0
- package/lib/typescript/src/react/store.d.ts +9 -0
- package/lib/typescript/src/react/topics.d.ts +80 -0
- package/lib/typescript/src/react/useAppReadyMetric.d.ts +3 -0
- package/lib/typescript/src/react/useLiveRecording.d.ts +4 -0
- package/lib/typescript/src/react/useTraceViewer.d.ts +140 -0
- package/lib/typescript/src/react/viewerModel.d.ts +59 -0
- package/lib/typescript/src/specs/Recording.nitro.d.ts +31 -0
- package/lib/typescript/src/specs/TraceSpan.nitro.d.ts +14 -0
- package/lib/typescript/src/specs/Tracing.nitro.d.ts +17 -0
- package/lib/typescript/src/types/CompletedSpanOptions.d.ts +15 -0
- package/lib/typescript/src/types/EventContext.d.ts +8 -0
- package/lib/typescript/src/types/MarkEvent.d.ts +4 -0
- package/lib/typescript/src/types/MarkOptions.d.ts +6 -0
- package/lib/typescript/src/types/MetricEvent.d.ts +8 -0
- package/lib/typescript/src/types/MetricOptions.d.ts +10 -0
- package/lib/typescript/src/types/NativeSamplingOptions.d.ts +7 -0
- package/lib/typescript/src/types/ReadOptions.d.ts +7 -0
- package/lib/typescript/src/types/RecordingOptions.d.ts +11 -0
- package/lib/typescript/src/types/RecordingStats.d.ts +25 -0
- package/lib/typescript/src/types/SpanEvent.d.ts +13 -0
- package/lib/typescript/src/types/SpanOptions.d.ts +6 -0
- package/lib/typescript/src/types/SpanOutcome.d.ts +2 -0
- package/lib/typescript/src/types/TraceAttribute.d.ts +7 -0
- package/lib/typescript/src/types/TraceAttributes.d.ts +3 -0
- package/lib/typescript/src/types/TraceContext.d.ts +10 -0
- package/lib/typescript/src/types/TracePage.d.ts +18 -0
- package/lib/typescript/src/types.d.ts +17 -0
- package/nitro.json +20 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/NitroTracing+autolinking.cmake +83 -0
- package/nitrogen/generated/android/NitroTracing+autolinking.gradle +27 -0
- package/nitrogen/generated/android/NitroTracingOnLoad.cpp +49 -0
- package/nitrogen/generated/android/NitroTracingOnLoad.hpp +34 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrotracing/NitroTracingOnLoad.kt +35 -0
- package/nitrogen/generated/ios/NitroTracing+autolinking.rb +62 -0
- package/nitrogen/generated/ios/NitroTracing-Swift-Cxx-Bridge.cpp +17 -0
- package/nitrogen/generated/ios/NitroTracing-Swift-Cxx-Bridge.hpp +27 -0
- package/nitrogen/generated/ios/NitroTracing-Swift-Cxx-Umbrella.hpp +38 -0
- package/nitrogen/generated/ios/NitroTracingAutolinking.mm +35 -0
- package/nitrogen/generated/ios/NitroTracingAutolinking.swift +16 -0
- package/nitrogen/generated/shared/c++/CompletedSpanOptions.hpp +122 -0
- package/nitrogen/generated/shared/c++/HybridRecordingSpec.cpp +31 -0
- package/nitrogen/generated/shared/c++/HybridRecordingSpec.hpp +100 -0
- package/nitrogen/generated/shared/c++/HybridTraceSpanSpec.cpp +23 -0
- package/nitrogen/generated/shared/c++/HybridTraceSpanSpec.hpp +65 -0
- package/nitrogen/generated/shared/c++/HybridTracingSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridTracingSpec.hpp +68 -0
- package/nitrogen/generated/shared/c++/MarkEvent.hpp +102 -0
- package/nitrogen/generated/shared/c++/MarkOptions.hpp +99 -0
- package/nitrogen/generated/shared/c++/MetricEvent.hpp +110 -0
- package/nitrogen/generated/shared/c++/MetricOptions.hpp +107 -0
- package/nitrogen/generated/shared/c++/NativeSamplingOptions.hpp +87 -0
- package/nitrogen/generated/shared/c++/ReadOptions.hpp +87 -0
- package/nitrogen/generated/shared/c++/RecordingOptions.hpp +95 -0
- package/nitrogen/generated/shared/c++/RecordingStats.hpp +123 -0
- package/nitrogen/generated/shared/c++/SpanEvent.hpp +121 -0
- package/nitrogen/generated/shared/c++/SpanOptions.hpp +99 -0
- package/nitrogen/generated/shared/c++/SpanOutcome.hpp +84 -0
- package/nitrogen/generated/shared/c++/TraceAttribute.hpp +87 -0
- package/nitrogen/generated/shared/c++/TracePage.hpp +111 -0
- package/package.json +236 -0
- package/performance.ts +2 -0
- package/plugins.ts +24 -0
- package/react-native.config.js +16 -0
- package/react.ts +10 -0
- package/release-profiler.ts +6 -0
- package/sentry.ts +2 -0
- package/src/client/TracingSink.ts +25 -0
- package/src/client/createTraceClient.ts +439 -0
- package/src/client/playground.ts +143 -0
- package/src/expo/ExpoAdapter.ts +71 -0
- package/src/expo/index.ts +2 -0
- package/src/index.ts +8 -0
- package/src/plugins/TracePlugin.ts +22 -0
- package/src/plugins/errors.ts +69 -0
- package/src/plugins/nativeMetrics.ts +26 -0
- package/src/plugins/navigation.ts +111 -0
- package/src/plugins/network.ts +178 -0
- package/src/plugins/orderSpans.ts +22 -0
- package/src/plugins/performance.ts +120 -0
- package/src/plugins/releaseProfiler.ts +123 -0
- package/src/plugins/runtimeMetrics.ts +131 -0
- package/src/plugins/sentry.ts +176 -0
- package/src/plugins/startPlugins.ts +58 -0
- package/src/react/DetailView.tsx +514 -0
- package/src/react/ExplorerFilters.tsx +151 -0
- package/src/react/ExplorerView.tsx +243 -0
- package/src/react/InspectorControls.tsx +651 -0
- package/src/react/InspectorHeader.tsx +171 -0
- package/src/react/InspectorSheet.tsx +89 -0
- package/src/react/MetricsView.tsx +182 -0
- package/src/react/SummaryView.tsx +121 -0
- package/src/react/TimelineView.tsx +87 -0
- package/src/react/TraceInspector.tsx +196 -0
- package/src/react/TraceOverlay.tsx +585 -0
- package/src/react/explorerModel.ts +285 -0
- package/src/react/labels.ts +234 -0
- package/src/react/native.tsx +159 -0
- package/src/react/readSnapshot.ts +58 -0
- package/src/react/store.ts +31 -0
- package/src/react/topics.ts +427 -0
- package/src/react/useAppReadyMetric.ts +10 -0
- package/src/react/useLiveRecording.ts +43 -0
- package/src/react/useTraceViewer.ts +333 -0
- package/src/react/viewerModel.ts +172 -0
- package/src/specs/Recording.nitro.ts +40 -0
- package/src/specs/TraceSpan.nitro.ts +14 -0
- package/src/specs/Tracing.nitro.ts +14 -0
- package/src/types/CompletedSpanOptions.ts +15 -0
- package/src/types/EventContext.ts +8 -0
- package/src/types/MarkEvent.ts +3 -0
- package/src/types/MarkOptions.ts +6 -0
- package/src/types/MetricEvent.ts +8 -0
- package/src/types/MetricOptions.ts +10 -0
- package/src/types/NativeSamplingOptions.ts +7 -0
- package/src/types/ReadOptions.ts +7 -0
- package/src/types/RecordingOptions.ts +11 -0
- package/src/types/RecordingStats.ts +25 -0
- package/src/types/SpanEvent.ts +13 -0
- package/src/types/SpanOptions.ts +6 -0
- package/src/types/SpanOutcome.ts +2 -0
- package/src/types/TraceAttribute.ts +7 -0
- package/src/types/TraceAttributes.ts +4 -0
- package/src/types/TraceContext.ts +10 -0
- package/src/types/TracePage.ts +18 -0
- package/src/types.ts +17 -0
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// plugins.ts
|
|
21
|
+
var plugins_exports = {};
|
|
22
|
+
__export(plugins_exports, {
|
|
23
|
+
createErrorsPlugin: () => createErrorsPlugin,
|
|
24
|
+
createNativeMetricsPlugin: () => createNativeMetricsPlugin,
|
|
25
|
+
createNavigationPlugin: () => createNavigationPlugin,
|
|
26
|
+
createNetworkPlugin: () => createNetworkPlugin,
|
|
27
|
+
createRuntimeMetricsPlugin: () => createRuntimeMetricsPlugin,
|
|
28
|
+
createScreenTracker: () => createScreenTracker,
|
|
29
|
+
startPlugins: () => startPlugins,
|
|
30
|
+
urlTemplate: () => urlTemplate
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(plugins_exports);
|
|
33
|
+
|
|
34
|
+
// src/plugins/startPlugins.ts
|
|
35
|
+
function startPlugins(recording, plugins, onError) {
|
|
36
|
+
const handles = [];
|
|
37
|
+
const ids = /* @__PURE__ */ new Set();
|
|
38
|
+
for (const plugin of plugins) {
|
|
39
|
+
if (ids.has(plugin.id))
|
|
40
|
+
throw new Error(`Duplicate tracing plugin: ${plugin.id}`);
|
|
41
|
+
ids.add(plugin.id);
|
|
42
|
+
}
|
|
43
|
+
const reportError = (error) => {
|
|
44
|
+
try {
|
|
45
|
+
onError(error);
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
for (const plugin of plugins) {
|
|
50
|
+
try {
|
|
51
|
+
handles.push(plugin.start({ recording, reportError }));
|
|
52
|
+
} catch (error) {
|
|
53
|
+
reportError(error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
let stopping;
|
|
57
|
+
return {
|
|
58
|
+
stop() {
|
|
59
|
+
if (!stopping)
|
|
60
|
+
stopping = (async () => {
|
|
61
|
+
for (const handle of [...handles].reverse()) {
|
|
62
|
+
try {
|
|
63
|
+
await handle.stop();
|
|
64
|
+
} catch (error) {
|
|
65
|
+
reportError(error);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
recording.stop();
|
|
70
|
+
} catch (error) {
|
|
71
|
+
reportError(error);
|
|
72
|
+
}
|
|
73
|
+
for (const handle of handles) {
|
|
74
|
+
try {
|
|
75
|
+
await handle.flush?.();
|
|
76
|
+
} catch (error) {
|
|
77
|
+
reportError(error);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
})();
|
|
81
|
+
return stopping;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/plugins/runtimeMetrics.ts
|
|
87
|
+
var nativeHost = () => {
|
|
88
|
+
const { AppState } = require("react-native");
|
|
89
|
+
return {
|
|
90
|
+
now: () => globalThis.performance.now(),
|
|
91
|
+
isActive: () => AppState.currentState === "active",
|
|
92
|
+
subscribe: (listener) => {
|
|
93
|
+
const subscription = AppState.addEventListener(
|
|
94
|
+
"change",
|
|
95
|
+
(state) => listener(state === "active")
|
|
96
|
+
);
|
|
97
|
+
return () => subscription.remove();
|
|
98
|
+
},
|
|
99
|
+
requestFrame: (callback) => requestAnimationFrame(callback),
|
|
100
|
+
cancelFrame: (id) => cancelAnimationFrame(id)
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
function createRuntimeMetricsPlugin(options = {}, host) {
|
|
104
|
+
const interval = options.intervalMs ?? 1e3;
|
|
105
|
+
if (!Number.isFinite(interval) || interval < 250)
|
|
106
|
+
throw new Error("Runtime metrics interval must be at least 250ms");
|
|
107
|
+
return {
|
|
108
|
+
id: "runtime-metrics",
|
|
109
|
+
start({ recording, reportError }) {
|
|
110
|
+
const api = host ?? nativeHost();
|
|
111
|
+
let stopped = false;
|
|
112
|
+
let active = false;
|
|
113
|
+
let timer;
|
|
114
|
+
let frame;
|
|
115
|
+
let started = 0;
|
|
116
|
+
let previousFrame;
|
|
117
|
+
let frames = 0;
|
|
118
|
+
let maxGap = 0;
|
|
119
|
+
let longGaps = 0;
|
|
120
|
+
const reset = () => {
|
|
121
|
+
started = api.now();
|
|
122
|
+
frames = 0;
|
|
123
|
+
maxGap = 0;
|
|
124
|
+
longGaps = 0;
|
|
125
|
+
};
|
|
126
|
+
const emit = (name, value, unit) => {
|
|
127
|
+
try {
|
|
128
|
+
recording.recordMetric({
|
|
129
|
+
name,
|
|
130
|
+
value,
|
|
131
|
+
unit,
|
|
132
|
+
correlationId: "",
|
|
133
|
+
attributes: [
|
|
134
|
+
{ key: "source", value: "js-runtime" },
|
|
135
|
+
{ key: "scope", value: "foreground" },
|
|
136
|
+
{ key: "windowMs", value: String(api.now() - started) }
|
|
137
|
+
]
|
|
138
|
+
});
|
|
139
|
+
} catch (error) {
|
|
140
|
+
reportError(error);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
const onFrame = () => {
|
|
144
|
+
if (stopped || !active) return;
|
|
145
|
+
const now = api.now();
|
|
146
|
+
if (previousFrame !== void 0) {
|
|
147
|
+
const gap = Math.max(0, now - previousFrame);
|
|
148
|
+
maxGap = Math.max(maxGap, gap);
|
|
149
|
+
if (gap > 50) longGaps++;
|
|
150
|
+
}
|
|
151
|
+
previousFrame = now;
|
|
152
|
+
frames++;
|
|
153
|
+
frame = api.requestFrame(onFrame);
|
|
154
|
+
};
|
|
155
|
+
const tick = () => {
|
|
156
|
+
if (stopped || !active) return;
|
|
157
|
+
const elapsed = api.now() - started;
|
|
158
|
+
emit("js.event_loop.delay", Math.max(0, elapsed - interval), "ms");
|
|
159
|
+
if (options.frames !== false && elapsed > 0) {
|
|
160
|
+
emit(
|
|
161
|
+
"js.frame_callback.rate",
|
|
162
|
+
frames * 1e3 / elapsed,
|
|
163
|
+
"callbacks/s"
|
|
164
|
+
);
|
|
165
|
+
if (frames > 1) emit("js.frame_gap.max", maxGap, "ms");
|
|
166
|
+
emit("js.frame_gap.over_50ms", longGaps, "count");
|
|
167
|
+
}
|
|
168
|
+
reset();
|
|
169
|
+
timer = setTimeout(tick, interval);
|
|
170
|
+
};
|
|
171
|
+
const suspend = () => {
|
|
172
|
+
clearTimeout(timer);
|
|
173
|
+
if (frame !== void 0) api.cancelFrame(frame);
|
|
174
|
+
frame = void 0;
|
|
175
|
+
};
|
|
176
|
+
const change = (next) => {
|
|
177
|
+
if (stopped || next === active) return;
|
|
178
|
+
active = next;
|
|
179
|
+
previousFrame = void 0;
|
|
180
|
+
suspend();
|
|
181
|
+
reset();
|
|
182
|
+
if (active) {
|
|
183
|
+
timer = setTimeout(tick, interval);
|
|
184
|
+
if (options.frames !== false) frame = api.requestFrame(onFrame);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
const unsubscribe = api.subscribe(change);
|
|
188
|
+
change(api.isActive());
|
|
189
|
+
return {
|
|
190
|
+
stop() {
|
|
191
|
+
stopped = true;
|
|
192
|
+
active = false;
|
|
193
|
+
suspend();
|
|
194
|
+
unsubscribe();
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/plugins/navigation.ts
|
|
202
|
+
function createNavigationPlugin(ref, options = {}) {
|
|
203
|
+
return {
|
|
204
|
+
id: "navigation",
|
|
205
|
+
start({ recording, reportError }) {
|
|
206
|
+
const requestFrame = options.requestFrame ?? ((callback) => requestAnimationFrame(callback));
|
|
207
|
+
let visit;
|
|
208
|
+
let current;
|
|
209
|
+
let visits = 0;
|
|
210
|
+
let stopped = false;
|
|
211
|
+
const enter = () => {
|
|
212
|
+
if (stopped) return;
|
|
213
|
+
try {
|
|
214
|
+
if (ref.isReady?.() === false) return;
|
|
215
|
+
const route = ref.getCurrentRoute();
|
|
216
|
+
const key = route && (route.key ?? route.name);
|
|
217
|
+
if (!route || key === current) return;
|
|
218
|
+
current = key;
|
|
219
|
+
visit?.end("success");
|
|
220
|
+
visit = void 0;
|
|
221
|
+
const correlationId = `screen:${++visits}`;
|
|
222
|
+
const attributes = [
|
|
223
|
+
{ key: "source", value: "navigation" },
|
|
224
|
+
{ key: "screen", value: route.name.slice(0, 1024) }
|
|
225
|
+
];
|
|
226
|
+
const startedAt = recording.getStats().nowMs;
|
|
227
|
+
recording.mark({
|
|
228
|
+
name: "navigation.enter",
|
|
229
|
+
correlationId,
|
|
230
|
+
attributes
|
|
231
|
+
});
|
|
232
|
+
visit = recording.startSpan({
|
|
233
|
+
name: `screen ${route.name}`.slice(0, 200),
|
|
234
|
+
correlationId,
|
|
235
|
+
attributes
|
|
236
|
+
});
|
|
237
|
+
requestFrame(
|
|
238
|
+
() => requestFrame(() => {
|
|
239
|
+
if (stopped) return;
|
|
240
|
+
try {
|
|
241
|
+
recording.recordMetric({
|
|
242
|
+
name: "navigation.transition",
|
|
243
|
+
value: recording.getStats().nowMs - startedAt,
|
|
244
|
+
unit: "ms",
|
|
245
|
+
correlationId,
|
|
246
|
+
attributes
|
|
247
|
+
});
|
|
248
|
+
} catch (error) {
|
|
249
|
+
reportError(error);
|
|
250
|
+
}
|
|
251
|
+
})
|
|
252
|
+
);
|
|
253
|
+
} catch (error) {
|
|
254
|
+
reportError(error);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
const unsubscribers = [
|
|
258
|
+
ref.addListener("ready", enter),
|
|
259
|
+
ref.addListener("state", enter)
|
|
260
|
+
];
|
|
261
|
+
enter();
|
|
262
|
+
return {
|
|
263
|
+
stop() {
|
|
264
|
+
stopped = true;
|
|
265
|
+
for (const unsubscribe of unsubscribers) unsubscribe();
|
|
266
|
+
visit?.end("success");
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
function createScreenTracker(initial) {
|
|
273
|
+
let route = initial ? { name: initial } : void 0;
|
|
274
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
275
|
+
return {
|
|
276
|
+
addListener(_event, listener) {
|
|
277
|
+
listeners.add(listener);
|
|
278
|
+
return () => void listeners.delete(listener);
|
|
279
|
+
},
|
|
280
|
+
getCurrentRoute: () => route,
|
|
281
|
+
setScreen(name) {
|
|
282
|
+
if (route?.name === name) return;
|
|
283
|
+
route = { name };
|
|
284
|
+
for (const listener of listeners) listener();
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// src/plugins/network.ts
|
|
290
|
+
var urlTemplate = (url) => url.split(/[?#]/)[0].replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]+/i, "").replace(
|
|
291
|
+
/\/(\d+|[0-9a-f]{8}-[0-9a-f-]{27,}|[0-9a-f]{16,})(?=\/|$)/gi,
|
|
292
|
+
"/:id"
|
|
293
|
+
) || "/";
|
|
294
|
+
function createNetworkPlugin(options = {}) {
|
|
295
|
+
const ignore = options.ignore ?? ((url) => url.includes("/symbolicate"));
|
|
296
|
+
return {
|
|
297
|
+
id: "network",
|
|
298
|
+
start({ recording, reportError }) {
|
|
299
|
+
let active = true;
|
|
300
|
+
const record = (method, url, startedAt, status, failure) => {
|
|
301
|
+
if (!active) return;
|
|
302
|
+
try {
|
|
303
|
+
recording.recordSpan({
|
|
304
|
+
name: `${method} ${urlTemplate(url)}`.slice(0, 200),
|
|
305
|
+
correlationId: "",
|
|
306
|
+
timestampMs: startedAt,
|
|
307
|
+
durationMs: Math.max(0, recording.getStats().nowMs - startedAt),
|
|
308
|
+
outcome: failure ?? (status === 0 || status >= 400 ? "error" : "success"),
|
|
309
|
+
attributes: [
|
|
310
|
+
{ key: "source", value: "network" },
|
|
311
|
+
{ key: "method", value: method },
|
|
312
|
+
{ key: "url", value: url.split(/[?#]/)[0].slice(0, 1024) },
|
|
313
|
+
{ key: "status", value: String(status) }
|
|
314
|
+
]
|
|
315
|
+
});
|
|
316
|
+
} catch (error) {
|
|
317
|
+
reportError(error);
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
const proto = (options.XMLHttpRequest ?? globalThis.XMLHttpRequest)?.prototype;
|
|
321
|
+
const open = proto?.open;
|
|
322
|
+
const send = proto?.send;
|
|
323
|
+
const requests = /* @__PURE__ */ new WeakMap();
|
|
324
|
+
const patchedOpen = function(method, url, ...rest) {
|
|
325
|
+
if (active && !ignore(String(url)))
|
|
326
|
+
requests.set(this, {
|
|
327
|
+
method: String(method).toUpperCase(),
|
|
328
|
+
url: String(url)
|
|
329
|
+
});
|
|
330
|
+
return open.call(
|
|
331
|
+
this,
|
|
332
|
+
method,
|
|
333
|
+
url,
|
|
334
|
+
...rest
|
|
335
|
+
);
|
|
336
|
+
};
|
|
337
|
+
const patchedSend = function(body) {
|
|
338
|
+
const request = requests.get(this);
|
|
339
|
+
if (active && request) {
|
|
340
|
+
try {
|
|
341
|
+
const startedAt = recording.getStats().nowMs;
|
|
342
|
+
let failure;
|
|
343
|
+
this.addEventListener("abort", () => failure = "cancelled");
|
|
344
|
+
this.addEventListener("timeout", () => failure = "error");
|
|
345
|
+
this.addEventListener("error", () => failure = "error");
|
|
346
|
+
this.addEventListener(
|
|
347
|
+
"loadend",
|
|
348
|
+
() => record(
|
|
349
|
+
request.method,
|
|
350
|
+
request.url,
|
|
351
|
+
startedAt,
|
|
352
|
+
this.status,
|
|
353
|
+
failure
|
|
354
|
+
)
|
|
355
|
+
);
|
|
356
|
+
} catch (error) {
|
|
357
|
+
reportError(error);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return send.call(this, body);
|
|
361
|
+
};
|
|
362
|
+
if (proto) {
|
|
363
|
+
proto.open = patchedOpen;
|
|
364
|
+
proto.send = patchedSend;
|
|
365
|
+
}
|
|
366
|
+
const host = options.fetchHost ?? globalThis;
|
|
367
|
+
const originalFetch = host.fetch;
|
|
368
|
+
const wrapFetch = typeof originalFetch === "function" && !originalFetch.polyfill;
|
|
369
|
+
const patchedFetch = async (input, init) => {
|
|
370
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
371
|
+
if (!active || ignore(url)) return originalFetch(input, init);
|
|
372
|
+
const method = String(
|
|
373
|
+
init?.method ?? (typeof input === "object" && "method" in input ? input.method : "GET")
|
|
374
|
+
).toUpperCase();
|
|
375
|
+
let startedAt = 0;
|
|
376
|
+
try {
|
|
377
|
+
startedAt = recording.getStats().nowMs;
|
|
378
|
+
} catch (error) {
|
|
379
|
+
reportError(error);
|
|
380
|
+
}
|
|
381
|
+
try {
|
|
382
|
+
const response = await originalFetch(input, init);
|
|
383
|
+
record(method, url, startedAt, response.status);
|
|
384
|
+
return response;
|
|
385
|
+
} catch (error) {
|
|
386
|
+
record(
|
|
387
|
+
method,
|
|
388
|
+
url,
|
|
389
|
+
startedAt,
|
|
390
|
+
0,
|
|
391
|
+
error?.name === "AbortError" ? "cancelled" : "error"
|
|
392
|
+
);
|
|
393
|
+
throw error;
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
if (wrapFetch) host.fetch = patchedFetch;
|
|
397
|
+
return {
|
|
398
|
+
stop() {
|
|
399
|
+
active = false;
|
|
400
|
+
if (proto && proto.open === patchedOpen)
|
|
401
|
+
proto.open = open;
|
|
402
|
+
if (proto && proto.send === patchedSend) proto.send = send;
|
|
403
|
+
if (wrapFetch && host.fetch === patchedFetch)
|
|
404
|
+
host.fetch = originalFetch;
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// src/plugins/errors.ts
|
|
412
|
+
var messageOf = (value) => value instanceof Error ? `${value.name}: ${value.message}` : String(value);
|
|
413
|
+
function createErrorsPlugin(options = {}) {
|
|
414
|
+
return {
|
|
415
|
+
id: "errors",
|
|
416
|
+
start({ recording, reportError }) {
|
|
417
|
+
const utils = options.errorUtils ?? globalThis.ErrorUtils;
|
|
418
|
+
let active = true;
|
|
419
|
+
let recordingError = false;
|
|
420
|
+
const record = (kind, message, fatal) => {
|
|
421
|
+
if (!active || recordingError) return;
|
|
422
|
+
recordingError = true;
|
|
423
|
+
try {
|
|
424
|
+
recording.mark({
|
|
425
|
+
name: "js.error",
|
|
426
|
+
correlationId: "",
|
|
427
|
+
attributes: [
|
|
428
|
+
{ key: "source", value: "error" },
|
|
429
|
+
{ key: "kind", value: kind },
|
|
430
|
+
{ key: "fatal", value: String(fatal) },
|
|
431
|
+
{ key: "message", value: message.slice(0, 1024) }
|
|
432
|
+
]
|
|
433
|
+
});
|
|
434
|
+
} catch (error) {
|
|
435
|
+
reportError(error);
|
|
436
|
+
} finally {
|
|
437
|
+
recordingError = false;
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
const previous = utils?.getGlobalHandler();
|
|
441
|
+
const handler = (error, isFatal) => {
|
|
442
|
+
record("global", messageOf(error), Boolean(isFatal));
|
|
443
|
+
previous?.(error, isFatal);
|
|
444
|
+
};
|
|
445
|
+
utils?.setGlobalHandler(handler);
|
|
446
|
+
const consoleError = console.error;
|
|
447
|
+
const patchedConsole = (...args) => {
|
|
448
|
+
record("console", args.map(messageOf).join(" "), false);
|
|
449
|
+
consoleError.apply(console, args);
|
|
450
|
+
};
|
|
451
|
+
if (options.console) console.error = patchedConsole;
|
|
452
|
+
return {
|
|
453
|
+
stop() {
|
|
454
|
+
active = false;
|
|
455
|
+
if (utils && previous && utils.getGlobalHandler() === handler)
|
|
456
|
+
utils.setGlobalHandler(previous);
|
|
457
|
+
if (console.error === patchedConsole) console.error = consoleError;
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// src/plugins/nativeMetrics.ts
|
|
465
|
+
function createNativeMetricsPlugin(options = {}) {
|
|
466
|
+
return {
|
|
467
|
+
id: "native-metrics",
|
|
468
|
+
start({ recording }) {
|
|
469
|
+
recording.startNativeSampling({
|
|
470
|
+
intervalMs: options.intervalMs ?? 1e3,
|
|
471
|
+
frames: options.frames ?? true
|
|
472
|
+
});
|
|
473
|
+
return { stop: () => recording.stopNativeSampling() };
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
//# sourceMappingURL=plugins.cjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../plugins.ts", "../../src/plugins/startPlugins.ts", "../../src/plugins/runtimeMetrics.ts", "../../src/plugins/navigation.ts", "../../src/plugins/network.ts", "../../src/plugins/errors.ts", "../../src/plugins/nativeMetrics.ts"],
|
|
4
|
+
"sourcesContent": ["export { startPlugins } from './src/plugins/startPlugins'\nexport type {\n TracePlugin,\n PluginContext,\n PluginHandle,\n} from './src/plugins/TracePlugin'\n\nexport { createRuntimeMetricsPlugin } from './src/plugins/runtimeMetrics'\nexport type { RuntimeMetricsOptions } from './src/plugins/runtimeMetrics'\n\nexport {\n createNavigationPlugin,\n createScreenTracker,\n} from './src/plugins/navigation'\nexport type {\n NavigationRefLike,\n NavigationPluginOptions,\n} from './src/plugins/navigation'\nexport { createNetworkPlugin, urlTemplate } from './src/plugins/network'\nexport type { NetworkPluginOptions } from './src/plugins/network'\nexport { createErrorsPlugin } from './src/plugins/errors'\nexport type { ErrorsPluginOptions, ErrorUtilsLike } from './src/plugins/errors'\nexport { createNativeMetricsPlugin } from './src/plugins/nativeMetrics'\nexport type { NativeMetricsOptions } from './src/plugins/nativeMetrics'\n", "import type { Recording } from '../specs/Recording.nitro'\nimport type { PluginHandle, TracePlugin } from './TracePlugin'\n/** Start optional integrations. Failures are isolated; stop waits for all cleanup. */\nexport function startPlugins(\n recording: Recording,\n plugins: readonly TracePlugin[],\n onError: (error: unknown) => void\n): PluginHandle {\n const handles: PluginHandle[] = []\n const ids = new Set<string>()\n for (const plugin of plugins) {\n if (ids.has(plugin.id))\n throw new Error(`Duplicate tracing plugin: ${plugin.id}`)\n ids.add(plugin.id)\n }\n const reportError = (error: unknown) => {\n try {\n onError(error)\n } catch {\n /* Error reporters cannot break capture. */\n }\n }\n for (const plugin of plugins) {\n try {\n handles.push(plugin.start({ recording, reportError }))\n } catch (error) {\n reportError(error)\n }\n }\n let stopping: Promise<void> | undefined\n return {\n stop() {\n if (!stopping)\n stopping = (async () => {\n for (const handle of [...handles].reverse()) {\n try {\n await handle.stop()\n } catch (error) {\n reportError(error)\n }\n }\n try {\n recording.stop()\n } catch (error) {\n reportError(error)\n }\n for (const handle of handles) {\n try {\n await handle.flush?.()\n } catch (error) {\n reportError(error)\n }\n }\n })()\n return stopping\n },\n }\n}\n", "import type { TracePlugin } from './TracePlugin'\nexport interface RuntimeMetricsOptions {\n /** Reporting interval in ms, minimum 250; default 1000. */\n intervalMs?: number\n /** Observe JS requestAnimationFrame callbacks (not native UI frames). Default true. */\n frames?: boolean\n}\n/** Injectable clock/lifecycle surface for deterministic tests and alternate hosts. */\nexport interface RuntimeMetricsHost {\n now(): number\n isActive(): boolean\n subscribe(listener: (active: boolean) => void): () => void\n requestFrame(callback: () => void): number\n cancelFrame(id: number): void\n}\nconst nativeHost = (): RuntimeMetricsHost => {\n const { AppState } = require('react-native') as typeof import('react-native')\n return {\n now: () => globalThis.performance.now(),\n isActive: () => AppState.currentState === 'active',\n subscribe: (listener) => {\n const subscription = AppState.addEventListener('change', (state) =>\n listener(state === 'active')\n )\n return () => subscription.remove()\n },\n requestFrame: (callback) => requestAnimationFrame(callback),\n cancelFrame: (id) => cancelAnimationFrame(id),\n }\n}\n/** Low-volume foreground JS health samples. No per-frame native calls or UI FPS claims. */\nexport function createRuntimeMetricsPlugin(\n options: RuntimeMetricsOptions = {},\n host?: RuntimeMetricsHost\n): TracePlugin {\n const interval = options.intervalMs ?? 1000\n if (!Number.isFinite(interval) || interval < 250)\n throw new Error('Runtime metrics interval must be at least 250ms')\n return {\n id: 'runtime-metrics',\n start({ recording, reportError }) {\n const api = host ?? nativeHost()\n let stopped = false\n let active = false\n let timer: ReturnType<typeof setTimeout> | undefined\n let frame: number | undefined\n let started = 0\n let previousFrame: number | undefined\n let frames = 0\n let maxGap = 0\n let longGaps = 0\n const reset = () => {\n started = api.now()\n frames = 0\n maxGap = 0\n longGaps = 0\n }\n const emit = (name: string, value: number, unit: string) => {\n try {\n recording.recordMetric({\n name,\n value,\n unit,\n correlationId: '',\n attributes: [\n { key: 'source', value: 'js-runtime' },\n { key: 'scope', value: 'foreground' },\n { key: 'windowMs', value: String(api.now() - started) },\n ],\n })\n } catch (error) {\n reportError(error)\n }\n }\n const onFrame = () => {\n if (stopped || !active) return\n const now = api.now()\n if (previousFrame !== undefined) {\n const gap = Math.max(0, now - previousFrame)\n maxGap = Math.max(maxGap, gap)\n if (gap > 50) longGaps++\n }\n previousFrame = now\n frames++\n frame = api.requestFrame(onFrame)\n }\n const tick = () => {\n if (stopped || !active) return\n const elapsed = api.now() - started\n emit('js.event_loop.delay', Math.max(0, elapsed - interval), 'ms')\n if (options.frames !== false && elapsed > 0) {\n emit(\n 'js.frame_callback.rate',\n (frames * 1000) / elapsed,\n 'callbacks/s'\n )\n if (frames > 1) emit('js.frame_gap.max', maxGap, 'ms')\n emit('js.frame_gap.over_50ms', longGaps, 'count')\n }\n reset()\n timer = setTimeout(tick, interval)\n }\n const suspend = () => {\n clearTimeout(timer)\n if (frame !== undefined) api.cancelFrame(frame)\n frame = undefined\n }\n const change = (next: boolean) => {\n if (stopped || next === active) return\n active = next\n previousFrame = undefined\n suspend()\n reset()\n if (active) {\n timer = setTimeout(tick, interval)\n if (options.frames !== false) frame = api.requestFrame(onFrame)\n }\n }\n const unsubscribe = api.subscribe(change)\n change(api.isActive())\n return {\n stop() {\n stopped = true\n active = false\n suspend()\n unsubscribe()\n },\n }\n },\n }\n}\n", "import type { TraceSpan } from '../specs/TraceSpan.nitro'\nimport type { TracePlugin } from './TracePlugin'\n/** Structural subset of a React Navigation container ref (expo-router: useNavigationContainerRef()). */\nexport interface NavigationRefLike {\n addListener(event: 'state' | 'ready', listener: () => void): () => void\n getCurrentRoute(): { name: string; key?: string } | undefined\n /** React Navigation logs an error when getCurrentRoute() runs before mount. */\n isReady?(): boolean\n}\nexport interface NavigationPluginOptions {\n /** Defaults to requestAnimationFrame. */\n requestFrame?: (callback: () => void) => unknown\n}\n/**\n * Per focused route: a `navigation.enter` mark, a `screen <name>` visit span (dwell time)\n * and a `navigation.transition` metric from state change to the second frame callback.\n * The transition is a render-opportunity estimate, not content readiness.\n */\nexport function createNavigationPlugin(\n ref: NavigationRefLike,\n options: NavigationPluginOptions = {}\n): TracePlugin {\n return {\n id: 'navigation',\n start({ recording, reportError }) {\n const requestFrame =\n options.requestFrame ??\n ((callback: () => void) => requestAnimationFrame(callback))\n let visit: TraceSpan | undefined\n let current: string | undefined\n let visits = 0\n let stopped = false\n const enter = () => {\n if (stopped) return\n try {\n if (ref.isReady?.() === false) return\n const route = ref.getCurrentRoute()\n const key = route && (route.key ?? route.name)\n if (!route || key === current) return\n current = key\n visit?.end('success')\n visit = undefined\n const correlationId = `screen:${++visits}`\n const attributes = [\n { key: 'source', value: 'navigation' },\n { key: 'screen', value: route.name.slice(0, 1024) },\n ]\n const startedAt = recording.getStats().nowMs\n recording.mark({\n name: 'navigation.enter',\n correlationId,\n attributes,\n })\n visit = recording.startSpan({\n name: `screen ${route.name}`.slice(0, 200),\n correlationId,\n attributes,\n })\n requestFrame(() =>\n requestFrame(() => {\n if (stopped) return\n try {\n recording.recordMetric({\n name: 'navigation.transition',\n value: recording.getStats().nowMs - startedAt,\n unit: 'ms',\n correlationId,\n attributes,\n })\n } catch (error) {\n reportError(error)\n }\n })\n )\n } catch (error) {\n reportError(error)\n }\n }\n // The initial route emits `ready`, not `state`; single-screen apps would record nothing.\n const unsubscribers = [\n ref.addListener('ready', enter),\n ref.addListener('state', enter),\n ]\n enter()\n return {\n stop() {\n stopped = true\n for (const unsubscribe of unsubscribers) unsubscribe()\n visit?.end('success')\n },\n }\n },\n }\n}\n/** For apps without React Navigation (custom tabs): pass to createNavigationPlugin, call setScreen on change. */\nexport function createScreenTracker(initial?: string) {\n let route = initial ? { name: initial } : undefined\n const listeners = new Set<() => void>()\n return {\n addListener(_event: 'state' | 'ready', listener: () => void) {\n listeners.add(listener)\n return () => void listeners.delete(listener)\n },\n getCurrentRoute: () => route,\n setScreen(name: string) {\n if (route?.name === name) return\n route = { name }\n for (const listener of listeners) listener()\n },\n }\n}\n", "import type { TracePlugin } from './TracePlugin'\ntype Fetch = typeof fetch\nexport interface NetworkPluginOptions {\n /** Defaults to the global XMLHttpRequest, which backs axios and React Native's polyfilled fetch. */\n XMLHttpRequest?: { prototype: XMLHttpRequest }\n /** Object whose `fetch` is wrapped. Defaults to globalThis. */\n fetchHost?: { fetch?: Fetch }\n /** Skip matching URLs. Defaults to Metro symbolication requests. */\n ignore?: (url: string) => boolean\n}\n/** Path without origin/query; numeric, UUID and long hex segments become `:id` so requests group. */\nexport const urlTemplate = (url: string) =>\n url\n .split(/[?#]/)[0]\n .replace(/^[a-z][a-z0-9+.-]*:\\/\\/[^/]+/i, '')\n .replace(\n /\\/(\\d+|[0-9a-f]{8}-[0-9a-f-]{27,}|[0-9a-f]{16,})(?=\\/|$)/gi,\n '/:id'\n ) || '/'\n/**\n * Opt-in request timing: method, URL without query, status and duration. Bodies and headers\n * are never read. XMLHttpRequest spans end at loadend; native fetch spans (expo/fetch,\n * nitro-fetch) end when response headers arrive, since reading bodies is left to the app.\n */\nexport function createNetworkPlugin(\n options: NetworkPluginOptions = {}\n): TracePlugin {\n const ignore =\n options.ignore ?? ((url: string) => url.includes('/symbolicate'))\n return {\n id: 'network',\n start({ recording, reportError }) {\n let active = true\n const record = (\n method: string,\n url: string,\n startedAt: number,\n status: number,\n failure?: 'cancelled' | 'error'\n ) => {\n if (!active) return\n try {\n recording.recordSpan({\n name: `${method} ${urlTemplate(url)}`.slice(0, 200),\n correlationId: '',\n timestampMs: startedAt,\n durationMs: Math.max(0, recording.getStats().nowMs - startedAt),\n outcome:\n failure ?? (status === 0 || status >= 400 ? 'error' : 'success'),\n attributes: [\n { key: 'source', value: 'network' },\n { key: 'method', value: method },\n { key: 'url', value: url.split(/[?#]/)[0].slice(0, 1024) },\n { key: 'status', value: String(status) },\n ],\n })\n } catch (error) {\n reportError(error)\n }\n }\n\n const proto = (options.XMLHttpRequest ?? globalThis.XMLHttpRequest)\n ?.prototype\n const open = proto?.open\n const send = proto?.send\n const requests = new WeakMap<\n XMLHttpRequest,\n { method: string; url: string }\n >()\n const patchedOpen = function (\n this: XMLHttpRequest,\n method: string,\n url: string | URL,\n ...rest: unknown[]\n ) {\n if (active && !ignore(String(url)))\n requests.set(this, {\n method: String(method).toUpperCase(),\n url: String(url),\n })\n return (open as (...args: unknown[]) => void).call(\n this,\n method,\n url,\n ...rest\n )\n }\n const patchedSend = function (\n this: XMLHttpRequest,\n body?: Document | XMLHttpRequestBodyInit | null\n ) {\n const request = requests.get(this)\n if (active && request) {\n try {\n const startedAt = recording.getStats().nowMs\n let failure: 'cancelled' | 'error' | undefined\n this.addEventListener('abort', () => (failure = 'cancelled'))\n this.addEventListener('timeout', () => (failure = 'error'))\n this.addEventListener('error', () => (failure = 'error'))\n this.addEventListener('loadend', () =>\n record(\n request.method,\n request.url,\n startedAt,\n this.status,\n failure\n )\n )\n } catch (error) {\n reportError(error)\n }\n }\n return send!.call(this, body)\n }\n if (proto) {\n proto.open = patchedOpen as typeof proto.open\n proto.send = patchedSend\n }\n\n // whatwg-fetch marks itself `polyfill` and already runs through the XHR hook above.\n const host = options.fetchHost ?? (globalThis as { fetch?: Fetch })\n const originalFetch = host.fetch\n const wrapFetch =\n typeof originalFetch === 'function' &&\n !(originalFetch as Fetch & { polyfill?: boolean }).polyfill\n const patchedFetch: Fetch = async (input, init) => {\n const url =\n typeof input === 'string'\n ? input\n : input instanceof URL\n ? input.href\n : input.url\n if (!active || ignore(url)) return originalFetch!(input, init)\n const method = String(\n init?.method ??\n (typeof input === 'object' && 'method' in input\n ? input.method\n : 'GET')\n ).toUpperCase()\n let startedAt = 0\n try {\n startedAt = recording.getStats().nowMs\n } catch (error) {\n reportError(error)\n }\n try {\n const response = await originalFetch!(input, init)\n record(method, url, startedAt, response.status)\n return response\n } catch (error) {\n record(\n method,\n url,\n startedAt,\n 0,\n (error as { name?: string })?.name === 'AbortError'\n ? 'cancelled'\n : 'error'\n )\n throw error\n }\n }\n if (wrapFetch) host.fetch = patchedFetch\n\n return {\n stop() {\n active = false\n // ponytail: if another library wrapped after us, leave our pass-through wrappers in place.\n if (proto && proto.open === (patchedOpen as unknown))\n proto.open = open!\n if (proto && proto.send === patchedSend) proto.send = send!\n if (wrapFetch && host.fetch === patchedFetch)\n host.fetch = originalFetch\n },\n }\n },\n }\n}\n", "import type { TracePlugin } from './TracePlugin'\ntype Handler = (error: unknown, isFatal?: boolean) => void\nexport interface ErrorUtilsLike {\n getGlobalHandler(): Handler\n setGlobalHandler(handler: Handler): void\n}\nexport interface ErrorsPluginOptions {\n /** Defaults to React Native's global ErrorUtils. */\n errorUtils?: ErrorUtilsLike\n /** Also record console.error calls. Default false; libraries log non-fatal noise there. */\n console?: boolean\n}\nconst messageOf = (value: unknown) =>\n value instanceof Error ? `${value.name}: ${value.message}` : String(value)\n/** Records uncaught JS errors as `js.error` marks, then calls the previous handler unchanged. */\nexport function createErrorsPlugin(\n options: ErrorsPluginOptions = {}\n): TracePlugin {\n return {\n id: 'errors',\n start({ recording, reportError }) {\n const utils =\n options.errorUtils ??\n (globalThis as unknown as { ErrorUtils?: ErrorUtilsLike }).ErrorUtils\n let active = true\n let recordingError = false\n const record = (kind: string, message: string, fatal: boolean) => {\n if (!active || recordingError) return\n recordingError = true\n try {\n recording.mark({\n name: 'js.error',\n correlationId: '',\n attributes: [\n { key: 'source', value: 'error' },\n { key: 'kind', value: kind },\n { key: 'fatal', value: String(fatal) },\n { key: 'message', value: message.slice(0, 1024) },\n ],\n })\n } catch (error) {\n reportError(error)\n } finally {\n recordingError = false\n }\n }\n const previous = utils?.getGlobalHandler()\n const handler: Handler = (error, isFatal) => {\n record('global', messageOf(error), Boolean(isFatal))\n previous?.(error, isFatal)\n }\n utils?.setGlobalHandler(handler)\n const consoleError = console.error\n const patchedConsole = (...args: unknown[]) => {\n record('console', args.map(messageOf).join(' '), false)\n consoleError.apply(console, args)\n }\n if (options.console) console.error = patchedConsole\n return {\n stop() {\n active = false\n if (utils && previous && utils.getGlobalHandler() === handler)\n utils.setGlobalHandler(previous)\n if (console.error === patchedConsole) console.error = consoleError\n },\n }\n },\n }\n}\n", "import type { TracePlugin } from './TracePlugin'\nexport interface NativeMetricsOptions {\n /** Metric window; 250\u201360000 ms. Default 1000. */\n intervalMs?: number\n /** Main-thread frame metrics (ui.fps, ui.frame_gap.max, ui.frames.slow/frozen). Default true. */\n frames?: boolean\n}\n/**\n * Native measurement layer: a sampler thread writes process.cpu, process.memory and\n * main-thread frame windows straight into the recording, with no per-frame JS work.\n * Alternative or complement to Sentry's measurements; each metric carries source=native.\n */\nexport function createNativeMetricsPlugin(\n options: NativeMetricsOptions = {}\n): TracePlugin {\n return {\n id: 'native-metrics',\n start({ recording }) {\n recording.startNativeSampling({\n intervalMs: options.intervalMs ?? 1000,\n frames: options.frames ?? true,\n })\n return { stop: () => recording.stopNativeSampling() }\n },\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|