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
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
First public release. In-app performance tracing for React Native, for development, custom and UAT builds.
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- **native:** bounded C++ recorder with a monotonic clock, explicit parent IDs, and source span IDs that link parents completing after their children.
|
|
10
|
+
- **native:** native sampler thread for UI fps, max frame gap, slow and frozen frames (CADisplayLink / Choreographer), process CPU and memory.
|
|
11
|
+
- **native:** `Recording.exportTraceEvents()` writes Chrome Trace Event / Perfetto JSON: a lane per source, instants for marks, and counters for metrics.
|
|
12
|
+
- **native:** metric samples may use at most half of the buffer and roll over within it, so long sessions keep their spans. Only lost spans and marks count as dropped history.
|
|
13
|
+
- **native:** stats split lost history by kind (`droppedSpans`, `droppedMarks`, `droppedMetrics`). The inspector says "Lost 12 spans, 3 marks" instead of a bare count.
|
|
14
|
+
- **client:** `createTraceClient` owns the recording lifecycle, plugins, the `trace` facade (`mark`, `metric`, `measure`, `measureSince`) and sharing.
|
|
15
|
+
- **client:** `shareTrace('perfetto')` shares a trace without stopping the recording.
|
|
16
|
+
- **client:** `flag(note?)` marks a problem and captures a bounded Hermes CPU profile (`flagProfileMs`, default 10 s). The profile is linked from the export.
|
|
17
|
+
- **client:** keeps 10000 events / 6 MB by default for multi-hour UAT sessions.
|
|
18
|
+
- **plugins:** collectors for native metrics, navigation and screens (`createScreenTracker` for custom tabs), network (XHR and native fetch), JS errors, runtime metrics and the Performance API.
|
|
19
|
+
- **plugins:** Sentry as an alternative measurement layer: frames and app start map onto the same metric names. Optional span export.
|
|
20
|
+
- **inspector:**
|
|
21
|
+
- Summary triages issues by topic: startup, screens, network, responsiveness, resources, errors.
|
|
22
|
+
- Timeline groups events by screen visit.
|
|
23
|
+
- Explore has search, sort and draft filters, with trace waterfalls.
|
|
24
|
+
- Metrics carry units.
|
|
25
|
+
- **inspector:** native tab bar with Liquid Glass and native menus on iOS; React Native fallbacks elsewhere. Labels are localizable in the package.
|
|
26
|
+
- **inspector:** live overlay with a draggable FPS bubble, a non-modal sheet for the current screen, and Flag and Share buttons.
|
|
27
|
+
- **example:** Instruments-style activity generators for screens, network, stalls and errors.
|
|
28
|
+
|
|
29
|
+
### Bug Fixes
|
|
30
|
+
|
|
31
|
+
- **native:** stopping a CPU profile really stops Hermes sampling on Android. React Native 0.85 binds `HermesSamplingProfiler.disable()` to the native enable, so `react-native-release-profiler`'s stop restarted the sampler. It then ran until the process died, and a dev reload aborted the app. `Tracing.disableHermesSampling()` stops it through the Hermes C++ API after every stop, and a ReactHost before-destroy guard stops it before reloads.
|
|
32
|
+
- **native:** armeabi-v7a builds compile (size_t narrowing).
|
|
33
|
+
- **inspector:** lists key rows by event sequence, so collectors that reuse a span ID cannot corrupt them.
|
|
34
|
+
- **inspector:** Android no longer crashes on AppCompat hosts: native tabs are iOS-only.
|
|
35
|
+
|
|
36
|
+
### Documentation
|
|
37
|
+
|
|
38
|
+
- Guides for getting started, collectors, inspector and overlay, exporting, native API, architecture, troubleshooting and releasing.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 gugell
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "NitroTracing"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => min_ios_version_supported, :visionos => 1.0 }
|
|
14
|
+
s.source = { :http => "https://registry.npmjs.org/#{package["name"]}/-/#{package["name"]}-#{s.version}.tgz" }
|
|
15
|
+
|
|
16
|
+
s.source_files = [
|
|
17
|
+
# Implementation (Swift)
|
|
18
|
+
"ios/**/*.{swift}",
|
|
19
|
+
# Autolinking/Registration (Objective-C++)
|
|
20
|
+
"ios/**/*.{m,mm}",
|
|
21
|
+
# Implementation (C++ objects)
|
|
22
|
+
"cpp/**/*.{hpp,cpp}",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
load 'nitrogen/generated/ios/NitroTracing+autolinking.rb'
|
|
26
|
+
add_nitrogen_files(s)
|
|
27
|
+
|
|
28
|
+
s.frameworks = 'QuartzCore'
|
|
29
|
+
s.dependency 'React-jsi'
|
|
30
|
+
s.dependency 'React-callinvoker'
|
|
31
|
+
install_modules_dependencies(s)
|
|
32
|
+
end
|
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# react-native-nitro-tracing
|
|
2
|
+
|
|
3
|
+
In-app performance tracing for React Native, for development, custom and UAT builds. It records spans, marks and metrics into a bounded C++ recorder. Native collectors measure frames, CPU and memory, and a live inspector runs inside the app. Recordings export to [Perfetto](https://ui.perfetto.dev).
|
|
4
|
+
|
|
5
|
+
Requires the New Architecture, Hermes and [`react-native-nitro-modules`](https://nitro.margelo.com) ^0.37.1, in a development or native build. Expo Go cannot load it.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npx expo install react-native-nitro-tracing react-native-nitro-modules
|
|
9
|
+
# inspector and overlay:
|
|
10
|
+
npx expo install react-native-safe-area-context @legendapp/list
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { createTraceClient } from 'react-native-nitro-tracing/client'
|
|
15
|
+
import { createExpoTraceSharing } from 'react-native-nitro-tracing/expo'
|
|
16
|
+
import {
|
|
17
|
+
createErrorsPlugin,
|
|
18
|
+
createNativeMetricsPlugin,
|
|
19
|
+
createNavigationPlugin,
|
|
20
|
+
createNetworkPlugin,
|
|
21
|
+
} from 'react-native-nitro-tracing/plugins'
|
|
22
|
+
|
|
23
|
+
export const tracing = createTraceClient({
|
|
24
|
+
...createExpoTraceSharing(),
|
|
25
|
+
runtimeMetrics: true,
|
|
26
|
+
plugins: [
|
|
27
|
+
createNativeMetricsPlugin(),
|
|
28
|
+
createNavigationPlugin(navigationRef),
|
|
29
|
+
createNetworkPlugin(),
|
|
30
|
+
createErrorsPlugin(),
|
|
31
|
+
],
|
|
32
|
+
})
|
|
33
|
+
await tracing.start()
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { TraceInspector, TraceOverlay } from 'react-native-nitro-tracing/react'
|
|
38
|
+
|
|
39
|
+
{
|
|
40
|
+
showTracing && (
|
|
41
|
+
<>
|
|
42
|
+
<TraceOverlay client={tracing} />
|
|
43
|
+
<TraceInspector client={tracing} />
|
|
44
|
+
</>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The package never gates itself on `__DEV__`; the app decides which builds include it. Tap **Flag** when something feels slow: it marks the moment and captures a CPU profile. **Share trace** sends a Perfetto file without stopping the recording.
|
|
50
|
+
|
|
51
|
+
## Entry points
|
|
52
|
+
|
|
53
|
+
| Import | Contains | Peers |
|
|
54
|
+
| --------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
55
|
+
| `react-native-nitro-tracing` | Native `Tracing` API | `react-native-nitro-modules` |
|
|
56
|
+
| `react-native-nitro-tracing/client` | `createTraceClient`: lifecycle, `trace` facade, share, flag | — |
|
|
57
|
+
| `react-native-nitro-tracing/plugins` | Native metrics, navigation, network, errors, runtime metrics, `TracePlugin` | — |
|
|
58
|
+
| `react-native-nitro-tracing/react` | `TraceInspector`, `TraceOverlay`, `useAppReadyMetric`, `defaultLabels` | `react-native-safe-area-context`, `@legendapp/list`; optional `react-native-bottom-tabs`, `expo-glass-effect` |
|
|
59
|
+
| `react-native-nitro-tracing/expo` | Share sheet adapter, dev menu item | `expo-file-system`, `expo-sharing`, `expo-dev-client` |
|
|
60
|
+
| `react-native-nitro-tracing/performance` | Performance API marks and measures | optional `react-native-performance` |
|
|
61
|
+
| `react-native-nitro-tracing/sentry` | Sentry as a measurement layer, and span export | `@sentry/react-native` |
|
|
62
|
+
| `react-native-nitro-tracing/release-profiler` | Hermes CPU profiles for Flag and Tools | `react-native-release-profiler` |
|
|
63
|
+
|
|
64
|
+
## Documentation
|
|
65
|
+
|
|
66
|
+
[Getting started](https://github.com/gugell/react-native-nitro-tracing/blob/main/docs/getting-started.md) ·
|
|
67
|
+
[Collectors](https://github.com/gugell/react-native-nitro-tracing/blob/main/docs/collectors.md) ·
|
|
68
|
+
[Inspector and overlay](https://github.com/gugell/react-native-nitro-tracing/blob/main/docs/inspector.md) ·
|
|
69
|
+
[Exporting traces](https://github.com/gugell/react-native-nitro-tracing/blob/main/docs/exporting.md) ·
|
|
70
|
+
[Native API](https://github.com/gugell/react-native-nitro-tracing/blob/main/docs/native-api.md) ·
|
|
71
|
+
[Architecture](https://github.com/gugell/react-native-nitro-tracing/blob/main/docs/architecture.md) ·
|
|
72
|
+
[Troubleshooting](https://github.com/gugell/react-native-nitro-tracing/blob/main/docs/troubleshooting.md) ·
|
|
73
|
+
[Changelog](https://github.com/gugell/react-native-nitro-tracing/blob/main/packages/react-native-nitro-tracing/CHANGELOG.md)
|
|
74
|
+
|
|
75
|
+
MIT
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
project(NitroTracing)
|
|
2
|
+
cmake_minimum_required(VERSION 3.9.0)
|
|
3
|
+
|
|
4
|
+
set (PACKAGE_NAME NitroTracing)
|
|
5
|
+
set (CMAKE_VERBOSE_MAKEFILE ON)
|
|
6
|
+
set (CMAKE_CXX_STANDARD 20)
|
|
7
|
+
|
|
8
|
+
# Define C++ library and add all sources
|
|
9
|
+
add_library(${PACKAGE_NAME} SHARED
|
|
10
|
+
src/main/cpp/cpp-adapter.cpp
|
|
11
|
+
../cpp/HybridTracing.cpp
|
|
12
|
+
../cpp/HybridRecording.cpp
|
|
13
|
+
../cpp/HybridTraceSpan.cpp
|
|
14
|
+
../cpp/HermesSampling.cpp
|
|
15
|
+
../cpp/NativeConversions.cpp
|
|
16
|
+
../cpp/core/Recorder.cpp
|
|
17
|
+
../cpp/core/Retention.cpp
|
|
18
|
+
../cpp/core/TraceJson.cpp
|
|
19
|
+
../cpp/core/NativeSampler.cpp
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Add Nitrogen specs :)
|
|
23
|
+
include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/NitroTracing+autolinking.cmake)
|
|
24
|
+
|
|
25
|
+
# Set up local includes
|
|
26
|
+
include_directories(
|
|
27
|
+
"src/main/cpp"
|
|
28
|
+
"../cpp"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
find_library(LOG_LIB log)
|
|
32
|
+
|
|
33
|
+
# Link all libraries together
|
|
34
|
+
target_link_libraries(
|
|
35
|
+
${PACKAGE_NAME}
|
|
36
|
+
${LOG_LIB}
|
|
37
|
+
android # <-- Android core
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Hermes C++ API, to stop the sampling profiler correctly (see cpp/HermesSampling.cpp).
|
|
41
|
+
# Optional: without Hermes the library builds and disableHermesSampling() returns false.
|
|
42
|
+
find_package(hermes-engine CONFIG)
|
|
43
|
+
if(TARGET hermes-engine::hermesvm)
|
|
44
|
+
target_link_libraries(${PACKAGE_NAME} hermes-engine::hermesvm)
|
|
45
|
+
target_compile_definitions(${PACKAGE_NAME} PRIVATE NITRO_TRACING_HERMES=1)
|
|
46
|
+
elseif(TARGET hermes-engine::libhermes)
|
|
47
|
+
target_link_libraries(${PACKAGE_NAME} hermes-engine::libhermes)
|
|
48
|
+
target_compile_definitions(${PACKAGE_NAME} PRIVATE NITRO_TRACING_HERMES=1)
|
|
49
|
+
endif()
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
repositories {
|
|
3
|
+
google()
|
|
4
|
+
mavenCentral()
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
dependencies {
|
|
8
|
+
classpath "com.android.tools.build:gradle:9.2.1"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
def reactNativeArchitectures() {
|
|
13
|
+
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
|
14
|
+
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def isNewArchitectureEnabled() {
|
|
18
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
apply plugin: "com.android.library"
|
|
22
|
+
apply plugin: 'org.jetbrains.kotlin.android'
|
|
23
|
+
apply from: '../nitrogen/generated/android/NitroTracing+autolinking.gradle'
|
|
24
|
+
apply from: "./fix-prefab.gradle"
|
|
25
|
+
|
|
26
|
+
def getExtOrDefault(name) {
|
|
27
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["NitroTracing_" + name]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
def getExtOrIntegerDefault(name) {
|
|
31
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["NitroTracing_" + name]).toInteger()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
android {
|
|
35
|
+
namespace "com.margelo.nitro.nitrotracing"
|
|
36
|
+
|
|
37
|
+
ndkVersion getExtOrDefault("ndkVersion")
|
|
38
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
39
|
+
|
|
40
|
+
defaultConfig {
|
|
41
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
42
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
43
|
+
consumerProguardFiles "proguard-rules.pro"
|
|
44
|
+
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
45
|
+
|
|
46
|
+
externalNativeBuild {
|
|
47
|
+
cmake {
|
|
48
|
+
cppFlags "-frtti -fexceptions -Wall -Wextra -fstack-protector-all"
|
|
49
|
+
arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
|
|
50
|
+
abiFilters (*reactNativeArchitectures())
|
|
51
|
+
|
|
52
|
+
buildTypes {
|
|
53
|
+
debug {
|
|
54
|
+
cppFlags "-O1 -g"
|
|
55
|
+
}
|
|
56
|
+
release {
|
|
57
|
+
cppFlags "-O2"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
externalNativeBuild {
|
|
65
|
+
cmake {
|
|
66
|
+
path "CMakeLists.txt"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
packagingOptions {
|
|
71
|
+
excludes = [
|
|
72
|
+
"META-INF",
|
|
73
|
+
"META-INF/**",
|
|
74
|
+
"**/libc++_shared.so",
|
|
75
|
+
"**/libNitroModules.so",
|
|
76
|
+
"**/libfbjni.so",
|
|
77
|
+
"**/libjsi.so",
|
|
78
|
+
"**/libfolly_json.so",
|
|
79
|
+
"**/libfolly_runtime.so",
|
|
80
|
+
"**/libglog.so",
|
|
81
|
+
"**/libhermes.so",
|
|
82
|
+
"**/libhermesvm.so",
|
|
83
|
+
"**/libhermes-executor-debug.so",
|
|
84
|
+
"**/libhermes_executor.so",
|
|
85
|
+
"**/libreactnative.so",
|
|
86
|
+
"**/libreactnativejni.so",
|
|
87
|
+
"**/libturbomodulejsijni.so",
|
|
88
|
+
"**/libreact_nativemodule_core.so",
|
|
89
|
+
"**/libjscexecutor.so"
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
buildFeatures {
|
|
94
|
+
buildConfig true
|
|
95
|
+
prefab true
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
buildTypes {
|
|
99
|
+
release {
|
|
100
|
+
minifyEnabled false
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
lintOptions {
|
|
105
|
+
disable "GradleCompatible"
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
compileOptions {
|
|
109
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
110
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
repositories {
|
|
116
|
+
mavenCentral()
|
|
117
|
+
google()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
dependencies {
|
|
122
|
+
// React Native is provided by the consuming app. Keeping this compileOnly
|
|
123
|
+
// prevents this library AAR from dexing RN classes a second time in release.
|
|
124
|
+
compileOnly "com.facebook.react:react-android"
|
|
125
|
+
|
|
126
|
+
// NitroModules is provided by the consuming app. Keeping this compileOnly
|
|
127
|
+
// avoids bundling NitroModules' runtime graph, including react-android, into
|
|
128
|
+
// this library AAR during release dexing.
|
|
129
|
+
compileOnly project(":react-native-nitro-modules")
|
|
130
|
+
|
|
131
|
+
// Hermes prefab headers and library, provided by the app at runtime.
|
|
132
|
+
compileOnly "com.facebook.react:hermes-android"
|
|
133
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
tasks.configureEach { task ->
|
|
2
|
+
// Make sure that we generate our prefab publication file only after having built the native library
|
|
3
|
+
// so that not a header publication file, but a full configuration publication will be generated, which
|
|
4
|
+
// will include the .so file
|
|
5
|
+
|
|
6
|
+
def prefabConfigurePattern = ~/^prefab(.+)ConfigurePackage$/
|
|
7
|
+
def matcher = task.name =~ prefabConfigurePattern
|
|
8
|
+
if (matcher.matches()) {
|
|
9
|
+
def variantName = matcher[0][1]
|
|
10
|
+
task.outputs.upToDateWhen { false }
|
|
11
|
+
task.dependsOn("externalNativeBuild${variantName}")
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
afterEvaluate {
|
|
16
|
+
def abis = reactNativeArchitectures()
|
|
17
|
+
rootProject.allprojects.each { proj ->
|
|
18
|
+
if (proj === rootProject) return
|
|
19
|
+
|
|
20
|
+
def dependsOnThisLib = proj.configurations.findAll { it.canBeResolved }.any { config ->
|
|
21
|
+
config.dependencies.any { dep ->
|
|
22
|
+
dep.group == project.group && dep.name == project.name
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (!dependsOnThisLib && proj != project) return
|
|
26
|
+
|
|
27
|
+
if (!proj.plugins.hasPlugin('com.android.application') && !proj.plugins.hasPlugin('com.android.library')) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
def variants = proj.android.hasProperty('applicationVariants') ? proj.android.applicationVariants : proj.android.libraryVariants
|
|
32
|
+
// Touch the prefab_config.json files to ensure that in ExternalNativeJsonGenerator.kt we will re-trigger the prefab CLI to
|
|
33
|
+
// generate a libnameConfig.cmake file that will contain our native library (.so).
|
|
34
|
+
// See this condition: https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExternalNativeJsonGenerator.kt;l=207-219?q=createPrefabBuildSystemGlue
|
|
35
|
+
variants.all { variant ->
|
|
36
|
+
def variantName = variant.name
|
|
37
|
+
abis.each { abi ->
|
|
38
|
+
def searchDir = new File(proj.projectDir, ".cxx/${variantName}")
|
|
39
|
+
if (!searchDir.exists()) return
|
|
40
|
+
def matches = []
|
|
41
|
+
searchDir.eachDir { randomDir ->
|
|
42
|
+
def prefabFile = new File(randomDir, "${abi}/prefab_config.json")
|
|
43
|
+
if (prefabFile.exists()) matches << prefabFile
|
|
44
|
+
}
|
|
45
|
+
matches.each { prefabConfig ->
|
|
46
|
+
prefabConfig.setLastModified(System.currentTimeMillis())
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Called only from C++ over JNI; keep it through R8 in release builds.
|
|
2
|
+
-keep class com.margelo.nitro.nitrotracing.NitroTracingFrameSource { *; }
|
|
3
|
+
# Reload guard: instantiated from ReactModuleInfo by class name; its JNI bridge is native.
|
|
4
|
+
-keep class com.margelo.nitro.nitrotracing.HermesSamplingGuard { *; }
|
|
5
|
+
-keep class com.margelo.nitro.nitrotracing.HermesSampling { *; }
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#include "HermesSampling.hpp"
|
|
2
|
+
#include "NitroTracingOnLoad.hpp"
|
|
3
|
+
#include "core/NativeSampler.hpp"
|
|
4
|
+
#include <fbjni/fbjni.h>
|
|
5
|
+
#include <jni.h>
|
|
6
|
+
|
|
7
|
+
using margelo::nitro::tracingcore::FrameMonitor;
|
|
8
|
+
|
|
9
|
+
namespace {
|
|
10
|
+
// Resolved on the loader thread: FindClass from other threads cannot see app classes.
|
|
11
|
+
jclass frameSourceClass = nullptr;
|
|
12
|
+
jmethodID setEnabled = nullptr;
|
|
13
|
+
|
|
14
|
+
void registerFrameSource(JNIEnv *env) {
|
|
15
|
+
jclass local = env->FindClass("com/margelo/nitro/nitrotracing/NitroTracingFrameSource");
|
|
16
|
+
if (!local) {
|
|
17
|
+
env->ExceptionClear();
|
|
18
|
+
return; // Frame metrics are optional; CPU and memory sampling still work.
|
|
19
|
+
}
|
|
20
|
+
frameSourceClass = static_cast<jclass>(env->NewGlobalRef(local));
|
|
21
|
+
env->DeleteLocalRef(local);
|
|
22
|
+
setEnabled = env->GetStaticMethodID(frameSourceClass, "setEnabled", "(Z)V");
|
|
23
|
+
FrameMonitor::instance().setToggle([](bool enabled) {
|
|
24
|
+
JNIEnv *env = facebook::jni::Environment::ensureCurrentThreadIsAttached();
|
|
25
|
+
env->CallStaticVoidMethod(frameSourceClass, setEnabled, static_cast<jboolean>(enabled));
|
|
26
|
+
if (env->ExceptionCheck())
|
|
27
|
+
env->ExceptionClear();
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
} // namespace
|
|
31
|
+
|
|
32
|
+
extern "C" JNIEXPORT void JNICALL
|
|
33
|
+
Java_com_margelo_nitro_nitrotracing_NitroTracingFrameSource_nativeOnFrame(JNIEnv *, jclass, jlong frameTimeNanos) {
|
|
34
|
+
// Choreographer frame times share the monotonic clock; 0 lets the monitor infer the interval.
|
|
35
|
+
FrameMonitor::instance().onFrame(static_cast<double>(frameTimeNanos) / 1e9, 0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
extern "C" JNIEXPORT jboolean JNICALL Java_com_margelo_nitro_nitrotracing_HermesSampling_disable(JNIEnv *, jclass) {
|
|
39
|
+
return margelo::nitro::nitrotracing::disableHermesSampling() ? JNI_TRUE : JNI_FALSE;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
|
|
43
|
+
return facebook::jni::initialize(vm, [] {
|
|
44
|
+
margelo::nitro::nitrotracing::registerAllNatives();
|
|
45
|
+
registerFrameSource(facebook::jni::Environment::current());
|
|
46
|
+
});
|
|
47
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
package com.margelo.nitro.nitrotracing
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactApplication
|
|
4
|
+
import com.facebook.react.ReactHost
|
|
5
|
+
import com.facebook.react.bridge.BaseJavaModule
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
|
+
import com.facebook.react.turbomodule.core.interfaces.TurboModule
|
|
8
|
+
import java.util.Collections
|
|
9
|
+
import java.util.WeakHashMap
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Stops Hermes' sampling profiler before a reload tears down the JS runtime.
|
|
13
|
+
*
|
|
14
|
+
* The sampler is process-wide. If a reload destroys the JS thread while it samples, the
|
|
15
|
+
* sampler signals a dead thread and the app aborts (`invalid pthread_t` on `hermes-sampling`).
|
|
16
|
+
* React Native quits the JS thread before invalidating modules, so this registers a
|
|
17
|
+
* ReactHost before-destroy listener, which runs while the thread is still alive.
|
|
18
|
+
* Eagerly initialized; JS never calls it.
|
|
19
|
+
*/
|
|
20
|
+
internal class HermesSamplingGuard(context: ReactApplicationContext) :
|
|
21
|
+
BaseJavaModule(context), TurboModule {
|
|
22
|
+
init {
|
|
23
|
+
(context.applicationContext as? ReactApplication)?.reactHost?.let(::watch)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
override fun getName() = NAME
|
|
27
|
+
|
|
28
|
+
companion object {
|
|
29
|
+
const val NAME = "NitroTracingHermesSamplingGuard"
|
|
30
|
+
// One listener per host; a new module instance is created on every reload.
|
|
31
|
+
private val watched = Collections.newSetFromMap(WeakHashMap<ReactHost, Boolean>())
|
|
32
|
+
|
|
33
|
+
private fun watch(host: ReactHost) {
|
|
34
|
+
synchronized(watched) { if (!watched.add(host)) return }
|
|
35
|
+
host.addBeforeDestroyListener { runCatching { HermesSampling.disable() } }
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** JNI bridge to cpp/HermesSampling.cpp. */
|
|
41
|
+
internal object HermesSampling {
|
|
42
|
+
@JvmStatic external fun disable(): Boolean
|
|
43
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
package com.margelo.nitro.nitrotracing
|
|
2
|
+
|
|
3
|
+
import android.os.Handler
|
|
4
|
+
import android.os.Looper
|
|
5
|
+
import android.view.Choreographer
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Main-thread Choreographer callbacks, started only while a native sampler needs frames.
|
|
9
|
+
* A callback delayed past its vsync means the main thread was busy; the C++ FrameMonitor
|
|
10
|
+
* infers the display interval from the shortest recent gap.
|
|
11
|
+
*/
|
|
12
|
+
object NitroTracingFrameSource : Choreographer.FrameCallback {
|
|
13
|
+
private val main = Handler(Looper.getMainLooper())
|
|
14
|
+
private var running = false
|
|
15
|
+
|
|
16
|
+
@JvmStatic
|
|
17
|
+
fun setEnabled(enabled: Boolean) {
|
|
18
|
+
main.post {
|
|
19
|
+
if (enabled && !running) {
|
|
20
|
+
running = true
|
|
21
|
+
Choreographer.getInstance().postFrameCallback(this)
|
|
22
|
+
} else if (!enabled && running) {
|
|
23
|
+
running = false
|
|
24
|
+
Choreographer.getInstance().removeFrameCallback(this)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
override fun doFrame(frameTimeNanos: Long) {
|
|
30
|
+
if (!running) return
|
|
31
|
+
nativeOnFrame(frameTimeNanos)
|
|
32
|
+
Choreographer.getInstance().postFrameCallback(this)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@JvmStatic private external fun nativeOnFrame(frameTimeNanos: Long)
|
|
36
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
package com.margelo.nitro.nitrotracing
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
|
+
|
|
9
|
+
class NitroTracingPackage : BaseReactPackage() {
|
|
10
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? =
|
|
11
|
+
if (name == HermesSamplingGuard.NAME) HermesSamplingGuard(reactContext) else null
|
|
12
|
+
|
|
13
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider = ReactModuleInfoProvider {
|
|
14
|
+
mapOf(
|
|
15
|
+
HermesSamplingGuard.NAME to ReactModuleInfo(
|
|
16
|
+
HermesSamplingGuard.NAME,
|
|
17
|
+
HermesSamplingGuard::class.java.name,
|
|
18
|
+
false, // canOverrideExistingModule
|
|
19
|
+
true, // needsEagerInit: registers the reload guard at startup
|
|
20
|
+
false, // isCxxModule
|
|
21
|
+
true, // isTurboModule
|
|
22
|
+
),
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
companion object {
|
|
27
|
+
init {
|
|
28
|
+
NitroTracingOnLoad.initializeNative()
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
package/client.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { createTraceClient } from './src/client/createTraceClient'
|
|
2
|
+
export type {
|
|
3
|
+
TraceClient,
|
|
4
|
+
TraceClientOptions,
|
|
5
|
+
TraceClientSnapshot,
|
|
6
|
+
ClientAttributes,
|
|
7
|
+
TraceFormat,
|
|
8
|
+
} from './src/client/createTraceClient'
|
|
9
|
+
|
|
10
|
+
export type {
|
|
11
|
+
PlaygroundReport,
|
|
12
|
+
PlaygroundCheckId,
|
|
13
|
+
} from './src/client/playground'
|
|
14
|
+
|
|
15
|
+
export type { TracingEntry, TracingSink } from './src/client/TracingSink'
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#include "HermesSampling.hpp"
|
|
2
|
+
|
|
3
|
+
#if defined(NITRO_TRACING_HERMES)
|
|
4
|
+
#include <hermes/hermes.h>
|
|
5
|
+
#endif
|
|
6
|
+
|
|
7
|
+
namespace margelo::nitro::nitrotracing {
|
|
8
|
+
bool disableHermesSampling() noexcept {
|
|
9
|
+
#if defined(NITRO_TRACING_HERMES)
|
|
10
|
+
// React Native 0.85's HermesSamplingProfiler binds its Java disable() to the native
|
|
11
|
+
// enable(), so on Android "stop profiling" leaves the sampler running. This is the call
|
|
12
|
+
// the binding should have made.
|
|
13
|
+
try {
|
|
14
|
+
auto *api = facebook::jsi::castInterface<facebook::hermes::IHermesRootAPI>(facebook::hermes::makeHermesRootAPI());
|
|
15
|
+
if (api == nullptr)
|
|
16
|
+
return false;
|
|
17
|
+
api->disableSamplingProfiler();
|
|
18
|
+
return true;
|
|
19
|
+
} catch (...) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
#else
|
|
23
|
+
return false;
|
|
24
|
+
#endif
|
|
25
|
+
}
|
|
26
|
+
} // namespace margelo::nitro::nitrotracing
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
namespace margelo::nitro::nitrotracing {
|
|
4
|
+
/**
|
|
5
|
+
* Stops Hermes' process-wide sampling profiler through the Hermes C++ API.
|
|
6
|
+
* Returns false when this build does not link Hermes (the iOS build, where the
|
|
7
|
+
* profiler's own stop works) or when Hermes refuses the call.
|
|
8
|
+
*/
|
|
9
|
+
bool disableHermesSampling() noexcept;
|
|
10
|
+
} // namespace margelo::nitro::nitrotracing
|