react-render-pulse 0.0.0-stage → 1.0.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/LICENSE +21 -0
- package/README.md +97 -2
- package/dist/aggregate/aggregator.d.cts +27 -0
- package/dist/aggregate/aggregator.d.ts +28 -0
- package/dist/aggregate/aggregator.d.ts.map +1 -0
- package/dist/aggregate/histogram.d.cts +18 -0
- package/dist/aggregate/histogram.d.ts +19 -0
- package/dist/aggregate/histogram.d.ts.map +1 -0
- package/dist/components/RenderMonitor.d.cts +19 -0
- package/dist/components/RenderMonitor.d.ts +20 -0
- package/dist/components/RenderMonitor.d.ts.map +1 -0
- package/dist/context/device.d.cts +2 -0
- package/dist/context/device.d.ts +3 -0
- package/dist/context/device.d.ts.map +1 -0
- package/dist/context/route.d.cts +7 -0
- package/dist/context/route.d.ts +8 -0
- package/dist/context/route.d.ts.map +1 -0
- package/dist/core.cjs +56 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +2 -0
- package/dist/core.d.ts +3 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +28 -0
- package/dist/core.js.map +1 -0
- package/dist/export/console.d.cts +3 -0
- package/dist/export/console.d.ts +4 -0
- package/dist/export/console.d.ts.map +1 -0
- package/dist/export/otel.d.cts +34 -0
- package/dist/export/otel.d.ts +35 -0
- package/dist/export/otel.d.ts.map +1 -0
- package/dist/hooks/useRenderMonitor.d.cts +9 -0
- package/dist/hooks/useRenderMonitor.d.ts +10 -0
- package/dist/hooks/useRenderMonitor.d.ts.map +1 -0
- package/dist/index.cjs +634 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +602 -0
- package/dist/index.js.map +1 -0
- package/dist/modes/detect.d.cts +16 -0
- package/dist/modes/detect.d.ts +17 -0
- package/dist/modes/detect.d.ts.map +1 -0
- package/dist/observe/longtasks.d.cts +12 -0
- package/dist/observe/longtasks.d.ts +13 -0
- package/dist/observe/longtasks.d.ts.map +1 -0
- package/dist/observe/renderWindows.d.cts +17 -0
- package/dist/observe/renderWindows.d.ts +18 -0
- package/dist/observe/renderWindows.d.ts.map +1 -0
- package/dist/otel.cjs +65 -0
- package/dist/otel.cjs.map +1 -0
- package/dist/otel.d.cts +2 -0
- package/dist/otel.d.ts +3 -0
- package/dist/otel.d.ts.map +1 -0
- package/dist/otel.js +38 -0
- package/dist/otel.js.map +1 -0
- package/dist/runtime/guard.d.cts +7 -0
- package/dist/runtime/guard.d.ts +8 -0
- package/dist/runtime/guard.d.ts.map +1 -0
- package/dist/runtime/initRenderPulse.d.cts +44 -0
- package/dist/runtime/initRenderPulse.d.ts +45 -0
- package/dist/runtime/initRenderPulse.d.ts.map +1 -0
- package/dist/runtime/runtime.d.cts +13 -0
- package/dist/runtime/runtime.d.ts +14 -0
- package/dist/runtime/runtime.d.ts.map +1 -0
- package/dist/runtime/useIsomorphicLayoutEffect.d.cts +2 -0
- package/dist/runtime/useIsomorphicLayoutEffect.d.ts +3 -0
- package/dist/runtime/useIsomorphicLayoutEffect.d.ts.map +1 -0
- package/dist/sample/sample.d.cts +7 -0
- package/dist/sample/sample.d.ts +8 -0
- package/dist/sample/sample.d.ts.map +1 -0
- package/dist/transport/payload.d.cts +8 -0
- package/dist/transport/payload.d.ts +9 -0
- package/dist/transport/payload.d.ts.map +1 -0
- package/dist/transport/transport.d.cts +18 -0
- package/dist/transport/transport.d.ts +19 -0
- package/dist/transport/transport.d.ts.map +1 -0
- package/dist/types.d.cts +120 -0
- package/dist/types.d.ts +121 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +128 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Amal M
|
|
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.
|
package/README.md
CHANGED
|
@@ -1,3 +1,98 @@
|
|
|
1
|
-
#
|
|
1
|
+
# react-render-pulse
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/react-render-pulse)
|
|
4
|
+
[](https://github.com/Amalmktk/react-render-pulse/actions/workflows/ci.yml)
|
|
5
|
+
[](https://github.com/Amalmktk/react-render-pulse/blob/main/LICENSE)
|
|
6
|
+
|
|
7
|
+
Real-user render performance monitoring for React, at the component level. Wrap the parts of your tree you care about and get render timings from real sessions: render counts, slow renders, p50/p75/p95 and the slowest renders per area and route, plus long tasks attributed to the area that was rendering.
|
|
8
|
+
|
|
9
|
+
Under 3.75 kB brotli. No runtime dependencies besides React 18 or 19.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install react-render-pulse
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
Start it once, in the browser, before your app renders:
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { createRoot } from "react-dom/client";
|
|
23
|
+
import { initRenderPulse } from "react-render-pulse";
|
|
24
|
+
import { App } from "./App";
|
|
25
|
+
|
|
26
|
+
initRenderPulse({
|
|
27
|
+
endpoint: "/api/render-pulse", // leave out to log batches to the console
|
|
28
|
+
sampleRate: 0.1, // 10% of page loads
|
|
29
|
+
appVersion: import.meta.env.VITE_APP_VERSION,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
createRoot(document.getElementById("root")!).render(<App />);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Wrap areas you want timings for:
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { RenderMonitor, useRenderMonitor } from "react-render-pulse";
|
|
39
|
+
|
|
40
|
+
export function OrdersPage() {
|
|
41
|
+
return (
|
|
42
|
+
<RenderMonitor id="orders-table">
|
|
43
|
+
<OrdersTable />
|
|
44
|
+
</RenderMonitor>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function PriceChart() {
|
|
49
|
+
useRenderMonitor("price-chart"); // exact render count; duration is an upper bound
|
|
50
|
+
return <Chart />;
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`<RenderMonitor>` adds no DOM elements and never remounts its children. Errors inside the package never reach your app.
|
|
55
|
+
|
|
56
|
+
Batches are sent when the page is hidden and every 3 minutes while it's visible. Send them to [`react-render-pulse-collector`](https://www.npmjs.com/package/react-render-pulse-collector) and read them with [`react-render-pulse-viewer`](https://www.npmjs.com/package/react-render-pulse-viewer).
|
|
57
|
+
|
|
58
|
+
## Key options
|
|
59
|
+
|
|
60
|
+
| Option | Default | Description |
|
|
61
|
+
| --- | --- | --- |
|
|
62
|
+
| `endpoint` | none | Where batches are `POST`ed. Without one, batches are logged to the console. |
|
|
63
|
+
| `sampleRate` | `1` | Fraction of page loads that collect anything. |
|
|
64
|
+
| `mode` | `"auto"` | `"lightweight"`, `"profiling"`, or `"auto"`: lightweight until React's profiling build is detected. |
|
|
65
|
+
| `slowRenderMs` | `16` | Renders slower than this count as slow. |
|
|
66
|
+
| `longTaskMs` | `50` | Shorter long tasks and long animation frames are ignored. |
|
|
67
|
+
| `appVersion` | none | Your app's version, for comparing releases. |
|
|
68
|
+
| `getRoute` | numeric path segments → `:id` | Returns the current route template, e.g. `/orders/:id`. |
|
|
69
|
+
| `exporters` | `[]` | Extra receivers, e.g. `createOtelExporter` from `react-render-pulse/otel`. |
|
|
70
|
+
|
|
71
|
+
All options: [client API reference](https://github.com/Amalmktk/react-render-pulse/blob/main/docs/api/client.md).
|
|
72
|
+
|
|
73
|
+
## Modes
|
|
74
|
+
|
|
75
|
+
- **Lightweight** (any production build): times each area between two marker components. About 10–15 µs per measured render. Doesn't see updates that start inside the area.
|
|
76
|
+
- **Profiling** (React's profiling build): React's `<Profiler>` timings for every commit. Exact, but the profiling build itself costs more; use it for a sampled group.
|
|
77
|
+
|
|
78
|
+
Enable the profiling build by aliasing `react-dom/client` to `react-dom/profiling` (Vite) or with `next build --profile`. See [Modes](https://github.com/Amalmktk/react-render-pulse/blob/main/docs/guide/modes.md).
|
|
79
|
+
|
|
80
|
+
## Entry points
|
|
81
|
+
|
|
82
|
+
| Import | Contents |
|
|
83
|
+
| --- | --- |
|
|
84
|
+
| `react-render-pulse` | `initRenderPulse`, `RenderMonitor`, `useRenderMonitor`, `createConsoleExporter`, types. Marked `"use client"`. |
|
|
85
|
+
| `react-render-pulse/core` | Types, `HISTOGRAM_BOUNDS`, `histogramPercentile`. No React; safe on servers. |
|
|
86
|
+
| `react-render-pulse/otel` | `createOtelExporter`, for OpenTelemetry metrics. |
|
|
87
|
+
|
|
88
|
+
## Privacy
|
|
89
|
+
|
|
90
|
+
No user IDs, IP addresses, page text, input values or query strings. The session id is random per page load and never stored. Routes come from `location.pathname`; numeric segments are replaced by default, but pass a `getRoute` if paths can contain names, slugs or UUIDs. See [What we collect](https://github.com/Amalmktk/react-render-pulse/blob/main/docs/guide/what-we-collect.md).
|
|
91
|
+
|
|
92
|
+
## Documentation
|
|
93
|
+
|
|
94
|
+
Full docs: https://github.com/Amalmktk/react-render-pulse/tree/main/docs
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
MIT © Amal M
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AreaReport, LongTaskEvent, LongTaskReport, RenderEvent, SessionSummary } from "../types.cjs";
|
|
2
|
+
export interface AggregatorOptions {
|
|
3
|
+
/** Renders slower than this count as slow. */
|
|
4
|
+
slowRenderMs: number;
|
|
5
|
+
/** Most distinct area/route pairs kept per batch; renders for new ones past this are dropped. */
|
|
6
|
+
maxAreas: number;
|
|
7
|
+
/** How many of the slowest renders to keep per area. */
|
|
8
|
+
worstCases: number;
|
|
9
|
+
/** `performance.now()` at session start, so worst cases report time since then. */
|
|
10
|
+
sessionStart: number;
|
|
11
|
+
}
|
|
12
|
+
export interface AggregatedBatch {
|
|
13
|
+
summary: SessionSummary;
|
|
14
|
+
areas: AreaReport[];
|
|
15
|
+
longTasks: LongTaskReport[];
|
|
16
|
+
longFrames: LongTaskReport[];
|
|
17
|
+
droppedAreas: number;
|
|
18
|
+
}
|
|
19
|
+
export interface Aggregator {
|
|
20
|
+
addRender: (event: RenderEvent) => void;
|
|
21
|
+
addLongTask: (event: LongTaskEvent) => void;
|
|
22
|
+
/** True when nothing was recorded since the last `drain()`. */
|
|
23
|
+
isEmpty: () => boolean;
|
|
24
|
+
/** Returns everything recorded since the last call, and starts a new batch. */
|
|
25
|
+
drain: () => AggregatedBatch;
|
|
26
|
+
}
|
|
27
|
+
export declare function createAggregator(options: AggregatorOptions): Aggregator;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AreaReport, LongTaskEvent, LongTaskReport, RenderEvent, SessionSummary } from "../types.js";
|
|
2
|
+
export interface AggregatorOptions {
|
|
3
|
+
/** Renders slower than this count as slow. */
|
|
4
|
+
slowRenderMs: number;
|
|
5
|
+
/** Most distinct area/route pairs kept per batch; renders for new ones past this are dropped. */
|
|
6
|
+
maxAreas: number;
|
|
7
|
+
/** How many of the slowest renders to keep per area. */
|
|
8
|
+
worstCases: number;
|
|
9
|
+
/** `performance.now()` at session start, so worst cases report time since then. */
|
|
10
|
+
sessionStart: number;
|
|
11
|
+
}
|
|
12
|
+
export interface AggregatedBatch {
|
|
13
|
+
summary: SessionSummary;
|
|
14
|
+
areas: AreaReport[];
|
|
15
|
+
longTasks: LongTaskReport[];
|
|
16
|
+
longFrames: LongTaskReport[];
|
|
17
|
+
droppedAreas: number;
|
|
18
|
+
}
|
|
19
|
+
export interface Aggregator {
|
|
20
|
+
addRender: (event: RenderEvent) => void;
|
|
21
|
+
addLongTask: (event: LongTaskEvent) => void;
|
|
22
|
+
/** True when nothing was recorded since the last `drain()`. */
|
|
23
|
+
isEmpty: () => boolean;
|
|
24
|
+
/** Returns everything recorded since the last call, and starts a new batch. */
|
|
25
|
+
drain: () => AggregatedBatch;
|
|
26
|
+
}
|
|
27
|
+
export declare function createAggregator(options: AggregatorOptions): Aggregator;
|
|
28
|
+
//# sourceMappingURL=aggregator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregator.d.ts","sourceRoot":"","sources":["../../src/aggregate/aggregator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAa,MAAM,aAAa,CAAC;AAErH,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,iGAAiG;IACjG,QAAQ,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACxC,WAAW,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC5C,+DAA+D;IAC/D,OAAO,EAAE,MAAM,OAAO,CAAC;IACvB,+EAA+E;IAC/E,KAAK,EAAE,MAAM,eAAe,CAAC;CAC9B;AAyBD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAoGvE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upper bounds (ms, inclusive) of the render-duration histogram buckets, plus
|
|
3
|
+
* an implicit overflow bucket. Part of payload v1: the collector merges
|
|
4
|
+
* histograms by index, so changing these needs a new payload version.
|
|
5
|
+
*/
|
|
6
|
+
export declare const HISTOGRAM_BOUNDS: readonly [1, 2, 4, 8, 12, 16, 24, 33, 50, 75, 100, 150, 250, 500, 1000];
|
|
7
|
+
export declare function createHistogram(): number[];
|
|
8
|
+
export declare function bucketIndex(ms: number): number;
|
|
9
|
+
/**
|
|
10
|
+
* Estimates a percentile (0–100) from bucket counts, interpolating linearly
|
|
11
|
+
* inside the bucket. The observed `min` and `max` narrow the bucket's range
|
|
12
|
+
* (every value lies between them): without them, durations clustered at a
|
|
13
|
+
* bucket edge, like many renders of exactly 8 ms, would be estimated from
|
|
14
|
+
* the bucket's middle instead.
|
|
15
|
+
*/
|
|
16
|
+
export declare function histogramPercentile(hist: readonly number[], p: number, max: number, min?: number): number;
|
|
17
|
+
/** Rounds to 0.1 ms: finer precision isn't meaningful and costs payload bytes. */
|
|
18
|
+
export declare function round(ms: number): number;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upper bounds (ms, inclusive) of the render-duration histogram buckets, plus
|
|
3
|
+
* an implicit overflow bucket. Part of payload v1: the collector merges
|
|
4
|
+
* histograms by index, so changing these needs a new payload version.
|
|
5
|
+
*/
|
|
6
|
+
export declare const HISTOGRAM_BOUNDS: readonly [1, 2, 4, 8, 12, 16, 24, 33, 50, 75, 100, 150, 250, 500, 1000];
|
|
7
|
+
export declare function createHistogram(): number[];
|
|
8
|
+
export declare function bucketIndex(ms: number): number;
|
|
9
|
+
/**
|
|
10
|
+
* Estimates a percentile (0–100) from bucket counts, interpolating linearly
|
|
11
|
+
* inside the bucket. The observed `min` and `max` narrow the bucket's range
|
|
12
|
+
* (every value lies between them): without them, durations clustered at a
|
|
13
|
+
* bucket edge, like many renders of exactly 8 ms, would be estimated from
|
|
14
|
+
* the bucket's middle instead.
|
|
15
|
+
*/
|
|
16
|
+
export declare function histogramPercentile(hist: readonly number[], p: number, max: number, min?: number): number;
|
|
17
|
+
/** Rounds to 0.1 ms: finer precision isn't meaningful and costs payload bytes. */
|
|
18
|
+
export declare function round(ms: number): number;
|
|
19
|
+
//# sourceMappingURL=histogram.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"histogram.d.ts","sourceRoot":"","sources":["../../src/aggregate/histogram.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,YAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAU,CAAC;AAExG,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAK9C;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,SAAI,GAAG,MAAM,CAsBpG;AAED,kFAAkF;AAClF,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAExC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export interface RenderMonitorProps {
|
|
3
|
+
/** Names this area in reports, e.g. `"orders-table"`. Areas with the same id are reported together. */
|
|
4
|
+
id: string;
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Measures the renders of its children and reports them under `id`.
|
|
9
|
+
*
|
|
10
|
+
* The tree it renders is the same in every mode and whether or not the
|
|
11
|
+
* session is sampled (a `<Profiler>` around two empty marker components), so
|
|
12
|
+
* switching modes or calling `initRenderPulse` late never remounts children.
|
|
13
|
+
* - Profiling mode: React's `<Profiler>` reports each commit's actual render time.
|
|
14
|
+
* - Lightweight mode: the time between the start and end markers rendering,
|
|
15
|
+
* which brackets the children's render. Updates that start below this area
|
|
16
|
+
* (a child's own state change) don't re-render the markers, so they aren't
|
|
17
|
+
* seen; profiling mode catches those.
|
|
18
|
+
*/
|
|
19
|
+
export declare function RenderMonitor({ id, children }: RenderMonitorProps): ReactNode;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export interface RenderMonitorProps {
|
|
3
|
+
/** Names this area in reports, e.g. `"orders-table"`. Areas with the same id are reported together. */
|
|
4
|
+
id: string;
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Measures the renders of its children and reports them under `id`.
|
|
9
|
+
*
|
|
10
|
+
* The tree it renders is the same in every mode and whether or not the
|
|
11
|
+
* session is sampled (a `<Profiler>` around two empty marker components), so
|
|
12
|
+
* switching modes or calling `initRenderPulse` late never remounts children.
|
|
13
|
+
* - Profiling mode: React's `<Profiler>` reports each commit's actual render time.
|
|
14
|
+
* - Lightweight mode: the time between the start and end markers rendering,
|
|
15
|
+
* which brackets the children's render. Updates that start below this area
|
|
16
|
+
* (a child's own state change) don't re-render the markers, so they aren't
|
|
17
|
+
* seen; profiling mode catches those.
|
|
18
|
+
*/
|
|
19
|
+
export declare function RenderMonitor({ id, children }: RenderMonitorProps): ReactNode;
|
|
20
|
+
//# sourceMappingURL=RenderMonitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RenderMonitor.d.ts","sourceRoot":"","sources":["../../src/components/RenderMonitor.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAgE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAKrG,MAAM,WAAW,kBAAkB;IACjC,uGAAuG;IACvG,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAoBD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,kBAAkB,GAAG,SAAS,CAyB7E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../src/context/device.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AASjD,wBAAgB,gBAAgB,IAAI,aAAa,CAShD"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Default route reader: the path with numeric segments replaced, so `/orders/42` and `/orders/7` group together. */
|
|
2
|
+
export declare function defaultGetRoute(): string;
|
|
3
|
+
/**
|
|
4
|
+
* Wraps a route reader so it only runs when the URL changes, since it's
|
|
5
|
+
* called on every measured render.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createRouteReader(getRoute: () => string): () => string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Default route reader: the path with numeric segments replaced, so `/orders/42` and `/orders/7` group together. */
|
|
2
|
+
export declare function defaultGetRoute(): string;
|
|
3
|
+
/**
|
|
4
|
+
* Wraps a route reader so it only runs when the URL changes, since it's
|
|
5
|
+
* called on every measured render.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createRouteReader(getRoute: () => string): () => string;
|
|
8
|
+
//# sourceMappingURL=route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../src/context/route.ts"],"names":[],"mappings":"AAAA,qHAAqH;AACrH,wBAAgB,eAAe,IAAI,MAAM,CAGxC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,MAAM,GAAG,MAAM,MAAM,CAYtE"}
|
package/dist/core.cjs
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
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
|
+
// src/core.ts
|
|
21
|
+
var core_exports = {};
|
|
22
|
+
__export(core_exports, {
|
|
23
|
+
HISTOGRAM_BOUNDS: () => HISTOGRAM_BOUNDS,
|
|
24
|
+
histogramPercentile: () => histogramPercentile
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(core_exports);
|
|
27
|
+
|
|
28
|
+
// src/aggregate/histogram.ts
|
|
29
|
+
var HISTOGRAM_BOUNDS = [1, 2, 4, 8, 12, 16, 24, 33, 50, 75, 100, 150, 250, 500, 1e3];
|
|
30
|
+
function histogramPercentile(hist, p, max, min = 0) {
|
|
31
|
+
const total = hist.reduce((sum, n) => sum + n, 0);
|
|
32
|
+
if (total === 0) return 0;
|
|
33
|
+
const target = Math.max(p / 100 * total, Number.MIN_VALUE);
|
|
34
|
+
let seen = 0;
|
|
35
|
+
for (let i = 0; i < hist.length; i++) {
|
|
36
|
+
const count = hist[i] ?? 0;
|
|
37
|
+
if (count === 0) continue;
|
|
38
|
+
if (seen + count >= target) {
|
|
39
|
+
const upper = Math.min(HISTOGRAM_BOUNDS[i] ?? max, max);
|
|
40
|
+
const lower = Math.min(Math.max(i === 0 ? 0 : HISTOGRAM_BOUNDS[i - 1] ?? 0, min), upper);
|
|
41
|
+
const fraction = (target - seen) / count;
|
|
42
|
+
return round(Math.min(lower + (upper - lower) * fraction, max));
|
|
43
|
+
}
|
|
44
|
+
seen += count;
|
|
45
|
+
}
|
|
46
|
+
return round(max);
|
|
47
|
+
}
|
|
48
|
+
function round(ms) {
|
|
49
|
+
return Math.round(ms * 10) / 10;
|
|
50
|
+
}
|
|
51
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
52
|
+
0 && (module.exports = {
|
|
53
|
+
HISTOGRAM_BOUNDS,
|
|
54
|
+
histogramPercentile
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=core.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core.ts","../src/aggregate/histogram.ts"],"sourcesContent":["// Framework-agnostic entry: no React imports, so it's safe in Server Components,\n// route handlers, and plain Node. Everything here is also exported from the main entry.\nexport type {\n AreaReport,\n DeviceContext,\n Exporter,\n LongTaskEvent,\n LongTaskKind,\n LongTaskReport,\n Mode,\n ModeOption,\n Payload,\n RenderEvent,\n RenderPhase,\n SessionInfo,\n SessionSummary,\n WorstCase,\n} from \"./types.js\";\nexport { HISTOGRAM_BOUNDS, histogramPercentile } from \"./aggregate/histogram.js\";\n","/**\n * Upper bounds (ms, inclusive) of the render-duration histogram buckets, plus\n * an implicit overflow bucket. Part of payload v1: the collector merges\n * histograms by index, so changing these needs a new payload version.\n */\nexport const HISTOGRAM_BOUNDS = [1, 2, 4, 8, 12, 16, 24, 33, 50, 75, 100, 150, 250, 500, 1000] as const;\n\nexport function createHistogram(): number[] {\n return new Array<number>(HISTOGRAM_BOUNDS.length + 1).fill(0);\n}\n\nexport function bucketIndex(ms: number): number {\n for (let i = 0; i < HISTOGRAM_BOUNDS.length; i++) {\n if (ms <= (HISTOGRAM_BOUNDS[i] ?? 0)) return i;\n }\n return HISTOGRAM_BOUNDS.length;\n}\n\n/**\n * Estimates a percentile (0–100) from bucket counts, interpolating linearly\n * inside the bucket. The observed `min` and `max` narrow the bucket's range\n * (every value lies between them): without them, durations clustered at a\n * bucket edge, like many renders of exactly 8 ms, would be estimated from\n * the bucket's middle instead.\n */\nexport function histogramPercentile(hist: readonly number[], p: number, max: number, min = 0): number {\n const total = hist.reduce((sum, n) => sum + n, 0);\n if (total === 0) return 0;\n\n const target = Math.max((p / 100) * total, Number.MIN_VALUE);\n let seen = 0;\n\n for (let i = 0; i < hist.length; i++) {\n const count = hist[i] ?? 0;\n if (count === 0) continue;\n\n if (seen + count >= target) {\n const upper = Math.min(HISTOGRAM_BOUNDS[i] ?? max, max);\n const lower = Math.min(Math.max(i === 0 ? 0 : (HISTOGRAM_BOUNDS[i - 1] ?? 0), min), upper);\n const fraction = (target - seen) / count;\n return round(Math.min(lower + (upper - lower) * fraction, max));\n }\n\n seen += count;\n }\n\n return round(max);\n}\n\n/** Rounds to 0.1 ms: finer precision isn't meaningful and costs payload bytes. */\nexport function round(ms: number): number {\n return Math.round(ms * 10) / 10;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACKO,IAAM,mBAAmB,CAAC,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,KAAK,KAAK,KAAK,GAAI;AAoBtF,SAAS,oBAAoB,MAAyB,GAAW,KAAa,MAAM,GAAW;AACpG,QAAM,QAAQ,KAAK,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC;AAChD,MAAI,UAAU,EAAG,QAAO;AAExB,QAAM,SAAS,KAAK,IAAK,IAAI,MAAO,OAAO,OAAO,SAAS;AAC3D,MAAI,OAAO;AAEX,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,QAAQ,KAAK,CAAC,KAAK;AACzB,QAAI,UAAU,EAAG;AAEjB,QAAI,OAAO,SAAS,QAAQ;AAC1B,YAAM,QAAQ,KAAK,IAAI,iBAAiB,CAAC,KAAK,KAAK,GAAG;AACtD,YAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,MAAM,IAAI,IAAK,iBAAiB,IAAI,CAAC,KAAK,GAAI,GAAG,GAAG,KAAK;AACzF,YAAM,YAAY,SAAS,QAAQ;AACnC,aAAO,MAAM,KAAK,IAAI,SAAS,QAAQ,SAAS,UAAU,GAAG,CAAC;AAAA,IAChE;AAEA,YAAQ;AAAA,EACV;AAEA,SAAO,MAAM,GAAG;AAClB;AAGO,SAAS,MAAM,IAAoB;AACxC,SAAO,KAAK,MAAM,KAAK,EAAE,IAAI;AAC/B;","names":[]}
|
package/dist/core.d.cts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export type { AreaReport, DeviceContext, Exporter, LongTaskEvent, LongTaskKind, LongTaskReport, Mode, ModeOption, Payload, RenderEvent, RenderPhase, SessionInfo, SessionSummary, WorstCase, } from "./types.cjs";
|
|
2
|
+
export { HISTOGRAM_BOUNDS, histogramPercentile } from "./aggregate/histogram.cjs";
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export type { AreaReport, DeviceContext, Exporter, LongTaskEvent, LongTaskKind, LongTaskReport, Mode, ModeOption, Payload, RenderEvent, RenderPhase, SessionInfo, SessionSummary, WorstCase, } from "./types.js";
|
|
2
|
+
export { HISTOGRAM_BOUNDS, histogramPercentile } from "./aggregate/histogram.js";
|
|
3
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,UAAU,EACV,aAAa,EACb,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,cAAc,EACd,IAAI,EACJ,UAAU,EACV,OAAO,EACP,WAAW,EACX,WAAW,EACX,WAAW,EACX,cAAc,EACd,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/core.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// src/aggregate/histogram.ts
|
|
2
|
+
var HISTOGRAM_BOUNDS = [1, 2, 4, 8, 12, 16, 24, 33, 50, 75, 100, 150, 250, 500, 1e3];
|
|
3
|
+
function histogramPercentile(hist, p, max, min = 0) {
|
|
4
|
+
const total = hist.reduce((sum, n) => sum + n, 0);
|
|
5
|
+
if (total === 0) return 0;
|
|
6
|
+
const target = Math.max(p / 100 * total, Number.MIN_VALUE);
|
|
7
|
+
let seen = 0;
|
|
8
|
+
for (let i = 0; i < hist.length; i++) {
|
|
9
|
+
const count = hist[i] ?? 0;
|
|
10
|
+
if (count === 0) continue;
|
|
11
|
+
if (seen + count >= target) {
|
|
12
|
+
const upper = Math.min(HISTOGRAM_BOUNDS[i] ?? max, max);
|
|
13
|
+
const lower = Math.min(Math.max(i === 0 ? 0 : HISTOGRAM_BOUNDS[i - 1] ?? 0, min), upper);
|
|
14
|
+
const fraction = (target - seen) / count;
|
|
15
|
+
return round(Math.min(lower + (upper - lower) * fraction, max));
|
|
16
|
+
}
|
|
17
|
+
seen += count;
|
|
18
|
+
}
|
|
19
|
+
return round(max);
|
|
20
|
+
}
|
|
21
|
+
function round(ms) {
|
|
22
|
+
return Math.round(ms * 10) / 10;
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
HISTOGRAM_BOUNDS,
|
|
26
|
+
histogramPercentile
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=core.js.map
|
package/dist/core.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/aggregate/histogram.ts"],"sourcesContent":["/**\n * Upper bounds (ms, inclusive) of the render-duration histogram buckets, plus\n * an implicit overflow bucket. Part of payload v1: the collector merges\n * histograms by index, so changing these needs a new payload version.\n */\nexport const HISTOGRAM_BOUNDS = [1, 2, 4, 8, 12, 16, 24, 33, 50, 75, 100, 150, 250, 500, 1000] as const;\n\nexport function createHistogram(): number[] {\n return new Array<number>(HISTOGRAM_BOUNDS.length + 1).fill(0);\n}\n\nexport function bucketIndex(ms: number): number {\n for (let i = 0; i < HISTOGRAM_BOUNDS.length; i++) {\n if (ms <= (HISTOGRAM_BOUNDS[i] ?? 0)) return i;\n }\n return HISTOGRAM_BOUNDS.length;\n}\n\n/**\n * Estimates a percentile (0–100) from bucket counts, interpolating linearly\n * inside the bucket. The observed `min` and `max` narrow the bucket's range\n * (every value lies between them): without them, durations clustered at a\n * bucket edge, like many renders of exactly 8 ms, would be estimated from\n * the bucket's middle instead.\n */\nexport function histogramPercentile(hist: readonly number[], p: number, max: number, min = 0): number {\n const total = hist.reduce((sum, n) => sum + n, 0);\n if (total === 0) return 0;\n\n const target = Math.max((p / 100) * total, Number.MIN_VALUE);\n let seen = 0;\n\n for (let i = 0; i < hist.length; i++) {\n const count = hist[i] ?? 0;\n if (count === 0) continue;\n\n if (seen + count >= target) {\n const upper = Math.min(HISTOGRAM_BOUNDS[i] ?? max, max);\n const lower = Math.min(Math.max(i === 0 ? 0 : (HISTOGRAM_BOUNDS[i - 1] ?? 0), min), upper);\n const fraction = (target - seen) / count;\n return round(Math.min(lower + (upper - lower) * fraction, max));\n }\n\n seen += count;\n }\n\n return round(max);\n}\n\n/** Rounds to 0.1 ms: finer precision isn't meaningful and costs payload bytes. */\nexport function round(ms: number): number {\n return Math.round(ms * 10) / 10;\n}\n"],"mappings":";AAKO,IAAM,mBAAmB,CAAC,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK,KAAK,KAAK,KAAK,GAAI;AAoBtF,SAAS,oBAAoB,MAAyB,GAAW,KAAa,MAAM,GAAW;AACpG,QAAM,QAAQ,KAAK,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC;AAChD,MAAI,UAAU,EAAG,QAAO;AAExB,QAAM,SAAS,KAAK,IAAK,IAAI,MAAO,OAAO,OAAO,SAAS;AAC3D,MAAI,OAAO;AAEX,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,QAAQ,KAAK,CAAC,KAAK;AACzB,QAAI,UAAU,EAAG;AAEjB,QAAI,OAAO,SAAS,QAAQ;AAC1B,YAAM,QAAQ,KAAK,IAAI,iBAAiB,CAAC,KAAK,KAAK,GAAG;AACtD,YAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,MAAM,IAAI,IAAK,iBAAiB,IAAI,CAAC,KAAK,GAAI,GAAG,GAAG,KAAK;AACzF,YAAM,YAAY,SAAS,QAAQ;AACnC,aAAO,MAAM,KAAK,IAAI,SAAS,QAAQ,SAAS,UAAU,GAAG,CAAC;AAAA,IAChE;AAEA,YAAQ;AAAA,EACV;AAEA,SAAO,MAAM,GAAG;AAClB;AAGO,SAAS,MAAM,IAAoB;AACxC,SAAO,KAAK,MAAM,KAAK,EAAE,IAAI;AAC/B;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/export/console.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,qHAAqH;AACrH,wBAAgB,qBAAqB,IAAI,QAAQ,CA2BhD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Exporter } from "../types.cjs";
|
|
2
|
+
type Attributes = Record<string, string | number | boolean>;
|
|
3
|
+
/**
|
|
4
|
+
* The parts of an OpenTelemetry `Meter` this exporter uses. Structurally
|
|
5
|
+
* compatible with `@opentelemetry/api`'s `Meter`, so there's no dependency on it.
|
|
6
|
+
*/
|
|
7
|
+
export interface OtelMeterLike {
|
|
8
|
+
createHistogram: (name: string, options?: {
|
|
9
|
+
description?: string;
|
|
10
|
+
unit?: string;
|
|
11
|
+
}) => {
|
|
12
|
+
record: (value: number, attributes?: Attributes) => void;
|
|
13
|
+
};
|
|
14
|
+
createCounter: (name: string, options?: {
|
|
15
|
+
description?: string;
|
|
16
|
+
unit?: string;
|
|
17
|
+
}) => {
|
|
18
|
+
add: (value: number, attributes?: Attributes) => void;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export interface OtelExporterOptions {
|
|
22
|
+
/** e.g. `metrics.getMeter("my-app")` from `@opentelemetry/api`. */
|
|
23
|
+
meter: OtelMeterLike;
|
|
24
|
+
/** Renders slower than this also increment `render_pulse.render.slow`. Defaults to 16. */
|
|
25
|
+
slowRenderMs?: number | undefined;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Records every measurement as OpenTelemetry metrics:
|
|
29
|
+
* - `render_pulse.render.duration` (histogram, ms) with `render_pulse.area`, `render_pulse.route`, `render_pulse.phase`, `render_pulse.mode`
|
|
30
|
+
* - `render_pulse.render.slow` (counter) with the same attributes
|
|
31
|
+
* - `render_pulse.longtask.duration` (histogram, ms) with `render_pulse.area`, `render_pulse.route`, `render_pulse.kind`
|
|
32
|
+
*/
|
|
33
|
+
export declare function createOtelExporter(options: OtelExporterOptions): Exporter;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Exporter } from "../types.js";
|
|
2
|
+
type Attributes = Record<string, string | number | boolean>;
|
|
3
|
+
/**
|
|
4
|
+
* The parts of an OpenTelemetry `Meter` this exporter uses. Structurally
|
|
5
|
+
* compatible with `@opentelemetry/api`'s `Meter`, so there's no dependency on it.
|
|
6
|
+
*/
|
|
7
|
+
export interface OtelMeterLike {
|
|
8
|
+
createHistogram: (name: string, options?: {
|
|
9
|
+
description?: string;
|
|
10
|
+
unit?: string;
|
|
11
|
+
}) => {
|
|
12
|
+
record: (value: number, attributes?: Attributes) => void;
|
|
13
|
+
};
|
|
14
|
+
createCounter: (name: string, options?: {
|
|
15
|
+
description?: string;
|
|
16
|
+
unit?: string;
|
|
17
|
+
}) => {
|
|
18
|
+
add: (value: number, attributes?: Attributes) => void;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export interface OtelExporterOptions {
|
|
22
|
+
/** e.g. `metrics.getMeter("my-app")` from `@opentelemetry/api`. */
|
|
23
|
+
meter: OtelMeterLike;
|
|
24
|
+
/** Renders slower than this also increment `render_pulse.render.slow`. Defaults to 16. */
|
|
25
|
+
slowRenderMs?: number | undefined;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Records every measurement as OpenTelemetry metrics:
|
|
29
|
+
* - `render_pulse.render.duration` (histogram, ms) with `render_pulse.area`, `render_pulse.route`, `render_pulse.phase`, `render_pulse.mode`
|
|
30
|
+
* - `render_pulse.render.slow` (counter) with the same attributes
|
|
31
|
+
* - `render_pulse.longtask.duration` (histogram, ms) with `render_pulse.area`, `render_pulse.route`, `render_pulse.kind`
|
|
32
|
+
*/
|
|
33
|
+
export declare function createOtelExporter(options: OtelExporterOptions): Exporter;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=otel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel.d.ts","sourceRoot":"","sources":["../../src/export/otel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAE5D;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,CACf,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAC9C;QAAE,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;KAAE,CAAC;IAClE,aAAa,EAAE,CACb,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAC9C;QAAE,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;KAAE,CAAC;CAChE;AAED,MAAM,WAAW,mBAAmB;IAClC,mEAAmE;IACnE,KAAK,EAAE,aAAa,CAAC;IACrB,0FAA0F;IAC1F,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,QAAQ,CAkCzE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tracks the renders of the component that calls it, reported under `id`.
|
|
3
|
+
*
|
|
4
|
+
* Render counts are exact. The duration runs from the hook's call to the
|
|
5
|
+
* commit, so it also includes anything React renders after this component
|
|
6
|
+
* in the same update: an upper bound. Wrap the component in `<RenderMonitor>`
|
|
7
|
+
* when you need its own render time.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useRenderMonitor(id: string): void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tracks the renders of the component that calls it, reported under `id`.
|
|
3
|
+
*
|
|
4
|
+
* Render counts are exact. The duration runs from the hook's call to the
|
|
5
|
+
* commit, so it also includes anything React renders after this component
|
|
6
|
+
* in the same update: an upper bound. Wrap the component in `<RenderMonitor>`
|
|
7
|
+
* when you need its own render time.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useRenderMonitor(id: string): void;
|
|
10
|
+
//# sourceMappingURL=useRenderMonitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRenderMonitor.d.ts","sourceRoot":"","sources":["../../src/hooks/useRenderMonitor.ts"],"names":[],"mappings":"AAOA;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAgBjD"}
|