@rozenite/performance-monitor-plugin 1.0.0-alpha.11
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/LICENSE +20 -0
- package/README.md +130 -0
- package/dist/App.html +31 -0
- package/dist/assets/App-C1ubeKf9.js +119 -0
- package/dist/assets/App-DRvEE1L4.css +1 -0
- package/dist/react-native.cjs +1 -0
- package/dist/react-native.d.ts +1 -0
- package/dist/react-native.js +5 -0
- package/dist/rozenite.config.d.ts +7 -0
- package/dist/rozenite.json +1 -0
- package/dist/src/react-native/asserts.d.ts +4 -0
- package/dist/src/react-native/helpers.d.ts +1 -0
- package/dist/src/react-native/performance-monitor.d.ts +8 -0
- package/dist/src/react-native/usePerformanceMonitorDevTools.d.ts +1 -0
- package/dist/src/shared/types.d.ts +39 -0
- package/dist/src/ui/App.d.ts +1 -0
- package/dist/src/ui/components/DataTable.d.ts +8 -0
- package/dist/src/ui/components/DetailsDisplay.d.ts +4 -0
- package/dist/src/ui/components/DetailsSidebar.d.ts +6 -0
- package/dist/src/ui/components/ExportModal.d.ts +9 -0
- package/dist/src/ui/components/JsonTree.d.ts +4 -0
- package/dist/src/ui/components/MarkDetails.d.ts +5 -0
- package/dist/src/ui/components/MarksTable.d.ts +6 -0
- package/dist/src/ui/components/MeasureDetails.d.ts +5 -0
- package/dist/src/ui/components/MeasuresTable.d.ts +6 -0
- package/dist/src/ui/components/MetricDetails.d.ts +5 -0
- package/dist/src/ui/components/MetricsTable.d.ts +6 -0
- package/dist/src/ui/components/SessionDuration.d.ts +5 -0
- package/dist/src/ui/utils.d.ts +2 -0
- package/dist/usePerformanceMonitorDevTools.cjs +1 -0
- package/dist/usePerformanceMonitorDevTools.js +118 -0
- package/package.json +41 -0
- package/project.json +12 -0
- package/react-native.ts +8 -0
- package/rozenite.config.ts +8 -0
- package/src/react-native/asserts.ts +29 -0
- package/src/react-native/helpers.ts +4 -0
- package/src/react-native/performance-monitor.ts +171 -0
- package/src/react-native/usePerformanceMonitorDevTools.ts +31 -0
- package/src/shared/types.ts +50 -0
- package/src/ui/App.css +97 -0
- package/src/ui/App.tsx +286 -0
- package/src/ui/components/DataTable.tsx +117 -0
- package/src/ui/components/DetailsDisplay.tsx +26 -0
- package/src/ui/components/DetailsSidebar.tsx +87 -0
- package/src/ui/components/ExportModal.tsx +278 -0
- package/src/ui/components/JsonTree.tsx +35 -0
- package/src/ui/components/MarkDetails.tsx +45 -0
- package/src/ui/components/MarksTable.tsx +42 -0
- package/src/ui/components/MeasureDetails.tsx +74 -0
- package/src/ui/components/MeasuresTable.tsx +72 -0
- package/src/ui/components/MetricDetails.tsx +56 -0
- package/src/ui/components/MetricsTable.tsx +54 -0
- package/src/ui/components/SessionDuration.tsx +54 -0
- package/src/ui/utils.ts +17 -0
- package/tsconfig.json +32 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vite.config.ts +20 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});exports.usePerformanceMonitorDevTools=void 0;process.env.NODE_ENV!=="production"?exports.usePerformanceMonitorDevTools=require("./usePerformanceMonitorDevTools.cjs").usePerformanceMonitorDevTools:exports.usePerformanceMonitorDevTools=()=>null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare let usePerformanceMonitorDevTools: typeof import('./src/react-native/usePerformanceMonitorDevTools').usePerformanceMonitorDevTools;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"name":"@rozenite/performance-monitor-plugin","version":"1.0.0-alpha.10","description":"Performance Monitor for Rozenite.","panels":[{"name":"Performance Monitor","source":"/App.html"}]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { PerformanceMark, PerformanceMeasure, PerformanceMetric } from 'react-native-performance';
|
|
2
|
+
export declare function assertPerformanceMark(entry: PerformanceEntry): asserts entry is PerformanceMark;
|
|
3
|
+
export declare function assertPerformanceMeasure(entry: PerformanceEntry): asserts entry is PerformanceMeasure;
|
|
4
|
+
export declare function assertPerformanceMetric(entry: PerformanceEntry): asserts entry is PerformanceMetric;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const toDateTimestamp: (origin: number, startTime: number) => number;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { PerformanceMonitorDevToolsClient } from '../shared/types';
|
|
2
|
+
export type PerformanceMonitor = {
|
|
3
|
+
enable: () => void;
|
|
4
|
+
disable: () => void;
|
|
5
|
+
isEnabled: () => boolean;
|
|
6
|
+
dispose: () => void;
|
|
7
|
+
};
|
|
8
|
+
export declare const getPerformanceMonitor: (client: PerformanceMonitorDevToolsClient) => PerformanceMonitor;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const usePerformanceMonitorDevTools: () => void;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { RozeniteDevToolsClient } from '@rozenite/plugin-bridge';
|
|
2
|
+
export type SharedPerformanceEntryProperties = {
|
|
3
|
+
name: string;
|
|
4
|
+
startTime: number;
|
|
5
|
+
duration: number;
|
|
6
|
+
};
|
|
7
|
+
export type SerializedPerformanceMeasure = SharedPerformanceEntryProperties & {
|
|
8
|
+
entryType: 'measure';
|
|
9
|
+
detail?: unknown;
|
|
10
|
+
};
|
|
11
|
+
export type SerializedPerformanceMark = SharedPerformanceEntryProperties & {
|
|
12
|
+
entryType: 'mark';
|
|
13
|
+
detail?: unknown;
|
|
14
|
+
};
|
|
15
|
+
export type SerializedPerformanceMetric = SharedPerformanceEntryProperties & {
|
|
16
|
+
entryType: 'metric';
|
|
17
|
+
value: string | number;
|
|
18
|
+
detail?: unknown;
|
|
19
|
+
};
|
|
20
|
+
export type SerializedPerformanceEntry = SerializedPerformanceMeasure | SerializedPerformanceMark | SerializedPerformanceMetric;
|
|
21
|
+
export type PerformanceMonitorEventMap = {
|
|
22
|
+
setEnabled: {
|
|
23
|
+
enabled: boolean;
|
|
24
|
+
};
|
|
25
|
+
setSession: {
|
|
26
|
+
sessionStartedAt: number;
|
|
27
|
+
timeOrigin: number;
|
|
28
|
+
};
|
|
29
|
+
appendMeasures: {
|
|
30
|
+
measures: SerializedPerformanceMeasure[];
|
|
31
|
+
};
|
|
32
|
+
appendMarks: {
|
|
33
|
+
marks: SerializedPerformanceMark[];
|
|
34
|
+
};
|
|
35
|
+
setMetrics: {
|
|
36
|
+
metrics: SerializedPerformanceMetric[];
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
export type PerformanceMonitorDevToolsClient = RozeniteDevToolsClient<PerformanceMonitorEventMap>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function PerformanceMonitorPanel(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ColumnDef } from '@tanstack/react-table';
|
|
2
|
+
export type DataTableProps<TData> = {
|
|
3
|
+
data: TData[];
|
|
4
|
+
columns: ColumnDef<TData>[];
|
|
5
|
+
onRowClick?: (item: TData) => void;
|
|
6
|
+
emptyMessage?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const DataTable: <TData>({ data, columns, onRowClick, emptyMessage, }: DataTableProps<TData>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SerializedPerformanceEntry } from '../../shared/types';
|
|
2
|
+
export type DetailsSidebarProps = {
|
|
3
|
+
selectedItem: SerializedPerformanceEntry | null;
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
};
|
|
6
|
+
export declare const DetailsSidebar: ({ selectedItem, onClose, }: DetailsSidebarProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SerializedPerformanceMeasure, SerializedPerformanceMark, SerializedPerformanceMetric } from '../../shared/types';
|
|
2
|
+
export type ExportModalProps = {
|
|
3
|
+
measures: SerializedPerformanceMeasure[];
|
|
4
|
+
metrics: SerializedPerformanceMetric[];
|
|
5
|
+
marks: SerializedPerformanceMark[];
|
|
6
|
+
sessionStartedAt: number;
|
|
7
|
+
clockShift: number;
|
|
8
|
+
};
|
|
9
|
+
export declare function ExportModal({ measures, metrics, marks, sessionStartedAt, clockShift, }: ExportModalProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SerializedPerformanceMark } from '../../shared/types';
|
|
2
|
+
export type MarksTableProps = {
|
|
3
|
+
marks: SerializedPerformanceMark[];
|
|
4
|
+
onRowClick?: (mark: SerializedPerformanceMark) => void;
|
|
5
|
+
};
|
|
6
|
+
export declare const MarksTable: ({ marks, onRowClick }: MarksTableProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SerializedPerformanceMeasure } from '../../shared/types';
|
|
2
|
+
export type MeasuresTableProps = {
|
|
3
|
+
measures: SerializedPerformanceMeasure[];
|
|
4
|
+
onRowClick?: (measure: SerializedPerformanceMeasure) => void;
|
|
5
|
+
};
|
|
6
|
+
export declare const MeasuresTable: ({ measures, onRowClick }: MeasuresTableProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SerializedPerformanceMetric } from '../../shared/types';
|
|
2
|
+
export type MetricsTableProps = {
|
|
3
|
+
metrics: SerializedPerformanceMetric[];
|
|
4
|
+
onRowClick?: (metric: SerializedPerformanceMetric) => void;
|
|
5
|
+
};
|
|
6
|
+
export declare const MetricsTable: ({ metrics, onRowClick }: MetricsTableProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const T=require("@rozenite/plugin-bridge"),g=require("react"),M=require("react-native-performance"),E=e=>e&&e.__esModule?e:{default:e},a=E(M),m=(e,s)=>e-a.default.timeOrigin+s;function v(e){if(e.entryType!=="mark")throw new Error("Entry is not a PerformanceMark")}function P(e){if(e.entryType!=="measure")throw new Error("Entry is not a PerformanceMeasure")}function k(e){if(e.entryType!=="metric")throw new Error("Entry is not a PerformanceMetric")}const w=e=>{let s=[],o=0,n=0,d=!1;const f=(i,l)=>{const u=new M.PerformanceObserver(i);u.observe(l),s.push(u)},b=()=>{d=!0,n=Date.now(),o=m(n,a.default.now()),e.send("setSession",{sessionStartedAt:o,timeOrigin:a.default.timeOrigin});const i=t=>{e.send("appendMeasures",{measures:t})},l=t=>{e.send("appendMarks",{marks:t})},u=t=>{e.send("setMetrics",{metrics:t})};f(t=>{const r=t.getEntries().map(c=>(v(c),{name:c.name,startTime:m(n,c.startTime),duration:c.duration,entryType:"mark"}));l(r)},{type:"mark",buffered:!0}),f(t=>{i(t.getEntries().map(r=>(P(r),{name:r.name,startTime:m(n,r.startTime),duration:r.duration,entryType:"measure",detail:r.detail})))},{type:"measure",buffered:!0}),f(t=>{u(t.getEntries().map(r=>(k(r),{name:r.name,startTime:m(n,r.startTime),duration:r.duration,entryType:"metric",value:r.value,detail:r.detail})))},{type:"metric",buffered:!0})},p=()=>{s.forEach(i=>{i.disconnect()}),a.default.clearMarks(),a.default.clearMeasures(),a.default.clearMetrics(),s=[],d=!1,o=0,n=0};return{enable:b,disable:p,isEnabled:()=>d,dispose:()=>{p()}}},y=()=>{const e=T.useRozeniteDevToolsClient({pluginId:"@rozenite/performance-monitor-plugin"});g.useEffect(()=>{if(!e)return;const s=w(e),o=e.onMessage("setEnabled",({enabled:n})=>{n?s.enable():s.disable()});return()=>{o.remove(),s.dispose()}},[e])};exports.usePerformanceMonitorDevTools=y;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { useRozeniteDevToolsClient as b } from "@rozenite/plugin-bridge";
|
|
2
|
+
import { useEffect as T } from "react";
|
|
3
|
+
import a, { PerformanceObserver as E } from "react-native-performance";
|
|
4
|
+
const u = (e, s) => e - a.timeOrigin + s;
|
|
5
|
+
function g(e) {
|
|
6
|
+
if (e.entryType !== "mark")
|
|
7
|
+
throw new Error("Entry is not a PerformanceMark");
|
|
8
|
+
}
|
|
9
|
+
function v(e) {
|
|
10
|
+
if (e.entryType !== "measure")
|
|
11
|
+
throw new Error("Entry is not a PerformanceMeasure");
|
|
12
|
+
}
|
|
13
|
+
function k(e) {
|
|
14
|
+
if (e.entryType !== "metric")
|
|
15
|
+
throw new Error("Entry is not a PerformanceMetric");
|
|
16
|
+
}
|
|
17
|
+
const w = (e) => {
|
|
18
|
+
let s = [], o = 0, n = 0, p = !1;
|
|
19
|
+
const d = (i, f) => {
|
|
20
|
+
const m = new E(i);
|
|
21
|
+
m.observe(f), s.push(m);
|
|
22
|
+
}, M = () => {
|
|
23
|
+
p = !0, n = Date.now(), o = u(n, a.now()), e.send("setSession", {
|
|
24
|
+
sessionStartedAt: o,
|
|
25
|
+
timeOrigin: a.timeOrigin
|
|
26
|
+
});
|
|
27
|
+
const i = (t) => {
|
|
28
|
+
e.send("appendMeasures", {
|
|
29
|
+
measures: t
|
|
30
|
+
});
|
|
31
|
+
}, f = (t) => {
|
|
32
|
+
e.send("appendMarks", {
|
|
33
|
+
marks: t
|
|
34
|
+
});
|
|
35
|
+
}, m = (t) => {
|
|
36
|
+
e.send("setMetrics", {
|
|
37
|
+
metrics: t
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
d(
|
|
41
|
+
(t) => {
|
|
42
|
+
const r = t.getEntries().map((c) => (g(c), {
|
|
43
|
+
name: c.name,
|
|
44
|
+
startTime: u(n, c.startTime),
|
|
45
|
+
duration: c.duration,
|
|
46
|
+
entryType: "mark"
|
|
47
|
+
}));
|
|
48
|
+
f(r);
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
type: "mark",
|
|
52
|
+
buffered: !0
|
|
53
|
+
}
|
|
54
|
+
), d(
|
|
55
|
+
(t) => {
|
|
56
|
+
i(
|
|
57
|
+
t.getEntries().map((r) => (v(r), {
|
|
58
|
+
name: r.name,
|
|
59
|
+
startTime: u(n, r.startTime),
|
|
60
|
+
duration: r.duration,
|
|
61
|
+
entryType: "measure",
|
|
62
|
+
detail: r.detail
|
|
63
|
+
}))
|
|
64
|
+
);
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
type: "measure",
|
|
68
|
+
buffered: !0
|
|
69
|
+
}
|
|
70
|
+
), d(
|
|
71
|
+
(t) => {
|
|
72
|
+
m(
|
|
73
|
+
t.getEntries().map((r) => (k(r), {
|
|
74
|
+
name: r.name,
|
|
75
|
+
startTime: u(n, r.startTime),
|
|
76
|
+
duration: r.duration,
|
|
77
|
+
entryType: "metric",
|
|
78
|
+
value: r.value,
|
|
79
|
+
detail: r.detail
|
|
80
|
+
}))
|
|
81
|
+
);
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
type: "metric",
|
|
85
|
+
buffered: !0
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
}, l = () => {
|
|
89
|
+
s.forEach((i) => {
|
|
90
|
+
i.disconnect();
|
|
91
|
+
}), a.clearMarks(), a.clearMeasures(), a.clearMetrics(), s = [], p = !1, o = 0, n = 0;
|
|
92
|
+
};
|
|
93
|
+
return {
|
|
94
|
+
enable: M,
|
|
95
|
+
disable: l,
|
|
96
|
+
isEnabled: () => p,
|
|
97
|
+
dispose: () => {
|
|
98
|
+
l();
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}, z = () => {
|
|
102
|
+
const e = b({
|
|
103
|
+
pluginId: "@rozenite/performance-monitor-plugin"
|
|
104
|
+
});
|
|
105
|
+
T(() => {
|
|
106
|
+
if (!e)
|
|
107
|
+
return;
|
|
108
|
+
const s = w(e), o = e.onMessage("setEnabled", ({ enabled: n }) => {
|
|
109
|
+
n ? s.enable() : s.disable();
|
|
110
|
+
});
|
|
111
|
+
return () => {
|
|
112
|
+
o.remove(), s.dispose();
|
|
113
|
+
};
|
|
114
|
+
}, [e]);
|
|
115
|
+
};
|
|
116
|
+
export {
|
|
117
|
+
z as usePerformanceMonitorDevTools
|
|
118
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rozenite/performance-monitor-plugin",
|
|
3
|
+
"version": "1.0.0-alpha.11",
|
|
4
|
+
"description": "Performance Monitor for Rozenite.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/react-native.cjs",
|
|
7
|
+
"module": "./dist/react-native.js",
|
|
8
|
+
"types": "./dist/react-native.d.ts",
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@rozenite/plugin-bridge": "1.0.0-alpha.11"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@radix-ui/react-icons": "^1.3.2",
|
|
14
|
+
"@radix-ui/react-separator": "^1.1.7",
|
|
15
|
+
"@radix-ui/react-tabs": "^1.1.12",
|
|
16
|
+
"@radix-ui/themes": "^3.2.1",
|
|
17
|
+
"@tanstack/react-table": "^8.21.3",
|
|
18
|
+
"react-virtuoso": "^4.6.0",
|
|
19
|
+
"@types/react": "~18.3.12",
|
|
20
|
+
"react": "18.3.1",
|
|
21
|
+
"react-dom": "18.3.0",
|
|
22
|
+
"react-json-tree": "^0.20.0",
|
|
23
|
+
"react-native": "0.76.0",
|
|
24
|
+
"react-native-performance": "5.1.4",
|
|
25
|
+
"react-native-web": "0.21.0",
|
|
26
|
+
"typescript": "^5.7.3",
|
|
27
|
+
"vite": "^6.0.0",
|
|
28
|
+
"@rozenite/vite-plugin": "1.0.0-alpha.11",
|
|
29
|
+
"rozenite": "1.0.0-alpha.11"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"react": "*",
|
|
33
|
+
"react-native": "*",
|
|
34
|
+
"react-native-performance": "*"
|
|
35
|
+
},
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "rozenite build",
|
|
39
|
+
"dev": "rozenite dev"
|
|
40
|
+
}
|
|
41
|
+
}
|
package/project.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
3
|
+
"name": "@rozenite/performance-monitor-plugin",
|
|
4
|
+
"targets": {
|
|
5
|
+
"build": {
|
|
6
|
+
"cache": true,
|
|
7
|
+
"dependsOn": ["^build"],
|
|
8
|
+
"inputs": ["{projectRoot}/src/**/*"],
|
|
9
|
+
"outputs": ["{projectRoot}/dist"]
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
package/react-native.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export let usePerformanceMonitorDevTools: typeof import('./src/react-native/usePerformanceMonitorDevTools').usePerformanceMonitorDevTools;
|
|
2
|
+
|
|
3
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4
|
+
usePerformanceMonitorDevTools =
|
|
5
|
+
require('./src/react-native/usePerformanceMonitorDevTools').usePerformanceMonitorDevTools;
|
|
6
|
+
} else {
|
|
7
|
+
usePerformanceMonitorDevTools = () => null;
|
|
8
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
PerformanceMark,
|
|
3
|
+
PerformanceMeasure,
|
|
4
|
+
PerformanceMetric,
|
|
5
|
+
} from 'react-native-performance';
|
|
6
|
+
|
|
7
|
+
export function assertPerformanceMark(
|
|
8
|
+
entry: PerformanceEntry
|
|
9
|
+
): asserts entry is PerformanceMark {
|
|
10
|
+
if (entry.entryType !== 'mark') {
|
|
11
|
+
throw new Error('Entry is not a PerformanceMark');
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function assertPerformanceMeasure(
|
|
16
|
+
entry: PerformanceEntry
|
|
17
|
+
): asserts entry is PerformanceMeasure {
|
|
18
|
+
if (entry.entryType !== 'measure') {
|
|
19
|
+
throw new Error('Entry is not a PerformanceMeasure');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function assertPerformanceMetric(
|
|
24
|
+
entry: PerformanceEntry
|
|
25
|
+
): asserts entry is PerformanceMetric {
|
|
26
|
+
if (entry.entryType !== 'metric') {
|
|
27
|
+
throw new Error('Entry is not a PerformanceMetric');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import performance, {
|
|
2
|
+
EntryType,
|
|
3
|
+
PerformanceEntry,
|
|
4
|
+
PerformanceObserver,
|
|
5
|
+
} from 'react-native-performance';
|
|
6
|
+
import type {
|
|
7
|
+
PerformanceMonitorDevToolsClient,
|
|
8
|
+
SerializedPerformanceMark,
|
|
9
|
+
SerializedPerformanceMeasure,
|
|
10
|
+
SerializedPerformanceMetric,
|
|
11
|
+
} from '../shared/types';
|
|
12
|
+
import { toDateTimestamp } from './helpers';
|
|
13
|
+
import {
|
|
14
|
+
assertPerformanceMark,
|
|
15
|
+
assertPerformanceMeasure,
|
|
16
|
+
assertPerformanceMetric,
|
|
17
|
+
} from './asserts';
|
|
18
|
+
|
|
19
|
+
type PerformanceObserverOptions = { type: EntryType; buffered?: boolean };
|
|
20
|
+
|
|
21
|
+
type PerformanceObserverEntryList = {
|
|
22
|
+
entries: PerformanceEntry[];
|
|
23
|
+
getEntries(): PerformanceEntry[];
|
|
24
|
+
getEntriesByType(type: EntryType): PerformanceEntry[];
|
|
25
|
+
getEntriesByName(name: string, type?: EntryType): PerformanceEntry[];
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type PerformanceObserverCallback = (
|
|
29
|
+
list: PerformanceObserverEntryList,
|
|
30
|
+
observer: PerformanceObserver
|
|
31
|
+
) => void;
|
|
32
|
+
|
|
33
|
+
export type PerformanceMonitor = {
|
|
34
|
+
enable: () => void;
|
|
35
|
+
disable: () => void;
|
|
36
|
+
isEnabled: () => boolean;
|
|
37
|
+
dispose: () => void;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const getPerformanceMonitor = (
|
|
41
|
+
client: PerformanceMonitorDevToolsClient
|
|
42
|
+
): PerformanceMonitor => {
|
|
43
|
+
let observers: PerformanceObserver[] = [];
|
|
44
|
+
let sessionStartedAt = 0;
|
|
45
|
+
let origin = 0;
|
|
46
|
+
let isObserving = false;
|
|
47
|
+
|
|
48
|
+
const addObserver = (
|
|
49
|
+
callback: PerformanceObserverCallback,
|
|
50
|
+
options: PerformanceObserverOptions
|
|
51
|
+
) => {
|
|
52
|
+
const observer = new PerformanceObserver(callback);
|
|
53
|
+
observer.observe(options);
|
|
54
|
+
observers.push(observer);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const enable = (): void => {
|
|
58
|
+
isObserving = true;
|
|
59
|
+
origin = Date.now();
|
|
60
|
+
sessionStartedAt = toDateTimestamp(origin, performance.now());
|
|
61
|
+
client.send('setSession', {
|
|
62
|
+
sessionStartedAt,
|
|
63
|
+
timeOrigin: performance.timeOrigin,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const appendMeasures = (measures: SerializedPerformanceMeasure[]) => {
|
|
67
|
+
client.send('appendMeasures', {
|
|
68
|
+
measures,
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const appendMarks = (marks: SerializedPerformanceMark[]) => {
|
|
73
|
+
client.send('appendMarks', {
|
|
74
|
+
marks,
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const setMetrics = (metrics: SerializedPerformanceMetric[]) => {
|
|
79
|
+
client.send('setMetrics', {
|
|
80
|
+
metrics,
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
addObserver(
|
|
85
|
+
(list) => {
|
|
86
|
+
const marks = list.getEntries().map((entry) => {
|
|
87
|
+
assertPerformanceMark(entry);
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
name: entry.name,
|
|
91
|
+
startTime: toDateTimestamp(origin, entry.startTime),
|
|
92
|
+
duration: entry.duration,
|
|
93
|
+
entryType: 'mark' as const,
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
appendMarks(marks);
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
type: 'mark',
|
|
101
|
+
buffered: true,
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
addObserver(
|
|
105
|
+
(list) => {
|
|
106
|
+
appendMeasures(
|
|
107
|
+
list.getEntries().map((entry) => {
|
|
108
|
+
assertPerformanceMeasure(entry);
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
name: entry.name,
|
|
112
|
+
startTime: toDateTimestamp(origin, entry.startTime),
|
|
113
|
+
duration: entry.duration,
|
|
114
|
+
entryType: 'measure' as const,
|
|
115
|
+
detail: entry.detail,
|
|
116
|
+
};
|
|
117
|
+
})
|
|
118
|
+
);
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
type: 'measure',
|
|
122
|
+
buffered: true,
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
addObserver(
|
|
126
|
+
(list) => {
|
|
127
|
+
setMetrics(
|
|
128
|
+
list.getEntries().map((entry) => {
|
|
129
|
+
assertPerformanceMetric(entry);
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
name: entry.name,
|
|
133
|
+
startTime: toDateTimestamp(origin, entry.startTime),
|
|
134
|
+
duration: entry.duration,
|
|
135
|
+
entryType: 'metric' as const,
|
|
136
|
+
value: entry.value,
|
|
137
|
+
detail: entry.detail,
|
|
138
|
+
};
|
|
139
|
+
})
|
|
140
|
+
);
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
type: 'metric',
|
|
144
|
+
buffered: true,
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
};
|
|
148
|
+
const disable = (): void => {
|
|
149
|
+
observers.forEach((observer) => {
|
|
150
|
+
observer.disconnect();
|
|
151
|
+
});
|
|
152
|
+
performance.clearMarks();
|
|
153
|
+
performance.clearMeasures();
|
|
154
|
+
performance.clearMetrics();
|
|
155
|
+
observers = [];
|
|
156
|
+
isObserving = false;
|
|
157
|
+
sessionStartedAt = 0;
|
|
158
|
+
origin = 0;
|
|
159
|
+
};
|
|
160
|
+
const isEnabled = (): boolean => isObserving;
|
|
161
|
+
const dispose = (): void => {
|
|
162
|
+
disable();
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
enable,
|
|
167
|
+
disable,
|
|
168
|
+
isEnabled,
|
|
169
|
+
dispose,
|
|
170
|
+
};
|
|
171
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useRozeniteDevToolsClient } from '@rozenite/plugin-bridge';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { getPerformanceMonitor } from './performance-monitor';
|
|
4
|
+
import { PerformanceMonitorEventMap } from '../shared/types';
|
|
5
|
+
|
|
6
|
+
export const usePerformanceMonitorDevTools = () => {
|
|
7
|
+
const client = useRozeniteDevToolsClient<PerformanceMonitorEventMap>({
|
|
8
|
+
pluginId: '@rozenite/performance-monitor-plugin',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (!client) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const performanceMonitor = getPerformanceMonitor(client);
|
|
17
|
+
|
|
18
|
+
const subscription = client.onMessage('setEnabled', ({ enabled }) => {
|
|
19
|
+
if (enabled) {
|
|
20
|
+
performanceMonitor.enable();
|
|
21
|
+
} else {
|
|
22
|
+
performanceMonitor.disable();
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
return () => {
|
|
27
|
+
subscription.remove();
|
|
28
|
+
performanceMonitor.dispose();
|
|
29
|
+
};
|
|
30
|
+
}, [client]);
|
|
31
|
+
};
|